Reputation: 737
I'm looking for a way to create a "functor" for linear interpolation of time,value pairs using SciPy (or NumPy) but according to the SciPy tutorial there is none! (Kind of the opposite of Trying to understand scipy and numpy interpolation)
The natural method would be interp1d but that has a warning:
Legacy This class is considered legacy and will no longer receive updates. […] For a guide to the intended replacements for interp1d see 1-D interpolation.
Following the link takes me to a page that tells me:
If all you need is a linear (a.k.a. broken line) interpolation, you can use the numpy.interp routine.
The problem is, these are not at all equivalent. numpy.interp
requires me to know the points beforehand, and does not return a function that can be used to look up the interpolated values.
Meanwhile, SciPy has a number of other interpolation methods that all return a function (or a function object) such as CubicSpline
or PchipInterpolator
.
What's the easy way to construct a function or object similar to what PchipInterpolator
returns, but for simple linear interpolation now that interp1d
is deprecated?
Upvotes: 1
Views: 267
Reputation: 9046
You can use scipy.interpolate.make_interp_spline
with k=1
for linear interpolation.
import numpy as np
from scipy.interpolate import make_interp_spline, interp1d
import matplotlib.pyplot as plt
plt.close("all")
x = np.linspace(0, 20, 10)
y = np.cos(x**2)/(x+1)
x_fine = np.linspace(0, 20, 100)
y_np = np.interp(x_fine, x, y)
f_sp1 = make_interp_spline(x, y, k=1)
y_sp1 = f_sp1(x_fine)
f_sp2 = interp1d(x, y)
y_sp2 = f_sp2(x_fine)
fig, ax = plt.subplots()
ax.plot(x, y, ".", label="Original")
ax.plot(x_fine, y_np, label="Numpy")
ax.plot(x_fine, y_sp1, label="Scipy (make_interp_spline)")
ax.plot(x_fine, y_sp2, label="Scipy (interp1d)")
ax.legend()
fig.show()
Upvotes: 2
Reputation: 518
Just wrap numpy.interp
in a function if you need to. Recreating the example in the official documentation using numpy.interp
:
import numpy as np
from scipy import interpolate
x = np.arange(0, 10)
y = np.exp(-x/3.0)
f1 = interpolate.interp1d(x, y)
def f2(i):
return np.interp(i, x, y)
xnew = np.arange(0, 9, 0.1)
np.isclose(f1(xnew), f2(xnew)) # Returns True
You may add the data points inside the function definition and construct "functors" for each case you have.
Alternatively:
from functools import partial
f2 = partial(np.interp, xp=x, fp=y)
You can even create a "functor", similar to scipy.interpolate.interp1d
:
from functools import partial
def interp1d(x, y):
return partial(np.interp, xp=x, fp=y)
f2 = interp1d(x, y)
Upvotes: 2