multiindex切片需显式指定层级或用元组/切片,xs()最简提取单层固定值并自动降维,query()支持复杂逻辑但依赖合法索引名,loc需严格按层级顺序配slice或元组,操作前必查index.names和levels顺序。

MultiIndex 切片不能直接用普通 df[...] 或 df.loc[...] 写法套用单层索引逻辑,必须显式指定层级或使用元组/切片对象,否则会报 KeyError 或返回意外空结果。
用 xs() 提取某一层级的固定值(最常用)
当你只想拿“省份=广东”的所有行,且不关心其他层级时,xs() 最干净。它自动降维,返回 DataFrame 或 Series(取决于是否保留最后一级)。
常见错误:漏写 level= 参数导致匹配错层级;或传入非元组导致只匹配第一级。
- 提取“城市=深圳”的所有数据:
df.xs("深圳", level="城市") - 提取“年份=2023”且保留“省份”“城市”两层索引:
df.xs(2023, level="年份", drop_level=False) - 提取多级组合(必须用元组):
df.xs(("广东", "深圳"), level=("省份", "城市"))
用 query() 做条件过滤(适合带逻辑表达式的场景)
query() 对 MultiIndex 的支持依赖索引名是否为合法变量名。如果层级名含空格、数字开头或特殊字符,需用反引号包裹。
性能上比 xs() 稍慢,但可写复杂条件,比如“广东或浙江且年份 > 2021”。
调用 Cutout.Pro 视觉处理 API 进行背景移除、人像抠图和照片增强,支持文件上传与图片 URL 输入。
- 基础用法:
df.query("`省份` == '广东' and `年份` == 2023") - 层级名非法时:
df.query("`level_0` == 'A'")(当未命名层级时默认叫level_0) - 注意:
query()不改变原索引结构,返回仍是 MultiIndex DataFrame
用 loc 配合 Slice 或元组做精确切片
loc 是最灵活但也最容易出错的方式——必须按索引顺序提供完整层级结构,缺一不可。想切“广东”下所有城市、“2022–2024”所有年份,就得用 Slice。
典型坑:写 df.loc["广东", :] 报错,因为没说明这是哪一层;或误以为 : 能通配所有层级。
- 取“广东”下全部数据(保留“城市”“年份”):
df.loc[("广东", slice(None), slice(None)), :] - 取“广东”+“深圳”+“2023”三元组:
df.loc[("广东", "深圳", 2023), :] - 跨层级切片(如所有“2023”年数据):
df.loc[(slice(None), slice(None), 2023), :]
重建索引前先确认层级顺序和名称
很多切片失败,根源不在语法,而在 df.index.names 和实际层级顺序不一致。例如你认为“年份”是第 2 层,但它其实是第 0 层(尤其用 set_index([a,b,c]) 时顺序即层级顺序)。
别跳过这步检查:print(df.index.names) 和 print(df.index.levels) 必须先看清楚。
- 重排层级顺序:
df.swaplevel("年份", "城市").sort_index() - 给无名层级赋名:
df.index.set_names(["省份", "城市", "年份"], inplace=True) - 层级名重复会导致
xs()和query()行为异常,务必唯一
MultiIndex 切片真正难的不是语法本身,而是每次操作前都得心里有张层级地图——哪层在前、有没有命名、哪些值实际存在。少一次 df.index.names 检查,就多一个 KeyError。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










