平滑曲线与样条函数+日期时间对象无法正常工作

4

我一直试图使绘图更平滑,就像这里所做的那样,但我的X轴是日期时间对象,无法与linspace兼容。

我将X轴转换为matplotlib日期:

Xnew = matplotlib.dates.date2num(X)
X_smooth = np.linspace(Xnew.min(), Xnew.max(), 10)
Y_smooth = spline(Xnew, Y, X_smooth)

但是我得到了一个空的图表,因为我的Y_smooth是 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.] ,原因不明。
我该如何解决这个问题?
编辑:
当我打印变量时,我看不到任何异常。
X : [datetime.date(2016, 7, 31), datetime.date(2016, 7, 30), datetime.date(2016, 7, 29)]
X new: [ 736176.  736175.  736174.]
X new max: 736176.0
X new min: 736174.0
XSMOOTH [ 736174.          736174.22222222  736174.44444444  736174.66666667
  736174.88888889  736175.11111111  736175.33333333  736175.55555556
  736175.77777778  736176.        ]
Y [711.74, 730.0, 698.0]
YSMOOTH [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]

我刚试过一个例子,你的方法对我有效。尝试调试每一行代码。Xnew.min()Xnew.max() 的值是多少?发布更多细节。XX_smoothXnew 的值是多少?在IPython执行期间进行调试,请尝试使用%debug添加断点,或者使用logging在执行期间查看中间值。 - Mark Mikofski
我编辑了问题并添加了变量。 - AimiHat
从你的输出中我推断出你的问题在于样条曲线,而不是日期时间。你能否重新表述你的问题?也许尝试使用较小的数字集,如10而不是300,这将更容易在SO中显示和调试。同时,请仔细检查np.splie文档。 - Mark Mikofski
我用10做了同样的事情,但没有任何区别...文档很小,没有示例:http://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.spline.html,那里没有什么可以学习的 ;( - AimiHat
X的顺序被颠倒了,Xnew减少但Xsmooth增加,反转XnewY - Mark Mikofski
1
我认为你想要从scipy中使用interp1d。它可以执行几种样条变体。 - OneCricketeer
1个回答

5

你的X值是反向的,scipy.interpolate.spline要求自变量单调递增,而这种方法已经过时了 - 改用interp1d(见下文)。

>>> from scipy.interpolate import spline
>>> import numpy as np
>>> X = [736176.0, 736175.0, 736174.0]  # <-- your original X is decreasing
>>> Y = [711.74, 730.0, 698.0]
>>> Xsmooth = np.linspace(736174.0, 736176.0, 10)
>>> spline(X, Y, Xsmooth)
array([ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.])

先反转XY,然后它就可以工作了

>>> spline(
...     list(reversed(X)),  # <-- reverse order of X so also
...     list(reversed(Y)),  # <-- reverse order of Y to match
...     Xsmooth
... )
array([  698.        ,   262.18297973,   159.33767533,   293.62017489,
         569.18656683,   890.19293934,  1160.79538066,  1285.149979  ,
        1167.41282274,   711.74      ])

请注意,许多样条插值方法要求X单调递增:

x(N,)array_like - 独立输入数据的1-D数组。必须递增。

x(N,)array_like - 数据点的输入维度-必须递增

scipy.interpolate.spline的默认阶数为三次。因为只有3个数据点,所以三次样条线(order = 3)和二次样条线(order = 2)之间存在很大差异。下面的图显示了不同阶数样条线之间的差异;注意:使用了100个点来平滑拟合曲线。

scipy.interpolate.spline


scipy.interpolate.spline的文档含糊不清,并暗示它可能不被支持。例如,在scipy.interpolate主页插值教程中都没有列出。spline的源代码显示它实际上调用了splevalsplmake,它们在附加工具下列出:

此处列出的函数是为了向后兼容而存在的(不应在新代码中使用)。

我建议遵循cricket_007的建议并使用interp1d。这是目前建议的方法,它有非常详细的文档和教程和API中的详细示例, 并且默认情况下允许独立变量无序 (任何顺序),具体请参阅API中的assume_sorted参数。

>>> from scipy.interpolate import interp1d
>>> f = interp1d(X, Y, kind='quadratic')
>>> f(Xsmooth)
array([ 711.74      ,  720.14123457,  726.06049383,  729.49777778,
        730.45308642,  728.92641975,  724.91777778,  718.4271605 ,
        709.4545679 ,  698.        ])

此外,如果数据等级不足,它会引发错误。
>>> f = interp1d(X, Y, kind='cubic')

数值错误:x和y数组必须至少有4个条目。

顺序重要吗?如果您使用负斜率对线性线进行样条插值会怎样?当Y减少时,X增加... - OneCricketeer
我不知道,也许是因为我没有阅读 scipy.interpolate.spline 的文档,但这并不重要,np.linspace 的输出 Xsmooth 与原始输入 Xnew 相反,这就是问题所在,它不一致。 - Mark Mikofski
1
我觉得绘制数据可能会更好地了解问题所要达到的目标。这只是我的个人意见... - OneCricketeer
1
反转没有起作用,但是cricket的interp1d效果很好,谢谢大家的帮助。 - AimiHat
@Codemon 你可以通过增加 linspace 中的“步骤”来使插值更加平滑。 - OneCricketeer
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接