首页 > 解决方案 > 为什么 groupby 方法在 Pandas 的滚动总和计算中不起作用,我该如何解决?

问题描述

我有以下数据,我使用 Date 和 Ticker 作为索引进行多重索引,然后为每只股票添加 Vol 列的滚动总和。

原始数据:

Date,Ticker,SharePrice,Vol
2014-12-31,MSFT,10.79,16.24
2015-03-31,MSFT,19.44,14.94
2015-06-30,MSFT,3.73,19.79
2015-09-30,MSFT,3.76,6.52
2015-12-31,MSFT,10.56,17.91
2016-03-31,MSFT,13.56,11.96
2016-06-30,MSFT,16.27,19.79
2015-03-31,GM,18.22,9.92
2015-06-30,GM,17.16,18.69
2015-09-30,GM,15.92,17.45

这是我用来计算 vol 滚动总和的代码 - 请注意,我不希望滚动总和包含与不同 Ticker 相关的 vol(我尝试使用 gruopby 来阻止它,但它不起作用):

代码:

import pandas as pd

stocks = pd.read_csv("C:\\Users\\stocks.csv", index_col=["Date", "Ticker"])

stocks['RollingVol'] = stocks['Vol'].groupby(level=1).fillna(0).rolling(1095, min_periods=2).sum()

print(stocks)

这是我得到的结果:

Date,Ticker,SharePrice,Vol,RollingVol
2014-12-31,MSFT,10.79,16.24,
2015-03-31,MSFT,19.44,14.94,31.18
2015-06-30,MSFT,3.73,19.79,50.97
2015-09-30,MSFT,3.76,6.52,57.489999999999995
2015-12-31,MSFT,10.56,17.91,75.39999999999999
2016-03-31,MSFT,13.56,11.96,87.35999999999999
2016-06-30,MSFT,16.27,19.79,107.14999999999998
2015-03-31,GM,18.22,9.92,117.06999999999998
2015-06-30,GM,17.16,18.69,135.76
2015-09-30,GM,15.92,17.45,153.20999999999998

例如,我的问题是 GM(117.0699999)的第一个滚动总和条目包括 MSFT 值,而它应该只是 NaN(因为 min_periods = 2),然后 GM 的第二个条目应该是 9.92+18.69= 28.61 等等如下详述。我不明白为什么我的代码中的 groupby(level=1) 没有实现这一点,我该如何解决?

提前谢谢了

预期结果:

Date,Ticker,SharePrice,Vol,RollingVol
2014-12-31,MSFT,10.79,16.24,
2015-03-31,MSFT,19.44,14.94,31.18
2015-06-30,MSFT,3.73,19.79,50.97
2015-09-30,MSFT,3.76,6.52,57.49
2015-12-31,MSFT,10.56,17.91,75.4
2016-03-31,MSFT,13.56,11.96,87.36
2016-06-30,MSFT,16.27,19.79,107.15
2015-03-31,GM,18.22,9.92,
2015-06-30,GM,17.16,18.69,28.61
2015-09-30,GM,15.92,17.45,46.06

标签: pythonpandas

解决方案


您的代码的问题在于,当您调用groupby时,实际上只调用了以下内容中的第一个函数 ,在您的示例中只有fillna,这不会改变任何内容。

对前面groupby的最终(“合并”)结果执行以下方法的调用。

要计算您真正想要的,请将您的代码更改为:

stocks['RollingVol'] = stocks.Vol.groupby(level=1).apply(
lambda grp: grp.rolling(1095, min_periods=2).sum())

对于您的样本数据,结果是:

                   SharePrice    Vol  RollingVol
Date       Ticker                               
2014-12-31 MSFT         10.79  16.24         NaN
2015-03-31 MSFT         19.44  14.94       31.18
2015-06-30 MSFT          3.73  19.79       50.97
2015-09-30 MSFT          3.76   6.52       57.49
2015-12-31 MSFT         10.56  17.91       75.40
2016-03-31 MSFT         13.56  11.96       87.36
2016-06-30 MSFT         16.27  19.79      107.15
2015-03-31 GM           18.22   9.92         NaN
2015-06-30 GM           17.16  18.69       28.61
2015-09-30 GM           15.92  17.45       46.06

请注意,每个组中的第一个值是NaN,因为您想要 min_periods=2

最后一个要考虑的细节:您选择了一个非常大的窗口大小(1095)。这会让人怀疑您实际上想要一个从当前组开始到当前行的扩展窗口。就像是:

stocks['RollingVol'] = stocks.Vol.groupby(level=1).apply(
    lambda grp: grp.expanding(min_periods=2).sum())

或者,假设您每天都有数据,您可能想要 3 年的滚动总和。


推荐阅读