scijit.interpolate.interp1d

scijit.interpolate.interp1d(x, y, kind='linear', axis=-1, copy=True, bounds_error=None, fill_value=nan, assume_sorted=False, extrapolate=False)

Build an _Interp1D for one-dimensional interpolation.

Parameters:
x1-D array_like of float

Sample abscissae. Sorted ascending unless assume_sorted says they already are. After sorting they must be strictly increasing; a repeated value raises ValueError. Minimum length is 2 for kinds 0-3 and 6, and k+1 (3 for quadratic, 4 for cubic) for 4 and 5.

yarray_like of float or complex, rank 1, 2 or 3

Sample ordinates. Its length along axis must match x. Every position on the other axes is an independent series over the same x. Rank 4 and above raise ValueError. A complex y of any width is held as complex128 and the interpolated result carries it; anything else is float64. The spline kinds fit the real and the imaginary parts separately on one knot vector.

kindstr or int, optional

Interpolation kind. Either one of these strings:

‘linear’ ‘slinear’ is accepted for this too ‘nearest’ ties round DOWN ‘previous’ ‘zero’ is accepted for this too ‘next’ ‘quadratic’ k=2 interpolating spline ‘cubic’ k=3 interpolating spline ‘nearest-up’ ties round UP

or an integer giving the spline ORDER, so kind=3 is cubic. See Notes for the integer’s full range. Default 'linear'. An unrecognised string raises NotImplementedError. The value may be a runtime string, not only a literal.

axisint, optional

Which axis of y the interpolation runs along, default -1. Negative values count from the end. Ignored for a 1-D y. ev(xs) returns the shape of y with this axis replaced by len(xs); a scalar query returns it with this axis removed.

copybool, optional

True, the default, copies x and y. False keeps a reference where the array is already contiguous float64, so a later mutation of it shows through; anything else is converted, which copies. With the default assume_sorted=False the sort copies regardless.

bounds_errorbool or None, optional

If True, evaluating outside [x[0], x[-1]] raises ValueError. Default None, which means True unless the call extrapolates. Passing True while extrapolating raises ValueError.

fill_valuefloat, (below, above), array_like, or ‘extrapolate’, optional

What out-of-bounds points get when bounds_error is False and the call does not extrapolate. A 2-tuple, and only a 2-tuple, is (below, above). Anything else, a scalar, a list or an array, is broadcast up to y.shape[:axis] + y.shape[axis+1:] and gives one value PER SERIES; a shape that does not broadcast raises ValueError. Each element of a 2-tuple broadcasts on its own, so ([1.0, 2.0], [3.0, 4.0]) sets a different value per series at each end. The string 'extrapolate' extrapolates instead of filling; it may be a runtime string, not only a literal. Default NaN.

assume_sortedbool, optional

False (the default) sorts x ascending and reorders y with it. True takes x as already ascending and skips the sort. Either way the result must be strictly increasing. A bool axis raises TypeError on the sorting path, and is read as 0 or 1 with assume_sorted=True.

extrapolatebool, optional

If True, extrapolate out-of-bounds points instead of filling them. The same thing fill_value='extrapolate' does. Default False. Linear extrapolates along the end segment, the splines continue the end polynomial, nearest/nearest-up clamp to the end node, ‘previous’ returns NaN below the range and ‘next’ returns NaN above it.

THE PRECEDENCE across the three parameters: extrapolation is on if EITHER extrapolate is True or fill_value is 'extrapolate', so the string wins over the default extrapolate=False; bounds_error=None then resolves to “raise unless extrapolating”; an explicit bounds_error=True alongside extrapolation from either spelling raises Cannot extrapolate and raise at the same time.; and a numeric fill_value given alongside extrapolation is never read.

Returns:
f_Interp1D

A callable jitclass instance. f(xs) runs _Interp1D.ev and f(x) runs _Interp1D.ev_one; f[xs] reaches ev too.

Raises:
NotImplementedError

On a kind that is neither one of the strings nor an integer, which includes a float and None, and the message names the value.

ValueError

On a fill_value whose shape does not broadcast up to y’s trailing shape, an x that is not strictly increasing once sorted, a length mismatch, too few points for the chosen kind, or bounds_error=True while extrapolating.

IndexError

On an axis outside [-y.ndim, y.ndim).

TypeError

On a bool axis with assume_sorted=False.

See also

scipy.interpolate.interp1d

The scipy routine this mirrors.

Notes

This factory is an @njit function, so it runs from Python and from inside @njit, and its keyword defaults apply in both. The _Interp1D constructor underneath takes all ten arguments explicitly, because a jitclass constructor’s defaults are Python-only; the factory is what supplies them, and it is where the kind string resolves.

An integer `kind` is the spline ORDER. So 0 is 'zero', 1 'slinear', 2 'quadratic' and 3 'cubic'; orders above 3 have no string spelling, and a negative order raises Expect non-negative k.

scipy.interpolate.interp1d is marked legacy in scipy’s own documentation, which points at make_interp_spline and the other constructors for new code.

Deviations from scipy. extrapolate is an additional parameter with no scipy counterpart, so interp1d exposes three out-of-bounds parameters where scipy exposes two; a scipy-shaped call never passes it. A duplicated abscissa raises here, where scipy sorts, does not check, and evaluates a zero-width interval to inf or nan. y is capped at rank 3, where scipy takes any rank. fill_value is a property returning the resolved (below, above) pair, where scipy’s returns the object last assigned, and set_fill_value is the method that takes everything scipy’s setter takes; a property setter on a jitclass is typed by its getter, so one property cannot accept both a number and a string.

A complex fill_value on a real y raises ValueError, and a complex x raises TypingError. scipy truncates both to float64 and returns a real result, warning only for the fill_value: measured, fill_value=1+2j on a real y returns float64 with a ComplexWarning, and a complex x returns complex128 whose imaginary part is 0.0 everywhere.

set_fill_value(‘extrapolate’) extrapolates for every kind. scipy’s own setter does not: it fixes the linear kernel at construction, so on a 1-D float64 y at kind='linear' the same object clamps to the end nodes when the string arrives afterwards and extrapolates when it arrives in the constructor. Measured at x = linspace(0, 1, 5), y = sin(3x), queried at -1 and 2: built with the string [-2.7266, -2.4067], set afterwards [0.0, 0.1411]. The same split appears at kind='previous' and 'next', where the setter route loses the NaN. This reproduces the constructor’s answer in every cell.

The spline kinds are fitted with this package’s make_interp_spline at bc_type='not-a-knot'. FITPACK’s 1 <= k <= 5 fitting cap does not apply, because no FITPACK fitter is involved.

Accuracy vs scipy on 16 nodes over 50 in-range points, calling scipy with the same string: ‘linear’, ‘nearest’, ‘nearest-up’, ‘previous’, ‘next’, ‘quadratic’, ‘cubic’ and ‘zero’ all exactly 0.0, and ‘slinear’ 1.11e-16. An integer kind, which is the spline ORDER, over orders 0 to 8: worst 4.44e-16. The two aliases: ‘zero’ exactly 0.0 against code 2, and ‘slinear’ 2.22e-16 against code 0, that last one because scipy routes ‘slinear’ through a degree-1 spline where this reads the segment directly. Extrapolating two units past each end: linear and nearest 0.0, quadratic 1.42e-14, cubic 8.53e-14.

prange-safe: yes for evaluation of prebuilt instances.

Examples

>>> import numpy as np
>>> from numba import njit
>>> from scijit.interpolate import interp1d
>>> x = np.linspace(0.0, 1.0, 9)
>>> y = np.sin(3.0 * x)
>>> f = interp1d(x, y, 'cubic')     # build once
>>> np.round(f(np.array([0.25, 0.75])), 6)
array([0.681639, 0.778073])

Inside compiled code, the mean of the interpolant over its domain:

>>> @njit
... def mean(f):
...     xs = np.linspace(0.0, 1.0, 201)
...     return np.mean(f(xs))
>>> float(np.round(mean(f), 6))
0.660382