如何在长的Pandas序列上应用三次样条插值?

9

我需要使用三次样条插值法在pandas Series中替换缺失的数据。我发现可以使用pandas.Series.interpolate(method='cubic')方法,如下所示:

import numpy as np
import pandas as pd

# create series
size = 50
x = np.linspace(-2, 5, size)
y = pd.Series(np.sin(x))

# deleting data segment
y[10:30] = np.nan

# interpolation
y = y.interpolate(method='cubic')

尽管这种方法在小序列(size = 50)中运行得很好,但似乎会导致程序在较大的序列(size = 5000)中冻结。有没有解决办法?


这似乎是一个“内存错误”。你使用的是32位机器吗?或者说,你使用的是32位版本的Python吗? - dagrha
这真的很奇怪! - maxymoo
我正在使用一台64位机器和最新的WinPython 64位版本。 - Crolle
1个回答

11

pandas调用了scipy的插值函数,不确定为什么'cubic'如此消耗内存且运行缓慢。

作为解决方案,您可以使用method='spline'(scipy参考 在这里), 并使用正确的参数,它会给出基本上相同的结果(似乎有一些浮点数差异),而且速度显著更快。

In [104]: # create series
     ...: size = 2000
     ...: x = np.linspace(-2, 5, size)
     ...: y = pd.Series(np.sin(x))
     ...: 
     ...: # deleting data segment
     ...: y[10:30] = np.nan
     ...: 

In [105]: %time cubic = y.interpolate(method='cubic')
Wall time: 4.94 s

In [106]: %time spline = y.interpolate(method='spline', order=3, s=0.)
Wall time: 1 ms

In [107]: (cubic == spline).all()
Out[107]: False

In [108]: pd.concat([cubic, spline], axis=1).loc[5:35, :]
Out[108]: 
           0         1
5  -0.916444 -0.916444
6  -0.917840 -0.917840
7  -0.919224 -0.919224
8  -0.920597 -0.920597
9  -0.921959 -0.921959
10 -0.923309 -0.923309
11 -0.924649 -0.924649
12 -0.925976 -0.925976
13 -0.927293 -0.927293

我找不到关于s=...的文档,但如果我们不传递该值,插值似乎就没有意义。那是什么? - Muhammad Yasirroni
2
@MuhammadYasirroni s 的文档位于 https://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.splrep.html#scipy.interpolate.splrep - 基本上,更高的 s 值会使样条曲线更加平滑。 - naught101
如果没有提供权重,则s = 0.0(插值)。这意味着此示例使用纯插值。 - Muhammad Yasirroni

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