✅ 今日目标
- 掌握 Pandas 的索引体系(Index / MultiIndex)
- 使用
set_index()
和reset_index()
管理数据索引 - 理解
pivot_table
与melt
、stack/unstack
重塑数据形态 - 初步理解“宽表”与“长表”在数据分析与可视化中的应用场景
📚 一、深入理解 Pandas 的索引系统
1. 默认索引 vs 自定义索引
df = pd.read_csv("./data/students_cleaned.csv")
# 自定义“姓名”为索引列
df_indexed = df.set_index("姓名")
print(df_indexed.head())
# 还原索引为普通列
df_reset = df_indexed.reset_index()
2. 多级索引(MultiIndex)
df_multi = df.set_index(["性别", "是否及格"])
print(df_multi.head())
# 多级索引选择
print(df_multi.loc[("男", True)])
📊 二、数据透视表(pivot_table)
类似 Excel 的数据透视功能,可做汇总/分组/聚合操作
# 性别 + 及格情况的平均成绩
pivot = pd.pivot_table(df, values="成绩", index="性别", columns="是否及格", aggfunc="mean")
print(pivot)
🔁 三、数据重塑:长表 ↔ 宽表
1. melt(宽表 → 长表)
df_melted = pd.melt(df, id_vars=["姓名", "性别"], value_vars=["成绩", "是否及格"])
print(df_melted.head())
2. pivot(长表 → 宽表)
# 从 melt 回 pivot
df_pivot = df_melted.pivot(index=["姓名", "性别"], columns="variable", values="value")
print(df_pivot.head())
3. stack & unstack
stacked = df.set_index(["姓名", "性别"]).stack()
print(stacked.head())
unstacked = stacked.unstack()
print(unstacked.head())
🧪 今日练习任务建议
-
使用
set_index
和reset_index
操作学生数据 -
创建一个以“性别 + 是否及格”为索引的多级索引表
-
统计不同性别在及格与否下的平均成绩(pivot_table)
-
使用
melt
将成绩 & 是否及格转换为“指标名 + 值”形式 -
使用
stack/unstack
查看层级结构变化data/students_cleaned.csv如数如图:
代码示例:
import pandas as pd import os # 数据路径 input_path = "data/students_cleaned.csv" if not os.path.exists(input_path): raise FileNotFoundError("❌ 缺少 students_cleaned.csv,请先运行 clean_data.py") # 加载数据 df = pd.read_csv(input_path) print("✅ 已加载数据:") print(df.head()) # ========== 一、索引操作 ========== print("\n👉 使用 set_index() 将姓名设为索引:") df_indexed = df.set_index("姓名") print(df_indexed.head()) print("\n🔁 使用 reset_index() 还原索引:") df_reset = df_indexed.reset_index() print(df_reset.head()) # ========== 二、多级索引 ========== print("\n📦 设置多级索引(性别 + 是否及格):") df_multi = df.set_index(["性别", "是否及格"]) print(df_multi.head()) print("\n🔍 查询:性别为 '女' 且 及格 的学生:") print(df_multi.loc[("女", True)]) # ========== 三、pivot_table 操作 ========== print("\n📊 pivot_table 统计性别 + 是否及格下的平均成绩:") pivot = pd.pivot_table(df, values="成绩", index="性别", columns="是否及格", aggfunc="mean") print(pivot) # ========== 四、melt 数据重塑 ========== print("\n🔄 使用 melt 变长表结构(指标列合并):") df_melted = pd.melt(df, id_vars=["姓名", "性别"], value_vars=["成绩", "是否及格"]) print(df_melted.head()) # ========== 五、pivot 还原宽表结构 ========== print("\n🔁 使用 pivot 将 melt 数据还原回宽表:") df_pivot = df_melted.pivot(index=["姓名", "性别"], columns="variable", values="value") print(df_pivot.head()) # ========== 六、stack 和 unstack ========== print("\n📚 使用 stack 增加层级结构(列 → 行):") df_stacked = df.set_index(["姓名", "性别"]).stack() print(df_stacked.head()) print("\n📂 使用 unstack 还原结构(行 → 列):") df_unstacked = df_stacked.unstack() print(df_unstacked.head())
运行结果:
✅ 已加载数据: 姓名 性别 成绩 是否及格 0 张三 男 88.00 True 1 李四 女 81.75 True 2 王五 男 59.00 False 3 田七 女 81.75 True 4 赵六 女 92.00 True 👉 使用 set_index() 将姓名设为索引: 性别 成绩 是否及格 姓名 张三 男 88.00 True 李四 女 81.75 True 王五 男 59.00 False 田七 女 81.75 True 赵六 女 92.00 True 🔁 使用 reset_index() 还原索引: 姓名 性别 成绩 是否及格 0 张三 男 88.00 True 1 李四 女 81.75 True 2 王五 男 59.00 False 3 田七 女 81.75 True 4 赵六 女 92.00 True 📦 设置多级索引(性别 + 是否及格): 姓名 成绩 性别 是否及格 男 True 张三 88.00 女 True 李四 81.75 男 False 王五 59.00 女 True 田七 81.75 True 赵六 92.00 🔍 查询:性别为 '女' 且 及格 的学生: 姓名 成绩 性别 是否及格 女 True 李四 81.75 True 田七 81.75 True 赵六 92.00 📊 pivot_table 统计性别 + 是否及格下的平均成绩: 是否及格 False True 性别 女 NaN 85.166667 男 59.0 88.000000 🔄 使用 melt 变长表结构(指标列合并): 姓名 性别 variable value 0 张三 男 成绩 88.0 1 李四 女 成绩 81.75 2 王五 男 成绩 59.0 3 田七 女 成绩 81.75 4 赵六 女 成绩 92.0 🔁 使用 pivot 将 melt 数据还原回宽表: variable 成绩 是否及格 姓名 性别 张三 男 88.0 1.0 李四 女 81.75 1.0 王五 男 59.0 0.0 田七 女 81.75 1.0 赵六 女 92.0 1.0 📚 使用 stack 增加层级结构(列 → 行): 姓名 性别 张三 男 成绩 88.0 是否及格 True 李四 女 成绩 81.75 是否及格 True 王五 男 成绩 59.0 dtype: object 📂 使用 unstack 还原结构(行 → 列): 成绩 是否及格 姓名 性别 张三 男 88.0 True 李四 女 81.75 True 王五 男 59.0 False 田七 女 81.75 True 赵六 女 92.0 True
🧾 今日总结
- 索引是 Pandas 操作效率与表达力的核心
- 多级索引可构建灵活的数据结构,适合多维度聚合分析
pivot_table
是强大而高效的“表格重建”工具melt
/pivot
/stack
/unstack
是数据“变形”关键方法