我對計算大型一維 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 獲得類似的性能?
與熊貓相比,如何在 numpy 的大視窗上獲得類似的性能?
uj5u.com熱心網友回復:
TL;DR:這兩個版本使用非常不同的演算法。
這個sliding_window_view技巧很好地解決了小視窗的滾動平均問題,但這不是一種干凈的方法,也不是一種有效的方法,尤其是對于大視窗。事實上,Numpy 計算一個平均值并記錄一個滾動平均值,因此沒有明確的資訊表明用戶是為了計算其他東西而大步作弊。所提供的實施numpy的運行在O(n * w)其中n是陣列大小和w視窗大小。Pandas 確實有需要計算滾動平均值的資訊,因此它使用了更有效的演算法。在熊貓演算法的運行O(n)時間。有關它的更多資訊,請閱讀這篇文章。
這是一個更快的 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
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/383413.html
