求助:基于每日数据计算连续滚动季度累积值的实现方案
问题:基于每日DataFrame计算连续滚动季度(3个月)累积PP值
原始DataFrame
DATE PP 0 1964-01-01 1.0 1 1964-01-02 0.0 2 1964-01-03 0.0 3 1964-01-04 0.0 4 1964-01-05 0.0 ... ... 21788 2023-03-18 NaN 21789 2023-03-19 NaN 21790 2023-03-20 NaN 21791 2023-03-21 NaN 21792 2023-03-22 NaN
预期结果
cum_start cum_end PP 1964-12 1965-02 25 1965-01 1965-03 30 1965-02 1965-04 12 1965-03 1965-05 11 1965-04 1965-06 25 ... ... 2022-9 2022-11 14 2022-10 2022-12 22 2022-11 2023-01 15 2022-12 2023-02 21 2023-01 2023-03 40
尝试的问题代码
trimestres = df.set_index('DATE').rolling('90D')['PP'].sum() trimestres = trimestres.groupby([trimestres.index.year, trimestres.index.quarter]).tail(3) trimestres = trimestres.reset_index().rename(columns={'DATE': 'cum_start'}) trimestres['cum_end'] = trimestres['cum_start'] + pd.DateOffset(months=3)
问题分析
原代码存在三个核心问题:
- 窗口范围不准确:
rolling('90D')按固定90天计算,无法匹配自然月的3个月周期(不同月份天数不同,3个月可能是90-93天),导致累积区间不符合预期的连续3个日历月。 - 分组逻辑错误:
groupby([year, quarter]).tail(3)是提取每个季度的最后3天数据,和预期的「每个月作为起始的滚动3个月累积」完全不符。 - 结束日期计算错误:直接给
cum_start加3个月会得到起始日期+3个月的当天(如1964-12-01加3个月是1965-03-01),但预期的cum_end是3个月周期的最后一个月(1965-02)。
解决方案
以下代码严格按照「每个月起始,计算连续3个日历月的PP总和」逻辑实现,完全匹配预期格式:
步骤1:数据预处理
import pandas as pd # 转换DATE列为datetime类型并设为索引 df['DATE'] = pd.to_datetime(df['DATE']) df = df.set_index('DATE') # 处理缺失值:将NaN填充为0(根据业务需求调整,若缺失值无需计入则可跳过此步) df['PP'] = df['PP'].fillna(0)
步骤2:生成滚动窗口并计算累积值
# 生成所有有效起始月份(月初):从数据最早月份到最晚月份往前推2个月 start_months = pd.date_range( start=df.index.min().floor('M'), # 取最早日期所在月的第一天 end=df.index.max().floor('M') - pd.DateOffset(months=2), # 最晚可起始月份(保证有3个月数据) freq='MS' # 按月初频率生成 ) # 遍历每个起始月份,计算对应3个月周期的PP总和 result_list = [] for start in start_months: # 计算周期结束日期:起始月份+3个月的前一天(即第三个月的最后一天) end_date = start + pd.DateOffset(months=3) - pd.Timedelta(days=1) # 计算该周期内的PP总和 pp_total = df.loc[start:end_date, 'PP'].sum() # 格式化为年月字符串(如1964-12) cum_start = start.strftime('%Y-%m') cum_end = end_date.strftime('%Y-%m') # 添加到结果列表 result_list.append({'cum_start': cum_start, 'cum_end': cum_end, 'PP': pp_total}) # 转换为DataFrame result_df = pd.DataFrame(result_list)
说明
- 此方法严格基于自然日历月生成滚动窗口,确保每个窗口是连续3个完整月份(如1964-12至1965-02包含12月、1月、2月所有日期)。
- 自动过滤无法形成完整3个月窗口的起始月份(如数据最后一个月无法作为起始,因为没有后续2个月的数据)。
- 结果格式完全匹配预期的
cum_start(起始年月)、cum_end(结束年月)、PP(累积值)结构。
内容的提问来源于stack exchange,提问作者Javier
相关产品推荐
相关产品推荐

