Reputation: 75
I need your help. So the aim is to interpolate between each element in a list to quadruple its length. So I do have a list, for example:
list = [1 ,5 ,2 ,6 ,8 ]
My desired outcome is:
new_list = [1 ,2 ,3 ,4 ,5 ,4.25 ,3.5 ,2.75, 2, 3, 4, 5, 6, 6.5, 7, 7.5 ,8 ,8 ,8 ,8 ].
I want to adopt the 5 elements of my list, interpolate inbetween each and therefore add 3 more values between the original ones. Because I can't interpolate the last value I simply want to add three more, in this case, 8s.
For a better understanding I have marked the original elements of the list bold. The normally printed elements of the new list are therefore the interpolated values between each pair. I hope I was able to express the question in a reasonably understandable way.
The code I tried is the follwing, which I also found here:
import sys
EPSILON = sys.float_info.epsilon # smallest possible difference
def print_list(values):
print('[' + ', '.join(format(value, '.3f') for value in values) + ']')
def interpolate(inp, fi):
i = int(fi)
f = fi - i
return (inp[i] if f < EPSILON else
inp[i] + f*(inp[i+1]-inp[i]))
inp = [1, 5, 2, 6, 8]
new_len = 20
delta = (len(inp)-1) / float(new_len-1)
outp = [interpolate(inp, i*delta) for i in range(new_len)]
print_list(inp)
print_list(outp)
The outcome is:
[1.000, 1.842, 2.684, 3.526, 4.368, 4.842, 4.211, 3.579, 2.947, 2.316, 2.421, 3.263, 4.105, 4.947, 5.789, 6.316, 6.737, 7.158, 7.579, 8.000]
The problem with the code is that the original elements are not adopted to the new list.
Upvotes: 0
Views: 236
Reputation: 44283
This function takes two arguments, a list and an expansion factor, which would be 4 in your example, and returns a new list. It's not very elegant, but I believe it does the job:
def interpolate(l, expansion_factor):
assert expansion_factor >= 1
new_l = l.copy()
if expansion_factor == 1:
return new_l
length = len(new_l)
i = length - 2
while i >= 0:
next = i + 1
value = new_l[next]
delta = (value - new_l[i]) / expansion_factor
for cnt in range(expansion_factor - 1):
value -= delta
if int(value) == value:
value = int(value)
new_l.insert(next, value)
i -= 1
# last element
value = new_l[-1]
for i in range(expansion_factor - 1):
new_l.append(value)
return new_l
print(interpolate([1, 5, 2, 6, 8], 4))
Prints:
[1, 2, 3, 4, 5, 4.25, 3.5, 2.75, 2, 3, 4, 5, 6, 6.5, 7, 7.5, 8, 8, 8, 8]
Upvotes: 1
Reputation: 14546
A useful tool for interpolating between two values is the linspace function. You can solve your problem by looping over your list and using this function to calculate the intermediate values. This eliminates the need for you to write your own interpolation function.
For example, to interpolate between 1 and 5, with 5 segments (including the beginning and the end):
>>> import numpy as np
>>> np.linspace(1,5,5)
array([1., 2., 3., 4., 5.])
Upvotes: 0