How to make scipy.interpolate give an extrapolated result beyond the input range?
You can take a look at InterpolatedUnivariateSpline
Here an example using it:
import matplotlib.pyplot as pltimport numpy as npfrom scipy.interpolate import InterpolatedUnivariateSpline# given valuesxi = np.array([0.2, 0.5, 0.7, 0.9])yi = np.array([0.3, -0.1, 0.2, 0.1])# positions to inter/extrapolatex = np.linspace(0, 1, 50)# spline order: 1 linear, 2 quadratic, 3 cubic ... order = 1# do inter/extrapolations = InterpolatedUnivariateSpline(xi, yi, k=order)y = s(x)# example showing the interpolation for linear, quadratic and cubic interpolationplt.figure()plt.plot(xi, yi)for order in range(1, 4): s = InterpolatedUnivariateSpline(xi, yi, k=order) y = s(x) plt.plot(x, y)plt.show()
As of SciPy version 0.17.0, there is a new option for scipy.interpolate.interp1d that allows extrapolation. Simply set fill_value='extrapolate' in the call. Modifying your code in this way gives:
import numpy as npfrom scipy import interpolatex = np.arange(0,10)y = np.exp(-x/3.0)f = interpolate.interp1d(x, y, fill_value='extrapolate')print f(9)print f(11)
and the output is:
0.04978706836790.010394302658
1. Constant extrapolation
You can use interp
function from scipy, it extrapolates left and right values as constant beyond the range:
>>> from scipy import interp, arange, exp>>> x = arange(0,10)>>> y = exp(-x/3.0)>>> interp([9,10], x, y)array([ 0.04978707, 0.04978707])
2. Linear (or other custom) extrapolation
You can write a wrapper around an interpolation function which takes care of linear extrapolation. For example:
from scipy.interpolate import interp1dfrom scipy import arange, array, expdef extrap1d(interpolator): xs = interpolator.x ys = interpolator.y def pointwise(x): if x < xs[0]: return ys[0]+(x-xs[0])*(ys[1]-ys[0])/(xs[1]-xs[0]) elif x > xs[-1]: return ys[-1]+(x-xs[-1])*(ys[-1]-ys[-2])/(xs[-1]-xs[-2]) else: return interpolator(x) def ufunclike(xs): return array(list(map(pointwise, array(xs)))) return ufunclike
extrap1d
takes an interpolation function and returns a function which can also extrapolate. And you can use it like this:
x = arange(0,10)y = exp(-x/3.0)f_i = interp1d(x, y)f_x = extrap1d(f_i)print f_x([9,10])
Output:
[ 0.04978707 0.03009069]