按列值的允许组合列表筛选df



假设我有一个数据帧,如下所示:

Animal  Color
0     Dog  White
1     Cat  Black
2     Dog  Black
3     Dog  Brown
4  Rabbit  Brown

我想得到所有与这些元组匹配的索引:[('Cat', 'Black'), ('Dog', 'Brown')]。在这种情况下,这就是[1,3]

我不能做df[np.isin(df['Animal'], ['Cat', 'Dog']) & np.isin(df['Color'], ['Black', 'Brown'])]这样的事情,因为那样会给我[1,2,3]

如果这只是一列,我会使用df[np.isin(df[col], ls)]

如果我只关心一个元组,我本可以完成df[(df[col0] == tup[0]) & (df[col1] == tup[1])]

我只是不知道如何把这两个概念结合起来。

以下是pandas MultiIndex的一种方法。我把这个例子改成了一只红狗:

from io import StringIO
import pandas as pd
data = '''   Animal  Color
0     Dog  White
1     Cat  Black
2     Dog  Red
3     Dog  Brown
4  Rabbit  Brown
'''
df = pd.read_csv(StringIO(data), sep='s+', engine='python', index_col=0)
to_keep = [('Cat', 'Black'), 
('Dog', 'Red'),
]
mask = pd.MultiIndex.from_frame(df[['Animal', 'Color']]).isin(to_keep)
print(df.loc[mask])
Animal  Color
1    Cat  Black
2    Dog    Red

让我们尝试广播:

mask = (df.values[:,None,:] == np.array(a)).all(-1).any(-1)
df[mask]

输出:

Animal  Color
1    Cat  Black
3    Dog  Brown

您只需创建一个包含逻辑的布尔序列,如下所示:

criterion = [('Cat', 'Black'), ('Dog', 'Brown')]
cond = reduce(lambda x, y: ((df['Animal'] == x[0]) & (df['Color'] == x[1])) | ((df['Animal'] == y[0]) & (df['Color'] == y[1])), criterion)
print(df[cond])

输出:

Animal  Color
1    Cat  Black
3    Dog  Brown

您可以使用for loop来提取索引:

df.loc[[ind 
for ind, a, b in zip(df.index, df.Animal, df.Color)
if (a, b) in keep]]
Animal  Color
1   Cat Black
3   Dog Brown

如果索引不重要,可以使用set indexreset index:

df.set_index(["Animal", "Color"], append=False, drop=False).loc[keep].reset_index(
drop=True
)
Animal    Color
0   Cat     Black
1   Dog     Brown

最新更新