You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 09:02:51