4

Could someone explain how to use an interpolation function on an existing array, in python as the one exists in matlab ?

example:

x =

 1
 2
 3
 4
 5
 6
 7
 8
 9
10

interp(x,2)

ans =

1.0000
1.4996
2.0000
2.4993
3.0000
3.4990
4.0000
4.4987
5.0000
5.4984
6.0000
6.4982
7.0000
7.4979
8.0000
8.4976
9.0000
9.4973
10.0000
10.4970

I'd like a function in python which does exactly this, i.e. adds more points keeping the original intact.

Hugh Bothwell
  • 55,315
  • 8
  • 84
  • 99
Archis
  • 41
  • 1
  • 2

2 Answers2

1

A couple of issues need to be raised:

  • Are you just looking at linear interpolation (ie "connect the dots" with straight line segments)? That's simple but kind of nasty. You can get nicer results with higher-order curves (ie bicubic splines) but for that you need to provide more information to nail down a unique solution (ie endpoint first-derivatives).

  • Do you want to smooth the curve at the same time, or do you expect it to go exactly through your given points?

  • Are your input points uniformly spaced (ie along the x axis)?

  • Your data shows not just interpolation but also extrapolation (ie your last point is off the end of your data) - is this actually what you want?

Matlab documentation says "interp inserts 0s into the original signal and then applies a lowpass interpolating filter to the expanded sequence".


Edit: I think the closest equivalent is scipy.interpolate.interp1d - see http://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.interp1d.html#scipy.interpolate.interp1d

You could make a wrapper like so:

import numpy as np
from scipy.interpolate import interp1d

def interp(ys, mul):
    # linear extrapolation for last (mul - 1) points
    ys = list(ys)
    ys.append(2*ys[-1] - ys[-2])
    # make interpolation function
    xs = np.arange(len(ys))
    fn = interp1d(xs, ys, kind="cubic")
    # call it on desired data points
    new_xs = np.arange(len(ys) - 1, step=1./mul)
    return fn(new_xs)

which then works like

>>> interp([1,2,3,4,5,6,7,8,9,10], 2)
array([  1. ,   1.5,   2. ,   2.5,   3. ,   3.5,   4. ,   4.5,   5. ,
         5.5,   6. ,   6.5,   7. ,   7.5,   8. ,   8.5,   9. ,   9.5,
        10. ,  10.5])
Hugh Bothwell
  • 55,315
  • 8
  • 84
  • 99
  • Yes my input points are uniformly spaced. I just want to add more points uniformly in between what already exists. For example if my data goes 1,1.5,2,2.5... I would want 1,1.25,1.5,1.75,2,2.25,2.50... Note that my original points exist and I just have added more points here. I don't care about extrapolation. My objective is to get more values on the independent axis so that I can smooth a function better. I cannot use arbitrary generators like linspace since my x values are already specified. – Archis Apr 12 '14 at 02:27
  • @Archis: see the wrapper function I just added. You can change the interpolation function used by specifying `interp1d(kind=)`; it is currently using a piecewise cubic spline. – Hugh Bothwell Apr 13 '14 at 14:02
  • @HughBothwell : I wanted to use interp2 function of matlab for a closed contour. Which python function shall I use? – Gunjan naik Aug 26 '15 at 05:23
0

You can get the results similar to Matlab's interp() function for example like this:

def interpolate_1d_vector(vector, factor):
    """
    Interpolate, i.e. upsample, a given 1D vector by a specific interpolation factor.
    :param vector: 1D data vector
    :param factor: factor for interpolation (must be integer)
    :return: interpolated 1D vector by a given factor
    """
    x = np.arange(np.size(vector))
    y = vector
    f = scipy.interpolate.interp1d(x, y)

    x_extended_by_factor = np.linspace(x[0], x[-1], np.size(x) * factor)
    y_interpolated = np.zeros(np.size(x_extended_by_factor))

    i = 0
    for x in x_extended_by_factor:
        y_interpolated[i] = f(x)
        i += 1

    return y_interpolated
bluevoxel
  • 4,978
  • 11
  • 45
  • 63