跳转至

Pandas 向前与居中滚动计算

Pandas 中的 rolling 默认是向后(也就是向上)获取滚动窗口,如果需要向前(也就是向下)或者居中(也就是同时向上和向下)获取滚动窗口,则可以分别使用 pd.api.indexers.FixedForwardWindowIndexercenter=True 来实现。

本文还使用了 .shift(-1) 实现向前或者居中获取滚动窗口,并对比了这种方法与上述方法所得结果的差异。

data forward_using_FixedForwardWindowIndexer forward_using_shift center_using_center center_using_shift
0 1.0 3.0 3.0 3.0 3.0
1 2.0 2.0 2.0 3.0 3.0
2 NaN 4.0 4.0 6.0 6.0
3 4.0 9.0 9.0 9.0 9.0
4 5.0 5.0 NaN 9.0 NaN

构造测试数据

我们首先构造一个简单的测试数据,并对它进行向前(也就是向下)或者居中(也就是同时向上和向下)获取滚动窗口,再求滚动窗口内的数据之和。

Python
import pandas as pd
import numpy as np

df = pd.DataFrame({"data": [1, 2, np.nan, 4, 5]})
df
data
0 1.0
1 2.0
2 NaN
3 4.0
4 5.0

使用 pd.api.indexers.FixedForwardWindowIndexer 实现向前获取滚动窗口

参考:stackoverflow - Left-align a pandas rolling object

Python
indexer = pd.api.indexers.FixedForwardWindowIndexer(window_size=2)
df['forward_using_FixedForwardWindowIndexer'] = df['data'].rolling(window=indexer, min_periods=1).sum()

使用 .shift(-1) 实现向前获取滚动窗口

Python
df['forward_using_shift'] = df['data'].rolling(window=2, min_periods=1).sum().shift(-1)
data forward_using_FixedForwardWindowIndexer forward_using_shift
0 1.0 3.0 3.0
1 2.0 2.0 2.0
2 NaN 4.0 4.0
3 4.0 9.0 9.0
4 5.0 5.0 NaN

对比 pd.api.indexers.FixedForwardWindowIndexer.shift(-1)

pd.api.indexers.FixedForwardWindowIndexer 构造的 indexer 对于尾部的数据也能进行计算,而 .shift() 本质上是先做常规的向后(也就是向上)滚动计算,再将所得结果向上移动 window -1 行。因此,.shift(-1) 所得结果的最后一个数据必然是 NaN

如果我们希望最后几个值也能用尽可能多的数据进行计算,则建议用 pd.api.indexers.FixedForwardWindowIndexer 实现。

使用 center=True 实现居中获取滚动窗口

参考:pandas.DataFrame.rolling

Python
df['center_using_center'] = df['data'].rolling(window=3, center=True, min_periods=1).sum()

使用 .shift(-1) 实现居中获取滚动窗口

Python
df['center_using_shift'] = df['data'].rolling(window=3, min_periods=1).sum().shift(-1)
data center_using_center center_using_shift
0 1.0 3.0 3.0
1 2.0 3.0 3.0
2 NaN 6.0 6.0
3 4.0 9.0 9.0
4 5.0 9.0 NaN

对比 center=True.shift(-1)

center=True 构造的 indexer 对于尾部的数据也能进行计算,而 .shift() 本质上是先做常规的向后(也就是向上)滚动计算,再将所得结果向上移动 (window - 1) / 2 行。因此,.shift(-1) 所得结果的最后一个数据必然是 NaN

如果我们希望最后几个值也能用尽可能多的数据进行计算,则建议用 center=True 实现。

评论