SciPy Cheatsheet

Interpolation

Use this SciPy reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.

Core Import

from scipy.interpolate import (
    interp1d,
    CubicSpline, Akima1DInterpolator, PchipInterpolator, make_interp_spline,
    BarycentricInterpolator, KroghInterpolator,
    LinearNDInterpolator, CloughTocher2DInterpolator,
    NearestNDInterpolator, RegularGridInterpolator,
    RectBivariateSpline, SmoothBivariateSpline, UnivariateSpline,
    BSpline, make_smoothing_spline,
    griddata
)
import numpy as np

1-D Interpolation

interp1d — Classic (Still Useful, But Consider Alternatives)

from scipy.interpolate import interp1d

x = np.array([0, 1, 2, 3, 4], dtype=float)
y = np.array([0, 1, 4, 9, 16], dtype=float)

# Create interpolant
f = interp1d(x, y)                              # linear (default)
f = interp1d(x, y, kind='linear')
f = interp1d(x, y, kind='quadratic')
f = interp1d(x, y, kind='cubic')
f = interp1d(x, y, kind='nearest')
f = interp1d(x, y, kind='previous')
f = interp1d(x, y, kind='next')
f = interp1d(x, y, kind=3)                     # 3rd-order spline

# Evaluate
x_new = np.linspace(0, 4, 100)
y_new = f(x_new)

# Extrapolation (default raises ValueError outside x)
f = interp1d(x, y, kind='cubic',
             bounds_error=False,       # no error outside range
             fill_value='extrapolate') # extrapolate outside

f = interp1d(x, y, fill_value=(y[0], y[-1]),  # constant fill
             bounds_error=False)

# 2-D: interpolate along an axis
y2d = np.vstack([y, y**2])               # shape (2, 5)
f2d = interp1d(x, y2d, axis=1)          # interpolate along columns

CubicSpline — Recommended Cubic Spline

from scipy.interpolate import CubicSpline

cs = CubicSpline(x, y)                              # natural boundary conditions
cs = CubicSpline(x, y, bc_type='natural')           # y''=0 at endpoints
cs = CubicSpline(x, y, bc_type='not-a-knot')        # default
cs = CubicSpline(x, y, bc_type='periodic')          # y[0]==y[-1] required
cs = CubicSpline(x, y, bc_type='clamped')           # y'=0 at endpoints

# Custom boundary conditions: ((order_left, val_left), (order_right, val_right))
cs = CubicSpline(x, y, bc_type=((1, 0.0), (1, 0.0)))   # first derivative = 0

# Evaluate
y_new = cs(x_new)
y_prime = cs(x_new, 1)     # first derivative
y_double = cs(x_new, 2)    # second derivative
y_triple = cs(x_new, 3)    # third derivative

# Integration
cs.integrate(a=0, b=4)     # definite integral

# Roots
cs.roots()                  # all real roots
cs.roots(extrapolate=False) # roots within [x[0], x[-1]] only

# 2-D y (along last axis)
y_vec = np.column_stack([np.sin(x), np.cos(x)])  # shape (5, 2)
cs_vec = CubicSpline(x, y_vec)

Shape-Preserving Interpolators

from scipy.interpolate import PchipInterpolator, Akima1DInterpolator

# PCHIP: monotone cubic — no overshoots, good for monotone data
pchip = PchipInterpolator(x, y)
pchip(x_new)
pchip(x_new, nu=1)    # first derivative

# Akima: smooth, less sensitive to outliers than cubic spline
akima = Akima1DInterpolator(x, y)
akima(x_new)
InterpolatorOvershoots?SmoothBest For
interp1d(kind='linear')NoC0Simple, fast
interp1d(kind='cubic')YesC2Smooth data, simple API
CubicSplineYesC2Full control of BCs, derivatives
PchipInterpolatorNoC1Monotone / noisy data
Akima1DInterpolatorRarelyC1Smooth with local outliers

Spline Fitting (Smoothing)

from scipy.interpolate import UnivariateSpline, make_smoothing_spline

# UnivariateSpline: fits with smoothing (not exact interpolation)
spl = UnivariateSpline(x, y, k=3, s=0)      # s=0 → exact interpolation
spl = UnivariateSpline(x, y, k=3, s=len(x)) # s=n → more smoothing
spl = UnivariateSpline(x, y, k=3, s=None)   # s auto from data variance

spl(x_new)
spl(x_new, nu=1)           # first derivative
spl.get_knots()            # knot positions
spl.get_coeffs()           # B-spline coefficients
spl.get_residual()         # sum of squared residuals
spl.integral(a=0, b=4)    # definite integral
spl.roots()                # roots

# With weights
spl = UnivariateSpline(x, y, w=1/yerr, k=3)

# make_smoothing_spline (SciPy 1.10+, better λ selection)
spl2 = make_smoothing_spline(x, y, lam=1.0)

B-Splines

from scipy.interpolate import BSpline, make_interp_spline, splrep, splev, splint

# Construct from knots + coefficients
k = 3   # degree
t = np.array([0, 0, 0, 0, 1, 2, 3, 4, 4, 4, 4])  # knots (must have k+1 at ends)
c = np.random.rand(len(t) - k - 1)                 # coefficients
bspl = BSpline(t, c, k)
bspl(x_new)

# Build from data (smoothing/interpolation)
bspl = make_interp_spline(x, y, k=3)     # interpolating
bspl = make_interp_spline(x, y, k=5)     # quintic

# Legacy splrep/splev interface
tck = splrep(x, y, k=3, s=0)       # (t, c, k) tuple
y_new = splev(x_new, tck)
y_der = splev(x_new, tck, der=1)   # derivative
area = splint(0, 4, tck)           # integral

Polynomial Interpolation

from scipy.interpolate import BarycentricInterpolator, KroghInterpolator

# Barycentric (numerically stable Lagrange interpolation)
bary = BarycentricInterpolator(x, y)
bary(x_new)

# Krogh (matches function values AND derivatives at nodes)
xi = [0.0, 1.0, 2.0]
yi = [0.0, 1.0, 4.0]         # function values
# Specify derivatives: repeat xi with derivative value
xi_ext = [0.0, 0.0, 1.0, 2.0]
yi_ext = [0.0, 0.0, 2.0, 4.0]   # y'(0)=0, then y(1), y(2)
krogh = KroghInterpolator(xi_ext, yi_ext)

N-D Scattered Data Interpolation

griddata — Quick N-D Interpolation

from scipy.interpolate import griddata

# Random 2-D scattered points → regular grid
points = np.random.rand(100, 2)     # (N, 2) array of (x, y) coords
values = np.sin(points[:, 0]) * np.cos(points[:, 1])

# Target grid
xi = np.mgrid[0:1:50j, 0:1:50j]    # 50×50 meshgrid
xi = np.column_stack([xi[0].ravel(), xi[1].ravel()])  # shape (2500, 2)

# Interpolate
result = griddata(points, values, xi, method='linear')   # or 'nearest', 'cubic'
result = result.reshape(50, 50)

Triangulation-Based Interpolators

from scipy.interpolate import LinearNDInterpolator, CloughTocher2DInterpolator, NearestNDInterpolator

points = np.random.rand(100, 2)
values = np.sin(points[:, 0])

# Linear (piecewise, C0)
f = LinearNDInterpolator(points, values, fill_value=np.nan)

# Cubic (C1 smooth, 2-D only)
f = CloughTocher2DInterpolator(points, values, fill_value=np.nan)

# Nearest neighbor
f = NearestNDInterpolator(points, values)

# Evaluate
query_points = np.array([[0.5, 0.5], [0.2, 0.8]])
result = f(query_points)    # or f(xi, yi) for separate arrays

N-D Regular Grid Interpolation

from scipy.interpolate import RegularGridInterpolator

# Grid axes (must be strictly monotone)
x_ax = np.linspace(0, 4, 5)
y_ax = np.linspace(0, 3, 4)
data = np.random.rand(5, 4)   # shape = (len(x_ax), len(y_ax))

rgi = RegularGridInterpolator((x_ax, y_ax), data,
                               method='linear',        # 'linear', 'nearest', 'slinear', 'cubic', 'quintic', 'pchip'
                               bounds_error=True,
                               fill_value=np.nan)

# Query points (arbitrary coordinates)
pts = np.array([[1.5, 1.2], [3.0, 2.5]])
vals = rgi(pts)

2-D Spline Interpolation on Grids

from scipy.interpolate import RectBivariateSpline, SmoothBivariateSpline

# RectBivariateSpline: data on a rectangular grid
x_ax = np.linspace(0, 4, 10)
y_ax = np.linspace(0, 3, 8)
z = np.outer(np.sin(x_ax), np.cos(y_ax))   # shape (10, 8)

rbs = RectBivariateSpline(x_ax, y_ax, z, kx=3, ky=3)   # cubic in both dims
xi = np.linspace(0, 4, 50)
yi = np.linspace(0, 3, 40)
z_fine = rbs(xi, yi)                  # shape (50, 40)
z_at_pt = rbs(1.5, 2.0, grid=False)  # single point

# SmoothBivariateSpline: scattered 2-D data with smoothing
points_x = np.random.rand(200)
points_y = np.random.rand(200)
values = np.sin(points_x) * np.cos(points_y)

sbvs = SmoothBivariateSpline(points_x, points_y, values, kx=3, ky=3, s=0.1)
z_fine = sbvs(xi, yi)

Common Gotchas

interp1d is being soft-deprecated in favor of make_interp_spline, CubicSpline, and RegularGridInterpolator. For new code, prefer the newer classes.

CubicSpline requires at least 3 data points for cubic (2 for linear). interp1d is more flexible for edge cases.

griddata with method='cubic' only works in 2-D. For N-D, use LinearNDInterpolator or NearestNDInterpolator.

Extrapolation: Most interpolators raise ValueError outside the data range by default. Set bounds_error=False, fill_value=np.nan or fill_value='extrapolate' explicitly.

RegularGridInterpolator point format: Query points are (N, ndim) arrays — each row is one point. This trips up users coming from RectBivariateSpline which takes separate axis arrays.

Smoothing parameter s in UnivariateSpline: s=0 = exact interpolation. s=len(x) ≈ strong smoothing. s=None uses a heuristic. Always inspect with spl.get_residual().