如何在pandas中实现DataFrame逆groupby宽转长并添加累计行?
Pandas宽表转长表并新增累计行实现方案
核心思路
整个操作分三步完成:
- 把按列存储的分阶段数据从宽表转为行存储的长表格式
- 按项目ID计算所有阶段的天数总和,生成
cumulative类型的记录 - 拼接两部分数据并调整排序,得到最终结果
完整可运行代码
import pandas as pd # 构造原始示例数据 df = pd.DataFrame({ "project id": [112, 113], "phase 1": [29, 36], "phase 2": [157, 121], "phase 3": [213, 23] }) # 宽表转长表,自动识别所有phase开头的列 long_df = df.melt( id_vars="project id", value_vars=df.filter(like="phase").columns, var_name="phase", value_name="days" ) # 提取phase列的数字编号 long_df["phase"] = long_df["phase"].str.replace("phase ", "", regex=False) # 生成每个项目的累计天数字段 cumulative_df = df[["project id"]].copy() cumulative_df["phase"] = "cumulative" # 对所有phase列横向求和得到总天数 cumulative_df["days"] = df.filter(like="phase").sum(axis=1) # 拼接数据并调整排序 final_df = pd.concat([long_df, cumulative_df], ignore_index=True) # 增加临时排序键,保证每个项目下阶段1/2/3在前,累计值在最后 final_df["sort_tmp"] = final_df["phase"].apply(lambda x: int(x) if x.isdigit() else 99) final_df = final_df.sort_values( by=["project id", "sort_tmp"] ).drop(columns="sort_tmp").reset_index(drop=True)
运行结果
执行print(final_df)即可得到目标格式的数据集:
project id phase days 0 112 1 29 1 112 2 157 2 112 3 213 3 112 cumulative 399 4 113 1 36 5 113 2 121 6 113 3 23 7 113 cumulative 180
扩展说明
如果后续新增phase4、phase5等更多阶段列,无需修改核心逻辑,代码会自动识别所有带phase前缀的列完成转换和求和。
内容的提问来源于stack exchange,提问作者O K
相关产品推荐
相关产品推荐

