Pandas 向前与居中滚动计算¶
Pandas 中的 rolling 默认是向后(也就是向上)获取滚动窗口,如果需要向前(也就是向下)或者居中(也就是同时向上和向下)获取滚动窗口,则可以分别使用 pd.api.indexers.FixedForwardWindowIndexer 和 center=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 |
构造测试数据¶
我们首先构造一个简单的测试数据,并对它进行向前(也就是向下)或者居中(也就是同时向上和向下)获取滚动窗口,再求滚动窗口内的数据之和。
| 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
indexer = pd.api.indexers.FixedForwardWindowIndexer(window_size=2)
df["forward_using_FixedForwardWindowIndexer"] = (
df["data"].rolling(window=indexer, 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 实现居中获取滚动窗口¶
df["center_using_center"] = (
df["data"].rolling(window=3, center=True, 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 实现。