如何在前瞻性基础上使用Pandas的rolling_*函数
假设我有一个时间序列:
In[138] rng = pd.date_range('1/10/2011', periods=10, freq='D')
In[139] ts = pd.Series(randn(len(rng)), index=rng)
In[140]
Out[140]:
2011-01-10 0
2011-01-11 1
2011-01-12 2
2011-01-13 3
2011-01-14 4
2011-01-15 5
2011-01-16 6
2011-01-17 7
2011-01-18 8
2011-01-19 9
Freq: D, dtype: int64
如果我使用一些滚动函数,比如说滚动求和(rolling_sum),我可以得到我想要的效果,这种效果是向后看(即计算之前的数据):
In [157]: pd.rolling_sum(ts, window=3, min_periods=0)
Out[157]:
2011-01-10 0
2011-01-11 1
2011-01-12 3
2011-01-13 6
2011-01-14 9
2011-01-15 12
2011-01-16 15
2011-01-17 18
2011-01-18 21
2011-01-19 24
Freq: D, dtype: float64
但是如果我想要做一个向前看的求和呢?我试过像这样做:
In [161]: pd.rolling_sum(ts.shift(-2, freq='D'), window=3, min_periods=0)
Out[161]:
2011-01-08 0
2011-01-09 1
2011-01-10 3
2011-01-11 6
2011-01-12 9
2011-01-13 12
2011-01-14 15
2011-01-15 18
2011-01-16 21
2011-01-17 24
Freq: D, dtype: float64
但这并不是我想要的效果。我希望得到的结果是:
2011-01-10 3
2011-01-11 6
2011-01-12 9
2011-01-13 12
2011-01-14 15
2011-01-15 18
2011-01-16 21
2011-01-17 24
2011-01-18 17
2011-01-19 9
也就是说,我想要“当前”这一天加上接下来的两天的总和。现在的解决方案不够好,因为我很在意边缘的情况。我知道我可以通过设置两个额外的列,分别向后移动1天和2天,然后把这三列相加来手动解决这个问题,但我觉得应该有更优雅的解决办法。
5 个回答
0
试试这个,适用于一个大小为3的滑动窗口:
window = 3
ts.rolling(window).sum().shift(-window + 1)
1
你可以试试 bottleneck
这个模块。当 ts
很大的时候,bottleneck
的速度比 pandas
快很多。
import bottleneck as bn
result = bn.move_sum(ts[::-1], window=3, min_count=1)[::-1]
而且 bottleneck
还有其他的滚动函数,比如 move_max
、move_argmin
和 move_rank
。
10
我之前也遇到过这个问题,后来发现用shift这个方法很简单。
如果你想要计算接下来10个周期的滚动总和,可以试试:
df['NewCol'] = df['OtherCol'].shift(-10).rolling(10, min_periods = 0).sum()
我们使用shift的原因是让“OtherCol”这一列的数据提前10行显示,这样我们就可以对之前的10行进行滚动求和。因为我们进行了位移,所以之前的10行实际上是未位移列的未来10行的数据。 :)
14
Pandas最近增加了一个新功能,让你可以实现向前看的滚动计算。你需要升级到pandas 1.1.0版本才能使用这个新功能。
indexer = pd.api.indexers.FixedForwardWindowIndexer(window_size=3)
ts.rolling(window=indexer, min_periods=1).sum()
31
为什么不直接在反转后的序列上操作呢(然后再把结果反转回来):
In [11]: pd.rolling_sum(ts[::-1], window=3, min_periods=0)[::-1]
Out[11]:
2011-01-10 3
2011-01-11 6
2011-01-12 9
2011-01-13 12
2011-01-14 15
2011-01-15 18
2011-01-16 21
2011-01-17 24
2011-01-18 17
2011-01-19 9
Freq: D, dtype: float64