Pandas多级索引下.loc方法的使用疑问及预期结果实现需求
嘿,我来帮你把这个MultiIndex下的.loc用法问题理清楚~
首先先还原你的场景,执行以下代码:
import pandas as pd df=pd.DataFrame({'a':[1,2,3,4,5,6,7,8],'b':['g1','g1','g1','g1','g2','g2','g2','g2'],'c':['v1','v2','v1','v2','v1','v2','v1','v2']}) df.set_index(['b','c'], inplace=True)
生成的DataFrame如下:
a b c g1 v1 1 v2 2 v1 3 v2 4 g2 v1 5 v2 6 v1 7 v2 8
你的疑问拆解
1. 为什么df.loc['g1','v1']会返回两行数据?
你之前的理解是.loc[row,col]的第二个参数是列标签,但这里的核心是:你给DataFrame设置了多层行索引(MultiIndex),b和c都是行索引的层级,而不是“行+列”的对应关系。
当你写df.loc['g1','v1']时,pandas会自动把这两个参数对应到行索引的第一层(b)和第二层(c),相当于筛选「行索引第一层为g1且第二层为v1」的所有行,所以会返回这两行结果:
a b c g1 v1 1 v1 3
2. 为什么df.loc[:,'v1']无法得到预期的所有v1行?
这是因为.loc[:, 'v1']里的第二个参数是在指定列标签,而你的DataFrame里只有一列a,根本没有名为v1的列,所以这样写要么报错,要么返回空结果,自然没法筛选到行索引里的v1。
如何获取你想要的结果?
要筛选所有行索引第二层为v1的行,这里有3种常用且清晰的方法:
方法1:用切片+元组指定MultiIndex
直接通过元组来匹配多层索引的层级,slice(None)表示匹配第一层索引的所有值:
df.loc[(slice(None), 'v1'), :]
方法2:用IndexSlice(可读性更强)
先导入IndexSlice,可以更直观地写出筛选逻辑:
from pandas import IndexSlice df.loc[IndexSlice[:, 'v1'], :]
方法3:用xs方法(专门针对MultiIndex的工具)
xs是pandas专门为多层索引设计的筛选方法,level参数指定要筛选的索引层级(可以写层级名称'c'或者索引位置1),drop_level=False用来保留原有的多层索引结构:
df.xs('v1', level='c', drop_level=False)
以上三种方法都能得到你预期的结果:
a b c g1 v1 1 v1 3 g2 v1 5 v1 7
内容的提问来源于stack exchange,提问作者HappyPy




