python - 为什么 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
解决方案
您的代码的问题在于,当您调用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 年的滚动总和。
推荐阅读
- pandas - 如何将值与熊猫数据框中的列值进行比较
- sql - Oracle SQL 在表中插入日期
- c# - 如果类型参数约束指定类型,为什么不能从用法推断类型参数?
- performance - Azure VM 监控默认运行状况标准警报通知
- ace-editor - Ace 编辑器未编辑文本
- android - 滑动开始时,向上滑动面板完全打开。
- visual-studio-code - vscode, emacs 所有输入字段中的导航快捷方式
- arrays - Django:查询字符串中的数组 foo[]=bar1&foo[]=bar2
- 3d - 如何根据点的类别制作 3D 密度图
- matlab - 为什么用空单元构建 MATLAB 结构对象会创建一个空结构?