【问题标题】:Pandas interpolate doesn't give monotonic results熊猫插值不会给出单调的结果
【发布时间】:2021-05-01 12:15:36
【问题描述】:

我有以下数据,我想将使用样条的插值方法应用于最后 4 个数字(我知道这是外推):

import numpy as np

x = [
    18.792571,
    19.170139,
    19.370556,
    19.393820,
    19.239932,
    18.908891,
    18.400699,
    17.892507,
    17.384314,
    16.876122,
    16.367930,
    15.859737,    
    np.nan,
    np.nan,
    np.nan,
    np.nan
]

我正在运行 pandas interpolate 并且发生了一件非常奇怪的事情,就像代码一样

import pandas as pd

pd.Series(x).interpolate(
    method="spline", 
    order=1
)

返回

0     18.792571
1     19.170139
2     19.370556
3     19.393820
4     19.239932
5     18.908891
6     18.400699
7     17.892507
8     17.384314
9     16.876122
10    16.367930
11    15.859737
12    16.103099
13    15.790022
14    15.476945
15    15.163868
dtype: float64

因此,虽然数据的趋势显然是负面的,但因为很早的指数,插值产生了向上的跳跃。使用 scipy 运行相同的计算时

import scipy.interpolate as inp
train_x = [_ for _ in x if _ > 0]
s = inp.InterpolatedUnivariateSpline(range(len(train_x)), train_x, k=1)
ynew = s(range(len(x)))
ynew[12:]

我明白了

array([15.351544, 14.843351, 14.335158, 13.826965])

在这种情况下,插值没有向上变化,所以结果对我来说是有意义的。

那么我的问题是:

  • 为什么 pandas 和 scipy 的结果不一样?
  • 如何让 pandas interpolate 给出我使用 scipy 获得的结果?
  • 为什么熊猫会发生这种向上的变化?

提前致谢!


编辑

使用 scipy interp1d 我有同样的问题:

s = inp.interp1d(range(len(train_x)), train_x, kind=1, fill_value='extrapolate')
ynew = s(range(len(x)))
ynew[12:]

给予

array([15.351544, 14.843351, 14.335158, 13.826965])

【问题讨论】:

  • 嗯,这很奇怪。有趣的是,Pandas interpolate 和 method=spline 的输出实际上与使用线性回归在整个数据集上推断的数据相匹配。如果您使用不同的方法(例如method=slinear),您将获得与直接 Scipy 实现类似的结果。我实际上不清楚 Pandas 如何解释 method=spline,即它执行的确切 scipy 函数和参数。

标签: python pandas numpy scipy interpolation


【解决方案1】:

也许不是答案,只是一些 cmets:

  1. Pandas 使用 scipy.interpolate.interp1d 而不是 InterpolatedUnivariateSpline。我相信这些在实现上略有不同。

  2. 我会使用 scipy.interpolate.interp1d 来查看 pandas 和 scipy 是否匹配。

  3. 插值用于填充内数据。你所拥有的更符合外推法。尽管可以使用这些方法进行外推。我预计结果可能会导致诸如向上变化之类的特殊性。

【讨论】:

  • 感谢您的回答,但是,我已经完成了第 2 点,但它们实际上并不匹配 :( 关于可能发生的任何线索?(它实际上给出了与 te univariatespline 相同的结果,正如我在编辑中添加的那样)
【解决方案2】:

实际上,pandas 使用 UnivariateSpline,因此,为了获得与 pandas 相同的结果,我们可以使用 scipy 运行以下命令:

import scipy.interpolate as inp
train_x = [_ for _ in x if _ > 0]
s = inp.UnivariateSpline(x=range(len(train_x)), y=train_x, k=1)
ynew = s(range(len(x)))
ynew[12:]

给了

array([16.10309945, 15.79002222, 15.47694498, 15.16386774])

在这种情况下,减少插值的方法是通过s = 0:

pd.Series(x).interpolate(
    method="spline", 
    order=1,
    s=0
)

返回:

0     18.792571
1     19.170139
2     19.370556
3     19.393820
4     19.239932
5     18.908891
6     18.400699
7     17.892507
8     17.384314
9     16.876122
10    16.367930
11    15.859737
12    15.351544
13    14.843351
14    14.335158
15    13.826965
dtype: float64

【讨论】:

    猜你喜欢
    • 2021-07-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-27
    • 1970-01-01
    • 2018-07-19
    相关资源
    最近更新 更多