滚动统计性能:pandas vs. numpy strides
Posted
技术标签:
【中文标题】滚动统计性能:pandas vs. numpy strides【英文标题】:Rolling statistics performance: pandas vs. numpy strides 【发布时间】:2022-01-18 22:26:28 【问题描述】:我有兴趣在大型一维 numpy 数组上计算滚动窗口中的统计信息。对于小窗口大小,使用 numpy strides (a la numpy.lib.stride_tricks.sliding_window_view
) 比 pandas 滚动窗口实现更快,但对于大窗口大小则相反。
考虑以下几点:
import numpy as np
from numpy.lib.stride_tricks import sliding_window_view
import pandas as pd
data = np.random.randn(10**6)
data_pandas = pd.Series(data)
window = 2
%timeit np.mean(sliding_window_view(data, window), axis=1)
# 19.3 ms ± 255 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit data_pandas.rolling(window).mean()
# 34.3 ms ± 688 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
window = 1000
%timeit np.mean(sliding_window_view(data, window), axis=1)
# 302 ms ± 8.01 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit data_pandas.rolling(window).mean()
# 31.7 ms ± 958 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
result_numpy = np.mean(sliding_window_view(data, window), axis=1)
result_pandas = data_pandas.rolling(window).mean()[window-1:]
np.allclose(result_numpy, result_pandas)
# True
对于较大的窗口大小,pandas 实现实际上更快,而 numpy 实现慢得多。
在 pandas 的底层发生了什么,我们如何使用 numpy 获得类似的性能?
与 pandas 相比,我如何在 numpy 的大窗口上获得类似的性能?
【问题讨论】:
这个问题是开放式的,不适用于已发布的答案。您可能会考虑将问题中的最后一条语句改写为“与 Pandas 相比,我如何在 NumPy 的大窗口上获得类似的性能?”,假设有答案。讨论内部实现细节通常超出了 *** 问题的范围。 与sliding_window
的创建时间基本相同,但最大的时间差异在于取(999999, 2)
与(999001, 1000)
的平均值。这是合理的。查看pd.rolling(...).mean
的文档,我看到一个engine
参数,它可能是cython
或numba
。所以pandas
正在做它自己专门的compiled.calculation。
已修复 @scootermefecit 感谢您的建议。
【参考方案1】:
TL;DR:这两个版本使用非常不同的算法。
sliding_window_view
技巧可以很好地解决小窗口的滚动平均问题,但这不是一种干净的方法,也不是一种有效的方法,尤其是对于大窗口。实际上,Numpy 计算平均值并记录滚动平均值,因此没有明确的信息表明用户正在大步作弊以计算其他内容。 提供的 Numpy 实现在 O(n * w)
中运行,其中 n
是数组大小,w
是窗口大小。 Pandas 确实具有需要计算滚动平均值的信息,因此它使用了更有效的算法。 Pandas 算法在 O(n)
时间运行。有关它的更多信息,请阅读this post。
这是一个更快的 Numpy 实现:
cumsum = np.cumsum(data)
invSize = 1. / window
(cumsum[window-1:] - np.concatenate([[0], cumsum[:-window]])) * invSize
这是我机器上的性能结果:
Naive Numpy version: 193.2 ms
Pandas version: 33.1 ms
Fast Numpy version: 8.5 ms
【讨论】:
感谢您提供更快的 numpy rolling mean 实现。我也对滚动方差(或标准偏差)感兴趣,正如预期的那样,使用 numpy 步幅甚至更慢,但使用 pandas 仍然非常快。您是否知道滚动方差的类似 numpy 实现? 对于数值稳定的方差并不容易,因为在计算过程中均值会发生变化。这篇文章可能对您有所帮助:***.com/questions/5147378/rolling-variance-algorithm以上是关于滚动统计性能:pandas vs. numpy strides的主要内容,如果未能解决你的问题,请参考以下文章