开发者

Python interp1d vs. UnivariateSpline

I'm trying to port some MatLab code over to Scipy, and I've tried two different functions from scipy.interpolate, interp1d and UnivariateSpline. The interp1d results match the interp1d MatLab function, but the UnivariateSpline numbers come out different - and in some cases very different.

f = interp1d(row1,row2,kind='cubic',bounds_error=False,fill_value=numpy.max(row2))
return  f(interp)

f = Univa开发者_StackOverflow社区riateSpline(row1,row2,k=3,s=0)
return f(interp)

Could anyone offer any insight? My x vals aren't equally spaced, although I'm not sure why that would matter.


I just ran into the same issue.

Short answer

Use InterpolatedUnivariateSpline instead:

f = InterpolatedUnivariateSpline(row1, row2)
return f(interp)

Long answer

UnivariateSpline is a 'one-dimensional smoothing spline fit to a given set of data points' whereas InterpolatedUnivariateSpline is a 'one-dimensional interpolating spline for a given set of data points'. The former smoothes the data whereas the latter is a more conventional interpolation method and reproduces the results expected from interp1d. The figure below illustrates the difference.

Python interp1d vs. UnivariateSpline

The code to reproduce the figure is shown below.

import scipy.interpolate as ip

#Define independent variable
sparse = linspace(0, 2 * pi, num = 20)
dense = linspace(0, 2 * pi, num = 200)

#Define function and calculate dependent variable
f = lambda x: sin(x) + 2
fsparse = f(sparse)
fdense = f(dense)

ax = subplot(2, 1, 1)

#Plot the sparse samples and the true function
plot(sparse, fsparse, label = 'Sparse samples', linestyle = 'None', marker = 'o')
plot(dense, fdense, label = 'True function')

#Plot the different interpolation results
interpolate = ip.InterpolatedUnivariateSpline(sparse, fsparse)
plot(dense, interpolate(dense), label = 'InterpolatedUnivariateSpline', linewidth = 2)

smoothing = ip.UnivariateSpline(sparse, fsparse)
plot(dense, smoothing(dense), label = 'UnivariateSpline', color = 'k', linewidth = 2)

ip1d = ip.interp1d(sparse, fsparse, kind = 'cubic')
plot(dense, ip1d(dense), label = 'interp1d')

ylim(.9, 3.3)

legend(loc = 'upper right', frameon = False)

ylabel('f(x)')

#Plot the fractional error
subplot(2, 1, 2, sharex = ax)

plot(dense, smoothing(dense) / fdense - 1, label = 'UnivariateSpline')
plot(dense, interpolate(dense) / fdense - 1, label = 'InterpolatedUnivariateSpline')
plot(dense, ip1d(dense) / fdense - 1, label = 'interp1d')

ylabel('Fractional error')
xlabel('x')
ylim(-.1,.15)

legend(loc = 'upper left', frameon = False)

tight_layout()


The reason why the results are different (but both likely correct) is that the interpolation routines used by UnivariateSpline and interp1d are different.

  • interp1d constructs a smooth B-spline using the x-points you gave to it as knots

  • UnivariateSpline is based on FITPACK, which also constructs a smooth B-spline. However, FITPACK tries to choose new knots for the spline, to fit the data better (probably to minimize chi^2 plus some penalty for curvature, or something similar). You can find out what knot points it used via g.get_knots().

So the reason why you get different results is that the interpolation algorithm is different. If you want B-splines with knots at data points, use interp1d or splmake. If you want what FITPACK does, use UnivariateSpline. In the limit of dense data, both methods give same results, but when data is sparse, you may get different results.

(How do I know all this: I read the code :-)


Works for me,

from scipy import allclose, linspace
from scipy.interpolate import interp1d, UnivariateSpline

from numpy.random import normal

from pylab import plot, show

n = 2**5

x = linspace(0,3,n)
y = (2*x**2 + 3*x + 1) + normal(0.0,2.0,n)

i = interp1d(x,y,kind=3)
u = UnivariateSpline(x,y,k=3,s=0)

m = 2**4

t = linspace(1,2,m)

plot(x,y,'r,')
plot(t,i(t),'b')
plot(t,u(t),'g')

print allclose(i(t),u(t)) # evaluates to True

show()

This gives me,

Python interp1d vs. UnivariateSpline


UnivariateSpline: A more recent wrapper of the FITPACK routines.

this might explain the slightly different values? (I also experienced that UnivariateSpline is much faster than interp1d.)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜