Python has good interpolation tools, but the right function depends on what you need: linear or smooth, one or two dimensions, and whether you will query outside your data. This guide covers the functions worth using and the traps in each.
Linear: numpy.interp
import numpy as np
xp = [0, 10, 20, 30]
fp = [0, 15.2, 28.9, 39.7]
np.interp(17.5, xp, fp) # 25.475
np.interp([5, 25], xp, fp) # array([ 7.6 , 34.3])
- Fast, simple, and vectorised over many x values.
xpmust be increasing. NumPy does not check this, and unsorted input silently gives wrong results.- Outside the data it does not extrapolate. It returns the first or last y value (or
left/rightif you pass them). Passleft=np.nan, right=np.nanto make out-of-range queries obvious.
Smooth curves: scipy.interpolate.CubicSpline
from scipy.interpolate import CubicSpline
cs = CubicSpline(x, y, bc_type="natural")
cs(2.5) # value
cs(2.5, 1) # first derivative
bc_type="natural"sets the second derivative to zero at both ends, which matches the cubic spline calculator on this site. The SciPy default is"not-a-knot", so results near the ends will differ slightly unless you set it.- By default it extrapolates using the end polynomials. Pass
extrapolate=Falseto get NaN outside the data. - x must be strictly increasing, with no duplicates.
make_interp_spline(x, y, k=3) is the more general B-spline interface. Use k=1 for linear and k=3 for cubic.
Polynomial through points: lagrange and BarycentricInterpolator
scipy.interpolate.lagrange(x, y) returns the interpolating polynomial as a numpy.poly1d, which is handy for small examples and teaching. SciPy's documentation warns it is numerically unstable beyond about 20 points. For evaluating a high-degree interpolant reliably, use BarycentricInterpolator. And remember that a single high-degree polynomial is often the wrong tool anyway (see choosing a method).
2D and gridded data: RegularGridInterpolator
from scipy.interpolate import RegularGridInterpolator
pressures = [1.0, 1.2] # MPa
temps = [200, 250] # °C
h = [[2828.3, 2943.1],
[2816.1, 2935.6]] # h[pressure][temp]
f = RegularGridInterpolator((pressures, temps), h)
f([1.1, 220]) # array([2869.06])
With the default method="linear" this is bilinear interpolation in 2D, and it works the same way in 3D and above. Out-of-range points raise an error by default (bounds_error=True). For scattered, non-grid points, use griddata or LinearNDInterpolator.
Filling gaps in a series: pandas
s.interpolate() # linear, treats rows as equally spaced
s.interpolate(method="index") # uses the index values as x
s.interpolate(method="time") # for a DatetimeIndex
The default method="linear" ignores the index and assumes the rows are evenly spaced. If your timestamps or x values are irregular, use "index" or "time", or the result is quietly wrong.
Which one to use
| Need | Use |
|---|---|
| Linear, 1D, fast | numpy.interp |
| Smooth curve, 1D | CubicSpline |
| Smooth but no overshoot | PchipInterpolator |
| Regular 2D/3D grid | RegularGridInterpolator |
| Scattered 2D points | griddata |
| Gaps in a time series | Series.interpolate(method="time") |
What about scipy.interpolate.interp1d?
interp1d still works, but SciPy marks it as legacy and recommends the functions above for new code: numpy.interp for linear, and CubicSpline or make_interp_spline for splines.
PCHIP: when a spline overshoots
A cubic spline can overshoot between points, for example dipping below zero when all your data is positive. PchipInterpolator builds a piecewise cubic that preserves the shape of the data. It never overshoots where the data is monotonic, at the cost of a slightly less smooth curve. Use it for physical quantities that must stay within bounds.