从Pandas数据框中选择行,其中两列与一对列表匹配

7

我正在尝试从数据框中创建一个布尔掩码(或索引列表),以指示多个列匹配列表中某些组合的位置。以下是一个例子:

import pandas as pd
df = pd.DataFrame({'A': ['alice', 'bob'    , 'charlie'  , 'dave' , 'dave'], 
                   'B': ['andy' , 'bridget', 'charlotte', 'diana', 'andy'], 
                   'C': ['some' , 'other'  , 'stuff'    , 'here' , '!' ]})

pairs = pd.DataFrame({'A': ['alice', 'dave'],
                      'B': ['andy' , 'diana']})

我希望的输出结果是以下之一

[True, False, False, True, False]

或者

[0, 3]

关键是我不想返回行索引为4,即['dave', 'andy','!'] 。 我可以通过转换回列表来实现所需的结果...但这感觉像是一个很长的方法,我认为有一种“pandas”的方法可以做到这一点!
df_list = df[['A', 'B']].values.tolist()
pairs_list = pairs.values.tolist()
[idx for idx, row in enumerate(df_list) if row in pairs_list]

编辑 - 谢谢。 - James Owers
1个回答

10
你可以使用 indicator=True 参数执行 outer 类型的合并,并测试是否 _merge 列等于 'both':
In [97]:
merged = df.merge(pairs, how='outer', indicator=True)
merged[merged['_merge'] =='both'].index

Out[97]:
Int64Index([0, 3], dtype='int64')

为了获得一个布尔Series
In [98]:
merged['_merge'] =='both'

Out[98]:
0     True
1    False
2    False
3     True
4    False
Name: _merge, dtype: bool

合并后的数据框如下所示:
In [99]:
merged

Out[99]:
         A          B      C     _merge
0    alice       andy   some       both
1      bob    bridget  other  left_only
2  charlie  charlotte  stuff  left_only
3     dave      diana   here       both
4     dave       andy      !  left_only

值得一提的是,如果您想将 msk = merged['_merge'] == 'both' 作为掩码用于 pandas DataFrame(例如 df.ix[msk])或 numpy 数组(例如 df[msk, :]),则需要提取布尔型 numpy 数组,即使 msk = (merged['_merge'] =='both').values - James Owers
每当您尝试使用一个布尔掩码Series与不具有相同形状或索引值的df时,它都会失败。 - EdChum
我不太理解你的评论@EdChum。当我使用它来掩盖与df相同顺序的另一个数据框时,我遇到了困难。合并是否会重新排序,从而使掩码对此目的无效? - James Owers
但是合并后的数据框将比原始数据框具有更多的行,索引值不一定存在于任何一个数据框中,也不一定具有相同的长度。 - EdChum
好的,我想我需要稍后回来构建一个更好的例子!感谢您的帮助。 - James Owers
1
@kungfujam - 对我来说,使用合并的掩码而不将其转换为numpy值可以正常工作。EdChum的解决方案非常好,我认为被低估了。 - elPastor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接