【发布时间】: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
【问题讨论】: