Reputation: 135
I want to increase the length of a list in python, whereas the missing values in between and on the right positions should be interpolated. Example:
[1, 3, 5, 7, 9]
interpolated to the new length of 10 would be:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
This is just the double size and can be solved with the following mathematical formula for interpolation, whereas every second value is interpolated:
y = y1 + ((y2 - y1) / (x2 - x1)) * (x - x1)
But I am trying to figure out, how to interpolate if the list with a length of 217 needs to be interpolated to a length of 240 for example.
Is there a library, which offers a function for this I don't know about? Or maybe someone can give me an example?
Edit: The data in the list is not linear. So a list like this is probable:
[4.534, 1.2433. 3.353, 2.3452, 6.124, 8.124, 1.232]
Upvotes: 7
Views: 11748
Reputation: 123501
A relatively simple way to do this is to map integer index values in the new list onto "fractional indices" in the original one, then use the fractional portion to linearly interpolate between the original list values represented by the integer portion of interpolated value and the following one (unless the fractional portion is zero).
For example, if the fractional index computed into the original list is 2.333..., then the resulting value would be 1⁄3 of the way between the values in original[2]
and original[3]
.
Here's sample code implementing the idea:
# For Python 2 compatibility.
from __future__ import division, print_function
def print_list(values):
print('[' + ', '.join(format(value, '.3f') for value in values) + ']')
def interpolate(inp, fi):
i, f = int(fi // 1), fi % 1 # Split floating-point index into whole & fractional parts.
j = i+1 if f > 0 else i # Avoid index error.
return (1-f) * inp[i] + f * inp[j]
inp = [1, 3, 5, 7, 9]
new_len = 10
delta = (len(inp)-1) / (new_len-1)
outp = [interpolate(inp, i*delta) for i in range(new_len)]
print_list(inp)
print_list(outp)
Output:
[1.000, 3.000, 5.000, 7.000, 9.000]
[1.000, 1.889, 2.778, 3.667, 4.556, 5.444, 6.333, 7.222, 8.111, 9.000]
Note: I do something similar to this in my answer to another, marginally-related, question (which includes a graphic that may help visualize the process).
Upvotes: 8
Reputation: 3570
Quoting Wikipedia:
interpolation is a method of constructing new data points within the range of a discrete set of known data points.
So traditionally interpolation is used to calculate new values of y for given x between known values of f(x1) and f(x2). Your formula is the formula for linear interpolation, which assumes at least linear behaviour between x1 and x2.
In your example, give a list with values, which you want to expand by interpolated values, so I assume they are your y-values:
[1, 3, 5, 7, 9]
What you are not giving are the corresponding x-values. According to your expected result, I assume they should be the same:
f(1)=1, f(3)=3
...
Now you extend your range to 10, which is a problem for classic linear interpolation, since you have no known upper f(x) to do your calculation.
Interpreting your expected result, you are assuming general linearity, which means the base function of your given y-values is globally linear and can be assumed to be f(x)=x
. If that is the case for your data, there is no need to calculate your formula for every point: calculate your linear function once (using any two different points) and use this to calculate any desired f(x).
If your target function is not globally linear, you cannot interpolate any values larger than your biggest f(x) or smaller than the smallest f(x) - and for any x inbetween you would not only need the f(x) values, but additionally the x-values that produced them.
Upvotes: 0