
本文介绍如何通过 melt + pivot_table 组合操作,将原始 dataframe 中的多个数值列(如 value_1、value_2)转化为行索引(新增 head_3 层级),同时仅保留 time 作为列头,从而获得更灵活的多级索引透视结构。
本文介绍如何通过 melt + pivot_table 组合操作,将原始 dataframe 中的多个数值列(如 value_1、value_2)转化为行索引(新增 head_3 层级),同时仅保留 time 作为列头,从而获得更灵活的多级索引透视结构。
在使用 Pandas 进行数据透视时,pivot_table 默认会将 values 参数指定的列作为新列(即横向展开),而将 index 和 columns 分别作为行/列索引。但当目标是将原数值列(如 value_1, value_2)变为行标签,同时让时间维度(time)成为唯一列头时,直接调用 pivot_table 并不能满足需求——此时需先“长化”数据,再重新透视。
核心思路是两步法:
-
melt()长格式转换:将value_1和value_2合并为一列(如head_3),对应值存入新列(如val); -
pivot_table()重透视:以head_1,head_2,head_3为复合索引,time为列,val为值,完成“值变行、时间变列”的布局。
以下是完整可运行示例:
import pandas as pd
# 构造原始数据
x = pd.DataFrame([
[1, 'step', 'id', 22, 33],
[2, 'step', 'id', 55, 66]
], columns=['time', 'head_1', 'head_2', 'value_1', 'value_2'])
# 第一步:melt 转为长格式
melted = x.melt(
id_vars=['time', 'head_1', 'head_2'], # 保持不变的标识列
value_vars=['value_1', 'value_2'], # 待“融化”的数值列
var_name='head_3', # 新增列名,存放原列名('value_1'/'value_2')
value_name='val' # 新增列名,存放对应数值
)
# 第二步:以三元组为索引,time 为列进行透视
result = melted.pivot_table(
index=['head_1', 'head_2', 'head_3'],
columns='time',
values='val',
aggfunc='first' # 因每组唯一,'first' 可安全去重;若存在重复组合,可依需改用 'sum'/'mean' 等
)
print(result)
输出结果为:
time 1 2
head_1 head_2 head_3
step id value_1 22 55
value_2 33 66
✅ 关键要点说明:
-
melt()是实现“列→行”转换的基石操作,不可跳过; -
var_name='head_3'显式命名新生成的变量列,使其自然融入多级索引结构; -
pivot_table(..., aggfunc='first')在确保无重复键的前提下避免警告;若原始数据中(head_1, head_2, head_3, time)存在多对一关系,应根据业务逻辑选择合适的聚合函数; - 最终结果为
pd.DataFrame,其行索引为MultiIndex(三级),列索引为Int64Index([1, 2]),完全符合目标结构。
该方法通用性强,适用于任意数量的数值列(只需扩展 value_vars 列表),是 Pandas 中实现“值维展开为行”的标准实践。










