
本文介绍一种高效、简洁的方法,利用multiindex和stack操作,将具有嵌套表头(年份+高低值)的原始dataframe重塑为结构清晰的长格式表格,适用于时间序列指标分析场景。
在实际数据分析中,我们常遇到以“复合列名”形式组织的宽格式数据——例如,同一指标(如low/high)按年份重复排列,且首两行分别承载语义层级(如year和level)。这类结构虽便于人工阅读,却不利于后续计算与建模。Pandas 提供了强大的索引与重塑工具,可将其一键转为标准的长格式(tidy data),关键在于正确构建列的多级索引(MultiIndex)并合理使用 stack()。
以下为完整实现流程:
import pandas as pd
import numpy as np
# 构造原始数据(模拟典型“双层表头”结构)
data = {
0: ['parameter', '', 'foo', 'bar'],
1: [2001, 'low', 1, np.nan],
2: [2001, 'high', 2, np.nan],
3: [2002, 'low', 7, 12],
4: [2002, 'high', 8, 13],
}
df = pd.DataFrame(data)
# 步骤1:提取列级语义 → 构建 MultiIndex
# 取第0行(年份)和第1行(low/high)作为两级列名(跳过第0列,因其为行索引标识)
years = df.iloc[0, 1:] # [2001, 2001, 2002, 2002]
levels = df.iloc[1, 1:] # ['low', 'high', 'low', 'high']
idx = pd.MultiIndex.from_arrays([years, levels], names=('year', 'level'))
# 步骤2:清理数据主体 → 设置行索引 + 重命名列轴
df_clean = (df.iloc[2:] # 跳过前两行(表头)
.set_index(0) # 将第0列('foo', 'bar')设为行索引,命名为 'parameter'
.set_axis(idx, axis=1) # 应用新构建的 MultiIndex 到列
.rename_axis('parameter') # 显式命名索引轴
)
# 步骤3:重塑 → stack 展开 level 维度,reset_index 标准化
result = df_clean.stack(level=0).reset_index()
result.columns = ['parameter', 'year', 'level', 'value'] # 可选:重命名列提升可读性
# 若需进一步 pivot 成 'low'/'high' 为列(即目标输出格式),执行:
final = result.pivot(index=['parameter', 'year'], columns='level', values='value') \
.reset_index() \
.rename_axis(None, axis=1)运行后得到目标结构:
parameter year high low 0 bar 2002 13.0 12.0 1 foo 2001 2.0 1.0 2 foo 2002 8.0 7.0
✅ 关键要点总结: MultiIndex.from_arrays() 是构建语义化列索引的核心,务必确保传入数组长度一致且顺序对应; set_axis(..., axis=1) 替代手动赋值 df.columns = ...,更安全且支持链式调用; stack(0) 默认展开最内层列索引(即 'level'),若有多层需显式指定 level 参数; 最终 pivot() 可选——若原始需求是“每个 level 单独成列”,则必须补此步;若接受 level 作为变量列,则 stack().reset_index() 已足够(更符合 tidy data 原则)。
该方法鲁棒性强,可轻松扩展至更多层级(如增加地区、产品线等),是处理报表导出类非标准数据的推荐范式。










