根据级别之间的 'AND' 条件删除 DataFrame 的多索引行

Drop multi-indexed rows of a DataFrame based on 'AND' condition between levels

我希望能够使用多级标准(使用逻辑 AND 加入标准)从多索引数据框对象中删除行。

考虑以下 pandas 数据框对象:

import pandas as pd
df = pd.DataFrame(data = [[1,'x'],[2,'x'],[1,'y'],[2,'y']],
                   index=pd.MultiIndex(levels=[['A','B'],['a','b']],
                                       labels=[[0,1,0,1],[0,1,1,0]],
                                       names=['idx0','idx1']))

print(df) 输出:

           0  1
idx0 idx1      
A    a     1  x
B    b     2  x
A    b     1  y
B    a     2  y

我想去掉'idx0'=='A''idx1'=='a'那一行,所以最后的结果是:

           0  1
idx0 idx1      
B    b     2  x
     a     2  y
A    b     1  y

在我看来,这似乎不能用 df.drop() 方法来完成。 'roundabout' 给出正确结果的方法是:

df = pd.concat([df.drop(labels='A',level=0),df.drop(labels='a',level=1)])
df = df.drop_duplicates()

但我认为必须有更好的方法...

您可以使用 isin 方法进行索引,并与您使用 ~ 选择的内容相反:

In [85]: df.index.isin([('A','a')])
Out[85]: array([ True, False, False, False], dtype=bool)

In [86]: df[~df.index.isin([('A','a')])]
Out[86]:
           0  1
idx0 idx1
B    b     2  x
A    b     1  y
B    a     2  y

时间:

In [95]: %timeit df.drop(('A','a'))
1000 loops, best of 3: 1.33 ms per loop

In [96]: %timeit df[~df.index.isin([('A','a')])]
1000 loops, best of 3: 457 us per loop

所以 drop 比 isin 解决方案慢了将近 3 倍。

要解决您关于 .drop() 的问题 - 只需将 MultiIndex 标签作为 tuple:

df.drop(('A', 'a'))

           0  1
idx0 idx1      
B    b     2  x
A    b     1  y
B    a     2  y