Python 如何前瞻性地使用函数

Python 如何前瞻性地使用函数,python,pandas,Python,Pandas,假设我有一个时间序列: 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

假设我有一个时间序列:

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
如果我使用一个滚动函数,例如滚动求和,我可以得到我想要的向后滚动计算行为:

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天,然后对三列求和,但必须有一个更优雅的解决方案

为什么不在相反的序列上执行此操作(并反转答案):


也许你可以试试
瓶颈
模块。当
ts
较大时,
瓶颈
pandas


瓶颈
还有其他滚动功能,如
移动最大值
移动argmin
移动秩
,我努力解决了这个问题,然后找到了使用shift的简单方法

如果您希望在接下来的10个周期内获得滚动总和,请尝试:

df['NewCol'] = df['OtherCol'].shift(-10).rolling(10, min_periods = 0).sum()

我们使用shift,这样“OtherCol”会比通常显示的位置提前10行,然后我们对前10行进行滚动求和。因为我们移位了,所以前10行实际上是未移位列的未来10行。:)

熊猫最近添加了一项新功能,使您能够实现前瞻性滚动。您必须升级到pandas 1.1.0才能获得该版本


我在大约一年前发现的,所以看起来还没有“官方”的支持。但是,发布在那里的临时解决方案也不能满足我在边缘的需求(我的示例中18/19仍然是空白)Pandas 1.1添加了对前瞻性窗口操作的“支持”,但当我尝试将其应用于此数据时,我的解释器出现故障。。。也许这还不支持向前的datetime窗口,但最终会支持。聪明的回答,谢谢。尽管只有当所有日期都在一个范围内时,这才有效。在您的情况下,您没有指定频率。例如,当您指定freq='D'时,此解决方案不再有效。因此,如果我有丢失的数据或可变的采样频率,这将不起作用。这似乎是一个真正有价值的功能,可以正确地实现。有人知道它是否在管道中吗?@user2543645我对此提出了一个问题。我没有意识到这在某些情况下是行不通的,很有趣。你能先重新采样(以获得一致的频率),然后反向滚动吗?我认为这应该行得通,但前提是你要按照你想要的频率重新采样。如果您有稀疏的数据,这可能会大大增加设置的大小。例如,如果您在不同年份收集了几天的每小时观察值,则必须添加数千个空值。如果有一个更为原生的支持,它的行为与rolling_*完全相同,只是在另一个方向。这似乎是一个不错的方法,但我相信您会丢失最初的10行,不是吗?只有在您有一系列完整的不间断日期时,这才有效。您不能使用rolling()可以使用的“#D”窗口
import bottleneck as bn
result = bn.move_sum(ts[::-1], window=3, min_count=1)[::-1]
df['NewCol'] = df['OtherCol'].shift(-10).rolling(10, min_periods = 0).sum()
indexer = pd.api.indexers.FixedForwardWindowIndexer(window_size=3)
ts.rolling(window=indexer, min_periods=1).sum()