如何在Pandas中按多列分组并基于日期偏移计算滚动求和?
解决分组后工作日滚动求和的问题
我来帮你搞定这个滚动求和的问题!首先咱们先理清你原来代码的问题所在,然后一步步修正得到正确结果。
问题分析
你遇到的问题其实不是负数导致的,而是代码逻辑顺序错了:你先对原始数据做滚动求和,再按日期聚合,这会导致同一天的多条数据被重复计算在滚动窗口里。正确的步骤应该是先按日期聚合每日数据,再对聚合后的结果做滚动求和。
另外,你提到的"2个工作日的移动窗口",我们需要先把每日同组同类型的数据合并,再对排序后的日期做滚动计算。
正确解决方案步骤
1. 先聚合每日数据
首先把同一天、同group、同type的value求和,得到每日的总数值:
import pandas as pd import numpy as np import datetime # 生成你的示例数据 vals = [-4,17,-4,-16,2,20,3,10,-17,-8,-21,2,0,-11,16,-24,-10,-21,5,12,14,9,-15,-15] grp = ['X']*6 + ['Y'] * 6 + ['X']*6 + ['Y'] * 6 typ = ['foo']*12+['bar']*12 dat = ['19/01/18','19/01/18','22/01/18','22/01/18','23/01/18','24/01/18'] * 4 df = pd.DataFrame({'group': grp,'type':typ,'value':vals,'date':dat}) df.date = pd.to_datetime(df.date) # 第一步:按group、type、date聚合,得到每日总和 df_daily = df.groupby(['group', 'type', 'date'])['value'].sum().reset_index() # 确保每个组内的日期按顺序排列 df_daily = df_daily.sort_values(['group', 'type', 'date'])
2. 执行2个工作日的滚动求和
这里分两种场景,根据你的需求选择:
场景A:窗口包含当前工作日和前1个工作日(共2个连续工作日)
如果你的窗口是固定的2个连续工作日(不管日期间隔,只要是排序后的前一个工作日),用window=2:
# 按group+type分组,做滚动2个工作日的求和 result = df_daily.groupby(['group', 'type']).rolling(window=2, on='date', min_periods=1)['value'].sum().reset_index() # min_periods=1 确保第一个工作日(没有前一个)也能返回自身的数值
场景B:窗口包含过去2个自然日内的所有工作日
如果你的窗口是基于自然日的2天(只包含该时间段内的工作日),用rolling('2D'):
result = df_daily.groupby(['group', 'type']).rolling('2D', on='date')['value'].sum().reset_index()
验证结果
以group=X, type=foo为例,聚合后的每日数据是:
| group | type | date | value |
|---|---|---|---|
| X | foo | 2018-01-19 | 13 |
| X | foo | 2018-01-22 | -20 |
| X | foo | 2018-01-23 | 2 |
| X | foo | 2018-01-24 | 20 |
用场景A的代码得到的滚动求和结果是:
| group | type | date | value |
|---|---|---|---|
| X | foo | 2018-01-19 | 13 |
| X | foo | 2018-01-22 | -7 |
| X | foo | 2018-01-23 | -18 |
| X | foo | 2018-01-24 | 22 |
这个结果完全正确,不管value是正还是负都能正常计算。
内容的提问来源于stack exchange,提问作者Bonners
相关产品推荐
相关产品推荐

