news 2026/5/14 18:07:28

模块二-数据选择与索引——11. 多层索引(MultiIndex)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
模块二-数据选择与索引——11. 多层索引(MultiIndex)

11. 多层索引(MultiIndex)

1. 概述

多层索引(MultiIndex)是 Pandas 中处理层次化数据的重要特性。它允许一个 DataFrame 拥有多个层级的行索引或列索引,适用于分组数据、时间序列、面板数据等复杂场景。

importpandasaspdimportnumpyasnp# 创建示例数据:多层级数据data={'年份':[2023,2023,2023,2023,2024,2024,2024,2024],'季度':['Q1','Q2','Q3','Q4','Q1','Q2','Q3','Q4'],'销售额':[100,120,110,130,150,160,140,170],'利润':[20,25,22,28,35,38,32,40]}df=pd.DataFrame(data)print("原始数据:")print(df)

2. 创建多层索引

2.1 从 DataFrame 创建

# 使用 set_index 创建多层索引multi_df=df.set_index(['年份','季度'])print("多层索引 DataFrame:")print(multi_df)print(f"\n索引结构:{multi_df.index}")print(f"索引层级:{multi_df.index.names}")

2.2 从数组创建

# 使用 pd.MultiIndex 创建arrays=[['A','A','B','B'],[1,2,1,2]]index=pd.MultiIndex.from_arrays(arrays,names=['字母','数字'])df_multi=pd.DataFrame({'值':[10,20,30,40]},index=index)print("从数组创建:")print(df_multi)

2.3 从元组列表创建

# 使用 from_tuplestuples=[('A',1),('A',2),('B',1),('B',2)]index=pd.MultiIndex.from_tuples(tuples,names=['字母','数字'])df_multi=pd.DataFrame({'值':[10,20,30,40]},index=index)print("从元组创建:")print(df_multi)

2.4 从笛卡尔积创建

# 使用 from_productletters=['A','B']numbers=[1,2,3]index=pd.MultiIndex.from_product([letters,numbers],names=['字母','数字'])df_multi=pd.DataFrame({'值':range(6)},index=index)print("从笛卡尔积创建:")print(df_multi)

3. 多层索引的访问

3.1 使用 loc 访问

multi_df=df.set_index(['年份','季度'])print("原始数据:")print(multi_df)# 访问第一层print("\n访问2023年数据:")print(multi_df.loc[2023])# 访问完整层级print("\n访问2023年Q1:")print(multi_df.loc[(2023,'Q1')])# 访问多个print("\n访问2023年Q1和Q2:")print(multi_df.loc[(2023,['Q1','Q2'])])

3.2 使用 xs 方法交叉选择

# xs 方法用于交叉选择multi_df=df.set_index(['年份','季度'])# 选择所有年份的 Q1print("所有年份的 Q1:")print(multi_df.xs('Q1',level='季度'))# 选择2023年的所有季度print("\n2023年所有季度:")print(multi_df.xs(2023,level='年份'))# 保持层级print("\n保持层级结构:")print(multi_df.xs('Q1',level='季度',drop_level=False))

4. 多层索引的切片

multi_df=df.set_index(['年份','季度'])# 按第一层切片print("2023-2024年数据:")print(multi_df.loc[2023:2024])# 按完整层级切片print("\n2023年Q1到2024年Q2:")print(multi_df.loc[(2023,'Q1'):(2024,'Q2')])# 使用 pd.IndexSliceidx=pd.IndexSliceprint("\n使用 IndexSlice:")print(multi_df.loc[idx[2023,'Q1':'Q3'],:])

5. 多层索引的层级操作

5.1 交换层级

multi_df=df.set_index(['年份','季度'])print("原始:")print(multi_df)# 交换层级swapped=multi_df.swaplevel()print("\n交换层级后:")print(swapped)# 指定交换的层级swapped2=multi_df.swaplevel(0,1)print("\n指定交换层级:")print(swapped2)

5.2 排序层级

# 创建乱序的多层索引arrays=[['B','A','B','A'],[2,1,1,2]]index=pd.MultiIndex.from_arrays(arrays,names=['字母','数字'])df_unsorted=pd.DataFrame({'值':[10,20,30,40]},index=index)print("乱序索引:")print(df_unsorted)# 排序索引sorted_df=df_unsorted.sort_index()print("\n排序后:")print(sorted_df)

5.3 重设层级

multi_df=df.set_index(['年份','季度'])# 重置所有层级reset_all=multi_df.reset_index()print("重置所有层级:")print(reset_all)# 重置指定层级reset_level=multi_df.reset_index(level='季度')print("\n重置季度层级:")print(reset_level)

5.4 删除层级

multi_df=df.set_index(['年份','季度'])# 删除层级(将索引转为普通列后删除)df_no_quarter=multi_df.reset_index(level='季度',drop=True)print("删除季度层级:")print(df_no_quarter)

6. 多层索引的聚合

6.1 按层级分组

multi_df=df.set_index(['年份','季度'])# 按年份分组求和print("按年份求和:")print(multi_df.groupby(level='年份').sum())# 按季度分组(跨年份)print("\n按季度求和:")print(multi_df.groupby(level='季度').sum())# 按多个层级分组print("\n按年份和季度分组:")print(multi_df.groupby(level=['年份','季度']).sum())

6.2 层级聚合函数

# 创建更多数据np.random.seed(42)index=pd.MultiIndex.from_product([['A','B','C'],['X','Y'],[1,2]],names=['组','子组','编号'])df_hier=pd.DataFrame({'数值1':np.random.randn(12),'数值2':np.random.randn(12)},index=index)print("层次化数据:")print(df_hier)# 按第一层聚合print("\n按组聚合:")print(df_hier.groupby(level='组').mean())# 按前两层聚合print("\n按组和子组聚合:")print(df_hier.groupby(level=['组','子组']).std())

7. 多层索引的堆叠与展开

7.1 stack() - 将列索引转为行索引

# 创建宽格式数据wide_df=pd.DataFrame({('2023','Q1'):[100,200],('2023','Q2'):[120,220],('2024','Q1'):[150,250],('2024','Q2'):[160,260]},index=['产品A','产品B'])wide_df.columns=pd.MultiIndex.from_tuples(wide_df.columns)print("宽格式数据:")print(wide_df)# stack() 将列转为行stacked=wide_df.stack()print("\nstack 后:")print(stacked)

7.2 unstack() - 将行索引转为列索引

multi_df=df.set_index(['年份','季度'])print("原始多层索引:")print(multi_df)# unstack 将季度转为列unstacked=multi_df.unstack(level='季度')print("\nunstack 后:")print(unstacked)# 指定层级unstacked2=multi_df.unstack(level=0)print("\n将年份转为列:")print(unstacked2)

8. 多层列索引

# 创建多层列索引columns=pd.MultiIndex.from_tuples([('销售额','2023'),('销售额','2024'),('利润','2023'),('利润','2024')])df_cols=pd.DataFrame([[100,150,20,35],[120,160,25,38]],columns=columns,index=['产品A','产品B'])print("多层列索引:")print(df_cols)# 访问列print("\n销售额:")print(df_cols['销售额'])# 访问特定年份print("\n2023年销售额:")print(df_cols[('销售额','2023')])

9. 完整示例:销售数据多维分析

# 创建销售数据np.random.seed(42)sales_data=[]foryearin[2023,2024]:forquarterin['Q1','Q2','Q3','Q4']:forproductin['产品A','产品B','产品C']:forregionin['华东','华南','华北']:sales_data.append({'年份':year,'季度':quarter,'产品':product,'地区':region,'销售额':np.random.randint(1000,5000),'销量':np.random.randint(50,200)})df_sales=pd.DataFrame(sales_data)print("="*60)print("销售数据多维分析")print("="*60)# 1. 创建多层索引sales_indexed=df_sales.set_index(['年份','季度','产品','地区'])print("\n1. 多层索引结构:")print(sales_indexed.head())print(f"索引层级:{sales_indexed.index.names}")# 2. 按年份汇总print("\n2. 按年份销售额汇总:")print(sales_indexed.groupby(level='年份')['销售额'].sum())# 3. 按产品和地区汇总print("\n3. 按产品和地区销售额:")product_region=sales_indexed.groupby(level=['产品','地区'])['销售额'].sum()print(product_region.unstack())# 4. 2024年各季度销售趋势print("\n4. 2024年各季度销售趋势:")q4_trend=sales_indexed.xs(2024,level='年份').groupby(level='季度')['销售额'].sum()print(q4_trend)# 5. 产品A在各地区的表现print("\n5. 产品A在各地区的销售:")product_a=sales_indexed.xs('产品A',level='产品')print(product_a.groupby(level='地区')['销售额'].sum())# 6. 透视分析print("\n6. 产品 × 地区 销售额透视:")pivot=sales_indexed.groupby(level=['产品','地区'])['销售额'].sum().unstack()print(pivot)

10. 总结

操作方法说明
创建多层索引df.set_index(['col1','col2'])从列创建
从数组创建pd.MultiIndex.from_arrays()从数组列表创建
从元组创建pd.MultiIndex.from_tuples()从元组列表创建
从笛卡尔积创建pd.MultiIndex.from_product()创建所有组合
访问数据df.loc[(level1, level2)]按层级访问
交叉选择df.xs('value', level='name')按层级值选择
交换层级df.swaplevel()交换索引层级
重置层级df.reset_index(level='name')将索引转为列
删除层级df.reset_index(level='name', drop=True)丢弃索引
堆叠df.stack()列→行
展开df.unstack()行→列
分组聚合df.groupby(level='name')按层级分组

11. 模块二总结

恭喜你完成了模块二:数据选择与索引

你已掌握:

  1. ✅ 列选择与操作
  2. ✅ 行选择与切片
  3. ✅ 条件筛选
  4. ✅ query 方法
  5. ✅ 索引设置与重置
  6. ✅ 多层索引

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/14 18:07:20

NativeBase 3.0深度解析:React Native高效UI开发与设计系统集成实践

1. 项目概述:一个被低估的移动端UI“基建狂魔”如果你在React Native或者跨端开发领域摸爬滚打过一段时间,大概率听说过或者用过NativeBase。我第一次接触它,是在一个需要快速搭建一个具备基础设计规范的移动端应用原型时。当时市面上组件库选…

作者头像 李华
网站建设 2026/5/14 18:06:42

Traymond:高效管理Windows窗口的免费系统托盘工具

Traymond:高效管理Windows窗口的免费系统托盘工具 【免费下载链接】traymond A simple Windows app for minimizing windows to tray icons 项目地址: https://gitcode.com/gh_mirrors/tr/traymond 你是否经常因为任务栏拥挤而找不到需要的窗口?T…

作者头像 李华
网站建设 2026/5/14 18:06:42

ARM Trace单元寄存器详解与调试技巧

1. ARM Trace单元寄存器概述在嵌入式系统开发和调试过程中,指令追踪(Instruction Trace)是一项至关重要的技术。ARM架构中的Trace单元提供了一套完整的硬件机制,用于捕获处理器执行流水线中的指令流。与传统的断点调试相比,指令追踪具有非侵入…

作者头像 李华
网站建设 2026/5/14 18:05:16

三步搞定B站视频下载:解锁大会员专属4K画质的秘密武器

三步搞定B站视频下载:解锁大会员专属4K画质的秘密武器 【免费下载链接】bilibili-downloader B站视频下载,支持下载大会员清晰度4K,持续更新中 项目地址: https://gitcode.com/gh_mirrors/bil/bilibili-downloader 还在为无法下载B站精…

作者头像 李华
网站建设 2026/5/14 18:04:33

如何在Mac上使用LyricsX实现智能歌词同步:完整指南

如何在Mac上使用LyricsX实现智能歌词同步:完整指南 【免费下载链接】LyricsX 🎶 Ultimate lyrics app for macOS. 项目地址: https://gitcode.com/gh_mirrors/ly/LyricsX LyricsX是一款专为macOS设计的终极歌词应用,它能自动同步并显示…

作者头像 李华
网站建设 2026/5/14 18:04:33

灵珠上线520 AI创作大赛:“用AI发电,让热爱看见”

5月13日,零门槛AI创作平台"灵珠"正式启动"520灵珠AI创作大赛",主题为"用AI发电,让热爱看见"。大赛不设任何参赛门槛,不限年龄、职业与创作方向,活动时间为5月13日至6月5日,获…

作者头像 李华