6.4 使用 melt、pivot 与 stack 重塑数据
第 1 章介绍了整洁数据(tidy data):每行表示一个观测,每列表示一个变量,每张表表示一种观测单位。真实导出文件经常是宽格式,例如把 sales_2026_01、sales_2026_02 和 sales_2026_03 放在不同列名中。重塑会改变表示方式,但不应自动改变事实。
开始之前,先声明表的粒度(grain)——一行究竟代表什么——再确定哪些键应当唯一。仅凭表的形状,无法判断重复键是错误、重复测量还是合法明细。
用 melt 把列名移动到行中
假设源表每行代表一家门店,每个月销售额分别占一列:
value_columns = [
"sales_2026_01",
"sales_2026_02",
"sales_2026_03",
]
long = wide.melt(
id_vars=["store_id", "region"],
value_vars=value_columns,
var_name="month_key",
value_name="sales",
)每个测量列都会复制标识列;原测量列名进入 month_key,单元格数值进入统一的 sales 列。若输入有 行,并显式选择 个值列,结果通常有 行,包括测量值本身缺失的行。
要用明确规则从原列名解析月份:
long["month"] = pd.to_datetime(
long["month_key"].str.removeprefix("sales_"),
format="%Y_%m",
errors="raise",
)不要在持续变化的数据集中使用“标识列之外的所有列”。未来新增的 note 可能被误折叠到 sales 中,让文本和数值混合,并破坏 dtype。显式列出 value_vars,就等于把源模式预期写进代码。
常用不变量包括:
- 预期输出行数等于输入行数乘所选测量列数。
store_id–month等目标键符合预期唯一性。
- 非缺失数值单元格数量不变。
- 对可加指标,销售总量保持不变。
只有目标单元格唯一时才使用 pivot
方向相反的重塑会把行中的值移动到列:
wide_again = long.pivot(
index="store_id",
columns="month",
values="sales",
)pivot 只负责重排,不负责聚合。每个 store_id–month 组合最多只能有一个 sales。如果两行指向同一个目标单元格,pandas 会报错,因为它没有依据决定保留哪个事实。
先查看完整冲突组:
keys = ["store_id", "month"]
conflict = long.duplicated(keys, keep=False)
long.loc[conflict].sort_values(keys)错误重复应按第 5 章的证据流程修复。如果这些行是合法订单明细,且销售额可以相加,就使用有声明的聚合:
wide_total = long.pivot_table(
index="store_id",
columns="month",
values="sales",
aggfunc="sum",
)绝不能只为消除 pivot 报错而换成 pivot_table。聚合会改变粒度;默认均值对于许多总量、计数、余额和比率都不正确。要说明 sum、mean、first 或其他函数为何符合领域含义,并比较聚合前后的总量或分母。
多个 index 或 columns 字段可以产生多级索引(MultiIndex)。stack 把一个列层级移动到行索引,unstack 则把一个行索引层级移动到列:
stacked = wide_total.stack(future_stack=True).rename("sales")
round_trip = stacked.reset_index()当前 pandas 已把新版 stack 实现作为标准行为;在 pandas 2.1–2.3 中,future_stack=True 也能明确表达这一意图。该模式下不要同时传入旧版 dropna 或 sort 控制。测试往返时,应先排序并统一索引、列名称,因为表示元数据可能不同,即使观测完全一致。
宽格式网格可能包含一个从未出现在源表中的门店–月份缺失单元格。经过 stack 后,它与“源表确实有这一行、但销售额观测为缺失”的情况无法区分。如果这种差异重要,必须保留源键集合,再用它筛选往返行;直接调用 dropna 也会误删真实的缺失观测。
缺失组合需要特别小心。宽表中的缺失单元格可能表示“没有观测”,而零表示“观测到的总量为零”。重塑不能交换二者含义。
把重塑当成可测试契约
可靠的重塑应记录:
- 源粒度与目标粒度。
- 标识列和值列。
- 唯一性预期与任何聚合规则。
- 缺失组合的处理方式。
- 前后的行数、非缺失数量与领域总量。
- 操作本应可逆时的往返测试或等价不变量。
这些重塑工作为下一章做好准备。当位置、颜色、分组或面板都能从清楚的列映射时,Matplotlib 最容易使用;本节建立的长格式通常正好提供这种结构。