如何在Pandas数据框中实现带断年重启的3年滚动收益聚合
解决面板数据的3年连续滚动求和问题
针对你这个带年份缺失的面板数据滚动求和需求,我们可以用Pandas一步步来实现,思路是先排序、标记连续年份组,再在每个连续组内做滚动计算:
步骤1:排序数据
首先得把每个公司的年度数据按年份排好序,这是后续处理的基础:
import pandas as pd # 假设你的原始数据存在df里 df = df.sort_values(by=['ticker', 'year']).reset_index(drop=True)
步骤2:标记连续年份分组
核心是识别每个公司的连续年份区间,如果中间年份缺失,就把后面的年份归为新的分组:
# 计算每个公司内年份的差值 df['year_gap'] = df.groupby('ticker')['year'].diff() # 当差值不等于1时,标记为新分组,用cumsum生成分组ID df['continuous_group'] = (df['year_gap'] != 1).groupby(df['ticker']).cumsum()
这一步会给每个连续的年份段分配唯一的continuous_group,比如某公司有1985-1987连续三年,然后1993-1995,这两个区间会有不同的分组ID。
步骤3:在连续分组内计算3年滚动求和
接下来在每个ticker + continuous_group的组内,用滚动窗口计算3年求和,同时生成对应的年份范围:
def calculate_rolling_sum(group): # 滚动窗口大小为3,必须满足3个连续年份才计算(min_periods=3) rolling_sum = group['return_y'].rolling(window=3, min_periods=3).sum() # 生成年份范围字符串:比如窗口内第1年到第3年 group['3_years'] = group['year'].shift(2).astype(str) + '-' + group['year'].astype(str) # 只保留有有效滚动结果的行 result = group[rolling_sum.notna()].copy() result['return_y'] = rolling_sum.dropna() return result[['3_years', 'ticker', 'return_y']] # 应用到每个分组 final_df = df.groupby(['ticker', 'continuous_group']).apply(calculate_rolling_sum).reset_index(drop=True)
验证效果
比如用你给出的部分数据测试:原始数据里KO有1985和2015年的数据,中间年份缺失,所以这两个年份会被分到不同的连续组,不会产生跨缺失年份的滚动结果,完全符合你的要求。
最后整理结果
如果需要调整列的顺序或者格式,可以再做简单处理:
final_df = final_df[['3_years', 'ticker', 'return_y']]
这样得到的final_df就完全匹配你预期的输出格式啦!
内容的提问来源于stack exchange,提问作者tigio_33
相关产品推荐
相关产品推荐

