Jeddy Eastside
Jeddy Eastside

Reputation: 75

Interpolate list to quadruple length

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

Answers (2)

Booboo
Booboo

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

CDJB
CDJB

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

Related Questions