我正在尝试将一些MatLab代码移植到Scipy,我尝试了scipy.interpolate,interp1d和UnivariateSpline两个不同的函数。 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)
有人可以提供任何见解吗?我的x值不是等间隔的,虽然我不确定为什么这很重要。
答案 0 :(得分:14)
我刚遇到同样的问题。
改为使用InterpolatedUnivariateSpline:
f = InterpolatedUnivariateSpline(row1, row2)
return f(interp)
UnivariateSpline是“适合给定数据点集的一维平滑样条曲线”,而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()
答案 1 :(得分:12)
结果不同(但两者都可能正确)的原因是UnivariateSpline
和interp1d
使用的插值例程不同。
interp1d
使用x
构建一个平滑的B样条 - 您给它的点作为结
UnivariateSpline
基于FITPACK,它也构造了一个平滑的B样条。然而,FITPACK尝试为样条选择 new 结,以更好地拟合数据(可能最小化chi ^ 2加上曲率的一些惩罚,或类似的东西)。您可以通过g.get_knots()
找出它使用的结点。
因此,您得到不同结果的原因是插值算法不同。如果您希望B样条曲线在数据点处有结,请使用interp1d
或splmake
。如果您想要FITPACK的功能,请使用UnivariateSpline
。在密集数据的限制下,两种方法都给出相同的结果,但是当数据稀疏时,您可能得到不同的结果。
(我怎么知道这一切:我读了代码: - )
答案 2 :(得分:2)
适合我,
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()
这给了我,
答案 3 :(得分:0)
UnivariateSpline: 更新 FITPACK例程的包装器。
这可能解释了略有不同的价值观? (我也经历过UnivariateSpline比interp1d快得多。)