Python interp1d与单变量plin

2024-05-08 22:55:02 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试将一些MatLab代码移植到Scipy,并且尝试了Scipy.interpolate、interp1dUnivariateSpline中的两个不同函数。interp1d的结果与interp1d的MatLab函数相匹配,但是单变量的pline数是不同的,在某些情况下是非常不同的。

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值不是等距的,虽然我不知道这有什么关系。


Tags: 函数代码return情况scipyrow1row2matlab
3条回答

我刚碰到同样的问题。

简短的回答

请改用InterpolatedUnivariateSpline

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

冗长的回答

UnivariateSpline是“适合给定数据点集的一维平滑样条曲线”,而InterpolatedUnivariateSpline是“给定数据点集的一维插值样条曲线”。前者平滑数据,而后者是一种更为传统的插值方法,并再现了interp1d中预期的结果。下图说明了区别。

Comparison of interpolation functions

复制该图的代码如下所示。

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()

结果不同(但都可能正确)的原因是UnivariateSplineinterp1d使用的插值例程不同。

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

  • UnivariateSpline基于FITPACK,它还构造了一个平滑的B样条曲线。但是,FITPACK尝试为样条曲线选择新的节点,以便更好地拟合数据(可能是为了最小化chi^2加上曲率的一些惩罚,或类似的东西)。您可以通过g.get_knots()找到它使用的结点。

所以得到不同结果的原因是插值算法不同。如果要在数据点处使用节点的B样条曲线,请使用interp1dsplmake。如果您想要FITPACK的功能,请使用UnivariateSpline。在稠密数据的限制下,两种方法给出的结果相同,但当数据稀疏时,可能得到不同的结果。

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

对我有用

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()

这给了我

enter image description here

相关问题 更多 >

    热门问题