关于python:使用scipy.interpolate.splrep函数

Using scipy.interpolate.splrep function

我正在尝试将三次样条曲线拟合到给定的点集。我的积分没有顺序。由于我需要这些信息,因此我无法对这些点进行排序或重新排序。

但是由于函数scipy.interpolate.splrep仅适用于非重复且单调递增的点,因此我定义了一个函数,该函数将x坐标映射到单调递增的空间。

我的老观点是:

1
2
3
xpoints=[4913.0, 4912.0, 4914.0, 4913.0, 4913.0, 4913.0, 4914.0, 4915.0, 4918.0, 4921.0, 4925.0, 4932.0, 4938.0, 4945.0, 4950.0, 4954.0, 4955.0, 4957.0, 4956.0, 4953.0, 4949.0, 4943.0, 4933.0, 4921.0, 4911.0, 4898.0, 4886.0, 4874.0, 4865.0, 4858.0, 4853.0, 4849.0, 4848.0, 4849.0, 4851.0, 4858.0, 4864.0, 4869.0, 4877.0, 4884.0, 4893.0, 4903.0, 4913.0, 4923.0, 4935.0, 4947.0, 4959.0, 4970.0, 4981.0, 4991.0, 5000.0, 5005.0, 5010.0, 5015.0, 5019.0, 5020.0, 5021.0, 5023.0, 5025.0, 5027.0, 5027.0, 5028.0, 5028.0, 5030.0, 5031.0, 5033.0, 5035.0, 5037.0, 5040.0, 5043.0]

ypoints=[10557.0, 10563.0, 10567.0, 10571.0, 10575.0, 10577.0, 10578.0, 10581.0, 10582.0, 10582.0, 10582.0, 10581.0, 10578.0, 10576.0, 10572.0, 10567.0, 10560.0, 10550.0, 10541.0, 10531.0, 10520.0, 10511.0, 10503.0, 10496.0, 10490.0, 10487.0, 10488.0, 10488.0, 10490.0, 10495.0, 10504.0, 10513.0, 10523.0, 10533.0, 10542.0, 10550.0, 10556.0, 10559.0, 10560.0, 10559.0, 10555.0, 10550.0, 10543.0, 10533.0, 10522.0, 10514.0, 10505.0, 10496.0, 10490.0, 10486.0, 10482.0, 10481.0, 10482.0, 10486.0, 10491.0, 10497.0, 10506.0, 10516.0, 10524.0, 10534.0, 10544.0, 10552.0, 10558.0, 10564.0, 10569.0, 10573.0, 10576.0, 10578.0, 10581.0, 10582.0]

情节:

Erroneous trace
映射函数和插值的代码为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
xnew=[]
ynew=ypoints

for c3,i in enumerate(xpoints):
         if np.isfinite(np.log(i*pow(2,c3))):
                    xnew.append(np.log(i*pow(2,c3)))
         else:
                    if c==0:
                        xnew.append(np.random.random_sample())
                    else:
                        xnew.append(xnew[c3-1]+np.random.random_sample())
xnew=np.asarray(xnew)
ynew=np.asarray(ynew)
constant1=10.0
nknots=len(xnew)/constant1
idx_knots = (np.arange(1,len(xnew)-1,(len(xnew)-2)/np.double(nknots))).astype('int')
knots = [xnew[i] for i in idx_knots]
knots = np.asarray(knots)
int_range=np.linspace(min(xnew),max(xnew),len(xnew))
tck = interpolate.splrep(xnew,ynew,k=3,task=-1,t=knots)
y1= interpolate.splev(int_range,tck,der=0)

代码在函数interpolate.splrep()上针对诸如上述一组点的点抛出错误。

错误是:
在save_spline_f中的第58行,文件" /home/neeraj/Desktop/koustav/res/BOS5/fit_spline3.py"
tck = interpolate.splrep(xnew,ynew,k = 3,task = -1,t = knots)
splrep中的文件" /usr/lib/python2.7/dist-packages/scipy/interpolate/fitpack.py",第465行
提高_iermessier(_iermess [ier] [0])
ValueError:输入数据错误

但对于其他几点来说,它工作正常。例如,以下几点。

1
2
3
xpoints=[1629.0, 1629.0, 1629.0, 1629.0, 1629.0, 1629.0, 1629.0, 1629.0, 1629.0, 1629.0, 1629.0, 1629.0, 1629.0, 1629.0, 1629.0, 1629.0, 1630.0, 1630.0, 1630.0, 1631.0, 1631.0, 1631.0, 1631.0, 1630.0, 1629.0, 1629.0, 1629.0, 1628.0, 1627.0, 1627.0, 1625.0, 1624.0, 1624.0, 1623.0, 1620.0, 1618.0, 1617.0, 1616.0, 1615.0, 1614.0, 1614.0, 1612.0, 1612.0, 1612.0, 1611.0, 1610.0, 1609.0, 1608.0, 1607.0, 1607.0, 1603.0, 1602.0, 1602.0, 1601.0, 1601.0, 1600.0, 1599.0, 1598.0]

ypoints=[10570.0, 10572.0, 10572.0, 10573.0, 10572.0, 10572.0, 10571.0, 10570.0, 10569.0, 10565.0, 10564.0, 10563.0, 10562.0, 10560.0, 10558.0, 10556.0, 10554.0, 10551.0, 10548.0, 10547.0, 10544.0, 10542.0, 10541.0, 10538.0, 10534.0, 10532.0, 10531.0, 10528.0, 10525.0, 10522.0, 10519.0, 10517.0, 10516.0, 10512.0, 10509.0, 10509.0, 10507.0, 10504.0, 10502.0, 10500.0, 10501.0, 10499.0, 10498.0, 10496.0, 10491.0, 10492.0, 10488.0, 10488.0, 10488.0, 10486.0, 10486.0, 10485.0, 10485.0, 10486.0, 10483.0, 10483.0, 10482.0, 10480.0]

情节:
Trace for which there was no error
有人可以暗示发生了什么吗?
提前致谢......


实际上,您不必自己定义一个新函数。就是这样
轨迹插补非常多:scipy:插补轨迹(scipy:插补轨迹)

答案对我有好处,希望它能对您有所帮助。

1
2
3
4
from scipy import interpolate as itp
mytck,myu=itp.splprep([xpoints,ypoints])
xnew,ynew= itp.splev(np.linspace(0,1,1000),mytck)
plot(xnew,ynew)

Result after Spline


我相信您正在使用的函数splrep()的目的是使y坐标适合x坐标的函数:y = f(x)。

为了使splrep()正常工作,您的函数必须为单值。也就是说,您必须能够在图形的任何位置绘制一条垂直线,并使它与曲线精确地相交一次。

相反,也许您想分别将x和y拟合为单调增加的第三个参数t。

x = f(t)
y = g(t)

t有两个简单的选择。第一个只是点的索引(第一个点为0,第二个点为1,依此类推)。第二个选择要难一点,累积的直线距离从点到点传播。然后,您将分别为x和y坐标调用slrep()

1
2
3
t = [0]
for i in range(1, len(x)):
  t[i] = t[i-1]+np.hypot(x[i]-x[i-1], y[i]-y[i-1])

也许您反而想要贝塞尔曲线样条曲线?


如文档中所述,X值的唯一性对于获得有意义的结果非常重要。在您的情况下,这违反了,因此对数据进行一些更正可能会有所帮助。