【问题标题】:Smooth line with spline + datetime objects doesn't work带有样条线 + 日期时间对象的平滑线不起作用
【发布时间】:2016-12-05 19:12:04
【问题描述】:

我一直在努力使情节更流畅,就像 here 一样,但我的 X 是与 linspace 不兼容的日期时间对象..

我将 Xs 转换为 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 的值是多少。对于debugging in a IPython during execution try using %debugadd breakpoints 或者可能使用logging 在执行期间查看中间值。
  • 我编辑了问题并添加了变量
  • 从你的输出我推断你的问题是样条,而不是日期时间。你能改写你的问题吗?也许用一组较小的数字来尝试你的问题,比如 10 而不是 300,这将在 SO 中更容易显示并且更容易调试。还要仔细检查np.splie 文档
  • 我对 10 做了同样的事情,但没有区别。文档很小,没有示例:docs.scipy.org/doc/scipy/reference/generated/…,那里没有什么可学的;(
  • 我想你想要来自 scipy 的 interp1d。它可以做一些样条变体

标签: python datetime matplotlib scipy interpolation


【解决方案1】:

您的 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 - 独立输入数据的一维数组。必须增加。

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

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

scipy.interpolate.spline 的文档含糊不清,暗示它可能不受支持。例如,它未列在scipy.interpolate main pageinterploation tutorial 上。 source for spline 表明它实际上调用了splevalsplmake,它们在Additional Tools 下列出为:

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

我会按照cricket_007 的建议使用interp1d。这是目前推荐的方法,它在detailed examples in both the tutorial 和 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')

ValueError: x 和 y 数组必须至少有 4 个条目

【讨论】:

  • 顺序重要吗?如果你用负斜率对直线进行样条曲线呢? X 随 Y 减小而增大...
  • 我不知道,也许,我没有阅读scipy.interpolate.spline 上的文档,但没关系,np.linspace Xsmooth 的输出与原始输入相反, Xnew,这就是问题所在,不一致。
  • 无法解释.. 当我按照你说的做时:newX = list(reversed(matplotlib.dates.date2num(X))) Y = list(reversed(Y)) X_smooth = np.linspace(min(newX), max(newX), 10) Y_smooth = spline(newX, Y, X_smooth) 我得到:[ 755. 1000.68447671 1062.10559586 991.91003112 842.74445597 667.25554403 518.08996888 447.89440414 509.31552329 755. ] 这个 Y:[755.0, 755.0, 755.0]
  • 我觉得绘制数据可能会更好地了解问题试图实现的目标。只是我的意见...
  • 倒车无效,但板球的 interp1d 效果很好,感谢大家的帮助
猜你喜欢
  • 2021-05-23
  • 2022-01-17
  • 2017-08-06
  • 2019-03-10
  • 1970-01-01
  • 2018-12-21
  • 1970-01-01
  • 1970-01-01
  • 2020-06-16
相关资源
最近更新 更多