移动的滚动平均值 window

rolling mean with a moving window

我的数据框有一个每日价格列和一个 window 尺寸列:

df = pd.DataFrame(columns = ['price', 'window'],
             data = [[100, 1],[120, 2], [115, 2], [116, 2], [100, 4]])

df

        price   window
0        100    1
1        120    2
2        115    2
3        116    2
4        100    4

我想使用 window 列的 window 计算每行价格的滚动平均值。

结果是这样的:

df
    price   window  rolling_mean_price
0   100        1    100.00
1   120        2    110.00
2   115        2    117.50
3   116        2    115.50
4   100        4    112.75

我没有找到任何优雅的方法来使用 apply 并且我拒绝遍历我的 DataFrame 的每一行...

就原始速度和复杂性而言,最佳解决方案基于 summed-area table 的想法。这个问题可以看作是一维的table。您可以在下面找到几种方法,从好到坏排列。

Numpy + 线性复杂度

size = len(df['price'])
price = np.zeros(size + 1)
price[1:] = df['price'].values.cumsum()

window = np.clip(np.arange(size) - (df['window'].values - 1), 0, None)
df['rolling_mean_price'] = (price[1:] - price[window]) / df['window'].values

print(df)

输出

   price  window  rolling_mean_price
0    100       1              100.00
1    120       2              110.00
2    115       2              117.50
3    116       2              115.50
4    100       4              112.75

循环 + 线性复杂度

price = df['price'].values.cumsum()
df['rolling_mean_price'] = [(price[i] - float((i - w) > -1) * price[i-w]) / w for i, w in enumerate(df['window'])]

循环 + 二次复杂度

price = df['price'].values
df['rolling_mean_price'] = [price[i - (w - 1):i + 1].mean() for i, w in enumerate(df['window'])]

我不推荐使用 pandas.DataFrame.apply() (reasons described ) 的这种方法,但如果您坚持使用,这里有一个解决方案:

df['rolling_mean_price'] = df.apply(
    lambda row: df.rolling(row.window).price.mean().iloc[row.name], axis=1)

输出如下所示:

>>> print(df)
   price  window  rolling_mean_price
0    100       1              100.00
1    120       2              110.00
2    115       2              117.50
3    116       2              115.50
4    100       4              112.75