【问题标题】:Rolling max with pandas on large datasets is very slow在大型数据集上使用 pandas 滚动最大值非常慢
【发布时间】:2018-02-03 01:40:51
【问题描述】:

我有一个 pandas 数据框 df,它的 DatatimeIndex 跨越大约 2 年、2 列和超过 3000 万行 float64 数据。我很快注意到df.rolling('1d').mean()df.rolling('1d').max() 之间的性能存在明显差异

>>> n=100000; import timeit; r=df[:n].rolling('1d'); timeit.timeit(lambda: r.max(), number=1)
2.5886592870228924
>>> n=100000; import timeit; r=df[:n].rolling('1d'); timeit.timeit(lambda: r.mean(), number=1)
0.011829487979412079
>>> n=1000000; import timeit; r=df[:n].rolling('1d'); timeit.timeit(lambda: r.max(), number=1)
53.8340517100296
>>> n=1000000; import timeit; r=df[:n].rolling('1d'); timeit.timeit(lambda: r.mean(), number=1)
0.06093513499945402

如您所见,df.rolling('1d').mean()df.rolling('1d').max() 快几百倍。我希望它会更快一些,因为计算最大熊猫可能必须在每一步跟踪滚动窗口中所有值的顺序。但是,很容易看到如何通过最多添加一个日志因子来实现这一点,所以我希望差异更小。如果这是最好的方法,那么使用 df.rolling('1d').max 对整个数据集来说将是一件痛苦的事情,因为看起来每次都需要几个小时。

之前遇到过 pandas 的效率问题(Series.iloc 索引),我很好奇这是否是 pandas 的问题,或者是否有更快的方法来解决这个问题。

 

编辑

最近在 pandas 的 master 分支中修复了这个问题。即使在完整的数据集上,滚动最大值现在也可以在 2.35 秒内计算出来,而之前可能需要几个小时。感谢 hexgnu 的修复。

>>> runtime(lambda: df.rolling('1d').max())
2.3093386580003425
>>> n=100000; import timeit; r=df[:n].rolling('1d'); timeit.timeit(lambda: r.max(), number=1)
0.015023122999991756
>>> n=1000000; import timeit; r=df[:n].rolling('1d'); timeit.timeit(lambda: r.max(), number=1)
0.08013121400290402
>>> n=10000000; import timeit; r=df[:n].rolling('1d'); timeit.timeit(lambda: r.max(), number=1)
0.6795377829985227
>>> import timeit; r=df.rolling('1d'); timeit.timeit(lambda: r.max(), number=1)
2.3540661859951797
>>> len(df)
32819278

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    Pandas 使用 linear scan over the window for every sample 运行 max 的幼稚实现。因此,它是线性复杂度乘以窗口大小,即每天有几百个样本,它会比平均值慢一百倍。

    可能的解决方法:按分钟计算,然后按小时超过此最大值,然后按天计算 - 这应该会产生一种对数效应,但常数可能会耗尽所有渐近优势。

    更好的解决方案:为 pandas 贡献 heap min_max 实现

    【讨论】:

    • 从 OP 问题的质量来看,他们很有可能会采纳您的最后建议。 +1 制作它。你们俩都做得很好。
    • 这里是这个问题:github.com/pandas-dev/pandas/issues/19521。这样做实际上非常简单
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-31
    • 2012-12-18
    • 2017-02-07
    • 1970-01-01
    • 2019-03-07
    相关资源
    最近更新 更多