Python interp1d与UnivariateSpline

Tim*_*ees 11 python matlab interpolation numpy scipy

我正在尝试将一些MatLab代码移植到Scipy,我尝试了scipy.interpolate,interp1dUnivariateSpline两个不同的函数.interp1d结果与interp1d MatLab函数匹配,但UnivariateSpline数字不同 - 在某些情况下非常不同.

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

f = UnivariateSpline(row1,row2,k=3,s=0)
return f(interp)
Run Code Online (Sandbox Code Playgroud)

谁能提供任何见解?我的x值不是等间隔的,虽然我不确定为什么这很重要.

Til*_*ann 14

我刚遇到同样的问题.

简短的回答

使用InterpolatedUnivariateSpline代替:

f = InterpolatedUnivariateSpline(row1, row2)
return f(interp)
Run Code Online (Sandbox Code Playgroud)

答案很长

单变量样条是一个"适合给定数据点集的一维平滑样条曲线",而InterpolatedUnivariateSpline是"给定数据点集合的一维插值样条曲线".前者使数据平滑,而后者是更传统的插值方法,并且再现了interp1d预期的结果.下图说明了差异.

插值函数的比较

重现该图的代码如下所示.

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()
Run Code Online (Sandbox Code Playgroud)

  • 您链接到InterpolatedUnivariateSpline的注释的文档"等同于S = 0的UnivariateSpline",这是他正在使用的. (5认同)

pv.*_*pv. 12

结果不同(但两者都可能正确)的原因在于使用的插值例程UnivariateSplineinterp1d不同的插值例程.

  • interp1d使用x你给它作为节点的点构造一个平滑的B样条

  • UnivariateSpline基于FITPACK,它也构造了一个平滑的B样条.然而,FITPACK试图为样条选择新的结,以更好地拟合数据(可能最小化chi ^ 2加上曲率的一些惩罚,或类似的东西).你可以找出它使用的结点g.get_knots().

所以你得到不同结果的原因是插值算法是不同的.如果您希望B样条曲线在数据点处有结,请使用interp1dsplmake.如果你想要FITPACK做什么,请使用UnivariateSpline.在密集数据的限制下,两种方法都给出相同的结果,但是当数据稀疏时,您可能会得到不同的结果.

(我怎么知道这一切:我读了代码:-)


xyz*_*123 0

UnivariateSpline: FITPACK 例程的更新包装器。

这可以解释略有不同的值吗?(我还体验到 UnivariateSpline 比 interp1d 快得多。)