
本文讲解 Pandas 中 MultiIndex 对象的内部结构,澄清 levels 和 codes(非 labels)是其核心组成,说明为何打印时默认不显示它们,并演示如何正确访问与验证。
本文讲解 pandas 中 multiindex 对象的内部结构,澄清 `levels` 和 `codes`(非 `labels`)是其核心组成,说明为何打印时默认不显示它们,并演示如何正确访问与验证。
在使用 Pandas 构建多级索引(MultiIndex)时,初学者常误以为 levels 和 codes(旧版本中曾称 labels,但自 pandas 0.24+ 起已统一为 codes)应直接出现在对象的字符串表示中。实际上,MultiIndex 的默认 __repr__ 仅以可读形式展示元组序列(如 ('a', 1)),并不显式渲染其底层结构——这并非构造失败,而是设计使然。
以下代码构建了一个典型的二维分层索引:
import pandas as pd inside = ['a', 'a', 'a', 'b', 'b', 'b'] outside = [1, 2, 3, 1, 2, 3] zipped = list(zip(inside, outside)) hier_zipped = pd.MultiIndex.from_tuples(zipped) print(hier_zipped)
输出为:
MultiIndex([('a', 1),
('a', 2),
('a', 3),
('b', 1),
('b', 2),
('b', 3)],
)该结果完全等价于显式指定 levels 和 codes 构造的对象:
# 等价构造(无需手动计算)
pd.MultiIndex(
levels=[['a', 'b'], [1, 2, 3]],
codes=[[0, 0, 0, 1, 1, 1], [0, 1, 2, 0, 1, 2]]
)要验证结构一致性,需主动访问其属性:
print("Levels (唯一值分层):")
print(hier_zipped.levels) # → FrozenList([['a', 'b'], [1, 2, 3]])
print("\nCodes (整数编码映射):")
print(hier_zipped.codes) # → FrozenList([[0, 0, 0, 1, 1, 1], [0, 1, 2, 0, 1, 2]])⚠️ 关键注意事项:
- codes 是当前标准属性名,labels 已弃用(在较新 pandas 版本中调用会触发 AttributeError);
- levels 和 codes 均返回 FrozenList,不可原地修改,确保索引不可变性;
- 若需调试或序列化索引结构,应显式打印 .levels 和 .codes,而非依赖 print(mi) 的简略输出;
- 使用 pd.MultiIndex.from_tuples()、.from_arrays() 或 .from_product() 等工厂方法时,pandas 自动推导并优化 levels/codes,无需手动干预。
理解 levels(各层级的去重有序值)与 codes(对应位置的整数索引)的分离设计,是掌握 MultiIndex 高效内存布局与向量化操作的基础——它使重复层级值仅存储一次,大幅提升大数据量下的索引性能。










