How to make scipy.interpolate give an extrapolated result beyond the input range? How to make scipy.interpolate give an extrapolated result beyond the input range? numpy numpy

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]