如何基于前两层索引组合筛选Pandas多层索引DataFrame?
问题
我有一个带多层索引的Pandas DataFrame,筛选后得到了除最后一层外的多组索引组合(即sel),示例代码如下:
import pandas as pd df = pd.DataFrame({'a': ['A', 'B', 'A', 'B'], 'b': ['X', 'X', 'X', 'Y'], 'c': ['S', 'T', 'T', 'T'], 'd': [1, 2, 3, 1]}).set_index(['a', 'b', 'c']) print(df.to_string()) # 输出: # d # a b c # A X S 1 # B X T 2 # A X T 3 # B Y T 1 sel = df.index.droplevel('c')[df.d == 1] # 基于多层索引的筛选逻辑 print(sel) # 输出: # MultiIndex([('A', 'X'), # ('B', 'Y')], # names=['a', 'b'])
现在想获取原DataFrame中所有(a,b)属于sel的行(也就是除第二行外的所有行),试过.loc、.xs都没成功,不想用修改索引或内连接这类临时方案,有没有更直接的方法?
解决方案
这里有几个直接的方法,不用修改原索引也不用内连接:
方法1:直接用.loc索引(最简洁)
Pandas支持用层级更少的MultiIndex去索引多层索引的DataFrame,它会自动匹配对应层级的所有子行:
result = df.loc[sel] print(result.to_string()) # 输出: # d # a b c # A X S 1 # X T 3 # B Y T 1
这就是你要的结果,直接传sel给.loc就会匹配前两层a和b,返回所有对应c的行。
方法2:用index.isin指定层级判断
如果需要更明确地指定匹配的层级,可以用index.isin,并通过level参数指定要匹配的索引名:
# 把sel转成元组列表,然后判断原索引的a、b层级是否匹配 mask = df.index.isin(list(sel), level=['a', 'b']) result = df[mask]
方法3:临时提取索引列判断
也可以临时提取前两层索引列,转成元组后判断是否在sel中:
# 重置索引提取a、b列,转成元组后匹配sel mask = df.reset_index()[['a', 'b']].apply(tuple, axis=1).isin(sel) result = df[mask]
内容的提问来源于stack exchange,提问作者Michel de Ruiter
相关产品推荐
相关产品推荐

