如何对带有多级列标识的DataFrame进行格式重塑(宽表转长表)
问题描述
我当前有一个dataframe(df1),格式如下所示:
| ID | F1_1 | F2_1r1 | F2_1r2 | F2_1r3 | F1_2 | F2_2r1 | F2_2r2 | F2_2r3 | F1_3 | F2_3r1 | F2_3r2 | F2_3r3 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 10 | 1 | 1 | 0 | 15 | 0 | 1 | 0 | 30 | 1 | 0 | 0 |
| 2 | 25 | 1 | 0 | 0 | 30 | 0 | 1 | 1 | 25 | 1 | 0 | 1 |
| 3 | 40 | 0 | 1 | 0 | 15 | 0 | 1 | 0 | 10 | 0 | 0 | 1 |
| 4 | 25 | 1 | 1 | 0 | 10 | 0 | 1 | 1 | 30 | 1 | 0 | 0 |
我希望对其重新格式化,调整为如下df2所示的排布结构:
| ID | F1_value | R1 | R2 | R3 | F1_x |
|---|---|---|---|---|---|
| 1 | 10 | 1 | 1 | 0 | 1 |
| 1 | 15 | 0 | 1 | 0 | 2 |
| 1 | 30 | 1 | 0 | 0 | 3 |
| 2 | 25 | 1 | 0 | 0 | 1 |
| 2 | 30 | 0 | 1 | 1 | 2 |
| 2 | 25 | 1 | 0 | 1 | 3 |
| 3 | 40 | 0 | 1 | 0 | 1 |
| 3 | 15 | 0 | 1 | 0 | 2 |
| 3 | 10 | 0 | 0 | 1 | 3 |
| 4 | 25 | 1 | 1 | 0 | 1 |
| 4 | 10 | 0 | 1 | 1 | 2 |
| 4 | 30 | 1 | 0 | 0 | 3 |
解决方案
这是典型的宽表转长表需求,两种实现方式如下:
方法1:循环拼接(逻辑直观,适合新手)
import pandas as pd # 假设你的原始数据已存入df1变量 result_list = [] for num in range(1, 4): # 提取对应编号的列组 part_df = df1[["ID", f"F1_{num}", f"F2_{num}r1", f"F2_{num}r2", f"F2_{num}r3"]].copy() # 统一重命名列 part_df.columns = ["ID", "F1_value", "R1", "R2", "R3"] # 新增分组标识列 part_df["F1_x"] = num result_list.append(part_df) # 拼接所有分组得到最终结果 df2 = pd.concat(result_list, ignore_index=True)
方法2:内置函数实现(代码简洁,适合批量扩展场景)
import pandas as pd # 统一列名格式方便匹配 df1.columns = df1.columns.str.replace(r"F2_(\d)r(\d)", r"F2_\1_\2", regex=True) # 第一次宽转长 df_long = pd.wide_to_long( df1, stubnames=["F1", "F2"], i="ID", j=["F1_x", "R_index"], sep="_", suffix=r"\d+" ).reset_index() # 第二次转换得到目标结构 df2 = df_long.pivot(index=["ID", "F1_x", "F1"], columns="R_index", values="F2")\ .rename(columns=lambda x: f"R{x}")\ .reset_index()\ .rename(columns={"F1": "F1_value"})\ .rename_axis(columns=None)
内容的提问来源于stack exchange,提问作者piper180
相关产品推荐
相关产品推荐

