按年度分组对Pandas DataFrame行求和:取前4个Value值
Pandas 按滚动4期求和生成汇总行解决方案
步骤1:数据导入与预处理
先统一日期格式,按维度分组后排序,避免时间乱序影响计算逻辑:
import pandas as pd # 构造示例数据 data = { 'Ac': ['Debt']*11, 'Type': ['Other']*11, 'Id': ['DE']*11, 'Date': ['2017-12-31', '2018-03-31', '2018-06-30', '2018-09-30', '2018-12-31', '2019-03-31', '2019-06-30', '2019-09-30', '2019-12-31', '2020-03-31', '2019-06-30'], 'Value': [5,4,3,2,5,6,1,5,2,3,4], 'Pe': ['12M']*11 } df = pd.DataFrame(data) # 转换日期格式,分组后按日期升序排序 df['Date'] = pd.to_datetime(df['Date']) df_sorted = df.groupby(['Ac', 'Type', 'Id', 'Pe'], as_index=False)\ .apply(lambda x: x.sort_values('Date'))\ .reset_index(drop=True)
步骤2:计算滚动窗口的求和结果
根据需求选择计算数值和或生成求和表达式:
选项A:计算数值求和
# 滚动4期求和,不足4期时取现有值的和 df_sorted['Rolling_Sum'] = df_sorted.groupby(['Ac', 'Type', 'Id', 'Pe'])['Value']\ .rolling(window=4, min_periods=1)\ .sum()\ .reset_index(drop=True)
选项B:生成求和表达式(如4+3+2+5)
def get_sum_expression(series): if len(series) == 1: return str(series.iloc[0]) return '+'.join(map(str, series.tolist())) df_sorted['Sum_Expr'] = df_sorted.groupby(['Ac', 'Type', 'Id', 'Pe'])['Value']\ .rolling(window=4, min_periods=1)\ .apply(get_sum_expression, raw=False)\ .reset_index(drop=True)
步骤3:筛选目标汇总行
按每4行取最后一行,不足4行的组取最后一行,满足你的两个条件:
# 给每组内的行编号 df_sorted['Row_Num'] = df_sorted.groupby(['Ac', 'Type', 'Id', 'Pe']).cumcount() + 1 # 筛选条件:行号为4的倍数,或组内最后一行且行号<4 filter_condition = (df_sorted['Row_Num'] % 4 == 0) | \ ((df_sorted['Row_Num'] == df_sorted.groupby(['Ac', 'Type', 'Id', 'Pe'])['Row_Num'].transform('max')) & (df_sorted['Row_Num'] < 4)) result = df_sorted[filter_condition].copy()
步骤4:整理最终结果格式
替换Value列并保留所需字段:
# 二选一:替换为数值求和或求和表达式 # result['Value'] = result['Rolling_Sum'] # 数值求和 result['Value'] = result['Sum_Expr'] # 求和表达式 # 保留目标列 final_result = result[['Ac', 'Type', 'Id', 'Date', 'Value', 'Pe']] print(final_result)
核心逻辑说明
- 跨年度兼容:滚动窗口不限制年度范围,只要是时间顺序内的前3条+当前条就会求和,最终保留当前行的日期。
- 不足4条处理:当组内数据不足4行时,自动保留最后一行的求和结果(单条数据时直接显示原值)。
内容的提问来源于stack exchange,提问作者Valeria Arango
相关产品推荐
相关产品推荐

