Pandas的层次化索引(MultiIndex)允许在一个轴上拥有多个索引层级,非常适合处理多维结构化数据,能够在单张表中实现多维度数据的组织与分析,避免拆分数据带来的操作复杂度。

层次化索引的创建方法
1. 从数组列表创建
可以直接传入多个数组组成的列表来构建层次化索引,外层数组对应第一层级,内层数组对应第二层级,索引层级顺序和数组顺序一致。
import pandas as pd
import numpy as np
# 创建两层行索引
arrays = [['2024-01', '2024-01', '2024-02', '2024-02'],
['北京', '上海', '北京', '上海']]
index = pd.MultiIndex.from_arrays(arrays, names=['月份', '城市'])
data = pd.DataFrame(np.random.randint(100, 500, size=4), index=index, columns=['销售额'])
print(data)
2. 从元组列表创建
每个元组对应一个索引组合,元组内的元素按顺序对应不同层级的索引值,适合已经整理好多维度键值对的场景。
# 从元组列表创建
tuples = [('2024-01', '北京'), ('2024-01', '上海'),
('2024-02', '北京'), ('2024-02', '上海')]
index = pd.MultiIndex.from_tuples(tuples, names=['月份', '城市'])
data = pd.DataFrame(np.random.randint(100, 500, size=4), index=index, columns=['销售额'])
print(data)
3. 从DataFrame创建
如果已经有包含多维度列的DataFrame,可以直接从现有列生成层次化索引,无需手动构造数组或元组。
# 从DataFrame创建
df = pd.DataFrame({
'月份': ['2024-01', '2024-01', '2024-02', '2024-02'],
'城市': ['北京', '上海', '北京', '上海'],
'销售额': np.random.randint(100, 500, size=4)
})
data = df.set_index(['月份', '城市'])
print(data)
层次化索引的常用操作
数据选取与切片
可以通过外层索引直接选取整层数据,也可以传入元组选取具体的多层级索引对应的数据,支持部分层级切片操作。
# 选取2024-01月份的所有数据
print(data.loc['2024-01'])
# 选取2024-01月份北京的销售额
print(data.loc[('2024-01', '北京'), '销售额'])
# 切片选取从2024-01到2024-02的所有数据
print(data.loc['2024-01':'2024-02'])
索引层级的交换与排序
可以通过swaplevel方法交换两个索引层级的顺序,使用sort_index方法按指定层级排序数据,方便后续按不同维度分析。
# 交换月份和城市两个索引层级
swapped_data = data.swaplevel('月份', '城市')
print(swapped_data)
# 按城市层级排序
sorted_data = swapped_data.sort_index(level='城市')
print(sorted_data)
索引的拆分与重置
可以将层次化索引拆分为普通列,也可以将普通列设置为层次化索引,灵活调整数据的存储结构。
# 重置索引,将层次化索引转为普通列 reset_data = data.reset_index() print(reset_data) # 再从普通列恢复层次化索引 recover_data = reset_data.set_index(['月份', '城市']) print(recover_data)
基于层次化索引的多维分析技巧
多维度聚合统计
结合groupby方法可以直接对层次化索引的不同层级进行聚合,快速得到不同维度的统计结果,无需额外调整数据结构。
# 按月份层级计算销售额总和 month_sum = data.groupby(level='月份').sum() print(month_sum) # 按城市层级计算销售额平均值 city_mean = data.groupby(level='城市').mean() print(city_mean) # 同时按月份和城市两个层级统计最大值 multi_stat = data.groupby(level=['月份', '城市']).max() print(multi_stat)
多维度数据透视
可以将层次化索引的数据转换为透视表结构,方便对比不同维度组合的数值,也可以使用unstack方法将内层索引展开为列。
# 将城市层级展开为列,得到透视结构 unstack_data = data.unstack(level='城市') print(unstack_data) # 使用pivot_table实现更复杂的多维透视 df = data.reset_index() pivot_table = pd.pivot_table(df, values='销售额', index='月份', columns='城市', aggfunc=np.sum) print(pivot_table)
跨层级数据计算
可以在不同索引层级之间进行计算,比如计算每个城市在各月份的销售额占当月总销售额的比例,无需拆分数据即可完成跨维度运算。
# 计算每个城市销售额占当月总销售额的比例 month_total = data.groupby(level='月份').sum() data['占比'] = data.apply(lambda x: x['销售额'] / month_total.loc[x.name[0], '销售额'], axis=1) print(data)
注意事项
- 层次化索引的层级名称尽量设置为有意义的字符串,方便后续通过名称选取层级,提升代码可读性。
- 对层次化索引做切片操作时,需要保证索引已经按对应层级排序,否则可能得到不符合预期的结果。
- 如果数据维度过多,层次化索引会让数据结构变得复杂,此时可以考虑使用
pivot_table或者拆分数据为多个子集处理。