Interpolation, smoothing and integration
Fit a smooth curve through noisy samples, interpolate scattered data in many dimensions, and integrate functions you cannot solve analytically.
Interpolation
import numpy as np
from scipy import interpolate
x = np.linspace(0, 2 * np.pi, 20)
y = np.sin(x) + np.random.default_rng(0).normal(0, 0.05, x.size)
cs = interpolate.CubicSpline(x, y, bc_type="natural")
xs = np.linspace(x[0], x[-1], 400)
print(cs(xs).shape, float(cs.derivative()(np.pi)))
# smoothing instead of passing through every noisy point
spl = interpolate.UnivariateSpline(x, y, s=len(x) * 0.05)
# scattered data in 2D
pts = np.random.default_rng(1).random((200, 2))
vals = np.sin(pts[:, 0]) * np.cos(pts[:, 1])
rbf = interpolate.RBFInterpolator(pts, vals, kernel="thin_plate_spline", smoothing=1e-6)
print(rbf(np.array([[0.5, 0.5], [0.2, 0.8]])).shape)
# scattered samples onto a regular grid
gx, gy = np.meshgrid(np.linspace(0, 1, 50), np.linspace(0, 1, 50))
grid = interpolate.griddata(pts, vals, (gx, gy), method="cubic")| Method | Passes through data | Use when |
|---|---|---|
interp1d(kind="linear") | Yes | Fast, monotone-safe, no smoothness needed |
CubicSpline | Yes | Smooth curves, derivatives available |
UnivariateSpline with s | No | Data is noisy and you want a trend |
PchipInterpolator | Yes | Smooth but must not overshoot between points |
RBFInterpolator | Depends on smoothing | Scattered points in 2D or more |
griddata | Yes | Scattered points evaluated on a regular grid |
Integration
from scipy import integrate
area, err = integrate.quad(lambda t: np.exp(-t ** 2), 0, np.inf)
print(area, err) # sqrt(pi)/2 = 0.8862...
val, _ = integrate.quad(lambda t: np.log(t) / (1 + t ** 2), 0, 1, weight="alg", wvar=-0.5)
volume, _ = integrate.dblquad(lambda y, x: x * y, 0, 1, 0, lambda x: 1 - x)
# integrate sampled data rather than a function
t = np.linspace(0, 10, 500)
v = np.sin(t) + 0.3 * t
cum = integrate.cumulative_trapezoid(v, t, initial=0.0)
print(cum[-1] - cum[0])quadreturns the estimate and an absolute error estimate; ignore the second value at your peril.- For sampled data use
trapezoidorsimpson; for a callable usequad. They are not interchangeable. - Infinite bounds are allowed and handled by a transformation, so
quad(f, 0, np.inf)is legitimate. cumulative_trapezoidwithinitial=0returns an array the same length as the input, which is what plotting usually wants.
Choosing between methods
Interpolation choices trade smoothness against overshoot. A cubic spline is smooth but can swing past your data points; a PCHIP interpolant is monotone and will not overshoot, which matters when the interpolated values are physical quantities such as concentrations.
⚠️
Extrapolation is the classic trap.
interp1d and CubicSpline happily evaluate outside the fitted range, returning confident nonsense. Pass extrapolate=False to get NaN instead of a plausible wrong answer, or bound your evaluation to the ends of the data.FAQ
My interpolated curve oscillates wildly between points. Why?
You are interpolating too high a degree through noisy or unevenly spaced data. Use PCHIP, reduce to a smoothing spline, or fit a model rather than interpolating. Runge-type oscillation is a property of the data and the method, not a bug.
How accurate is quad by default?
It adaptively refines until the estimated absolute error is below
epsabs (about 1.5e-8) or the relative error is below epsrel. Tighten both for sensitive work, and always check the returned error against the magnitude of the answer.Related
Optimisation and curve fitting Root finding and special functions
Last refreshed 2026-09-18.