Python 比较多个列以获取两个数据帧中不同的行

Python 比较多个列以获取两个数据帧中不同的行,python,pandas,Python,Pandas,我有两个数据帧: df1= A B C 0 A0 B0 C0 1 A1 B1 C1 2 A2 B2 C2 df2= A B C 0 A2 B2 C10 1 A1 B3 C11 2 A9 B4 C12 我想根据一列或两列(或更多列)查找df1中未在df2中找到的行。因此,如果我只比较列“A”,那么df1中的以下行在df2中找不到(请注意,列“B”和列“C”不用于df1和df2之间的比较) 我想返回一

我有两个数据帧:

df1=
    A    B   C
0   A0   B0  C0
1   A1   B1  C1
2   A2   B2  C2

df2=
    A    B   C
0   A2   B2  C10
1   A1   B3  C11
2   A9   B4  C12
我想根据一列或两列(或更多列)查找df1中未在df2中找到的行。因此,如果我只比较列“A”,那么df1中的以下行在df2中找不到(请注意,列“B”和列“C”不用于df1和df2之间的比较)

我想返回一个带有

0   False
1   True
2   True
0   False
1   False
2   True
或者,如果我只比较列“A”和列“B”,那么df1中的以下行在df2中找不到(请注意,列“C”不用于df1和df2之间的比较)

我想返回一个带有

0   False
1   True
2   True
0   False
1   False
2   True
我知道如何使用集合来实现这一点,但我正在寻找一种简单的方法来实现这一点

 ~df1['A'].isin(df2['A'])
你应该会得到你想要的系列

df1[ ~df1['A'].isin(df2['A'])]
数据帧:

    A   B   C
0   A0  B0  C0

如果您的版本是
0.17.0
,那么您可以使用并传递感兴趣的列how='left',并设置
indicator=True
,以确定这些值是仅存在于left中还是同时存在于left中。然后,您可以测试附加的
\u merge
列是否等于“两者”:

In [102]:
pd.merge(df1, df2, on='A',how='left', indicator=True)['_merge'] == 'both'

Out[102]:
0    False
1     True
2     True
Name: _merge, dtype: bool

In [103]:
pd.merge(df1, df2, on=['A', 'B'],how='left', indicator=True)['_merge'] == 'both'

Out[103]:
0    False
1    False
2     True
Name: _merge, dtype: bool
合并的输出:

In [104]:
pd.merge(df1, df2, on='A',how='left', indicator=True)

Out[104]:
    A B_x C_x  B_y  C_y     _merge
0  A0  B0  C0  NaN  NaN  left_only
1  A1  B1  C1   B3  C11       both
2  A2  B2  C2   B2  C10       both

In [105]:    
pd.merge(df1, df2, on=['A', 'B'],how='left', indicator=True)

Out[105]:
    A   B C_x  C_y     _merge
0  A0  B0  C0  NaN  left_only
1  A1  B1  C1  NaN  left_only
2  A2  B2  C2  C10       both
方法(1)
方法(2)
您可以使用左合并来获取两个帧中存在的值
+
仅存在于第一个数据帧中的值

In [10]:
left = pd.merge(df1 , df2 , on = ['A' , 'B'] ,how = 'left')
left
Out[10]:
    A   B   C_x C_y
0   A0  B0  C0  NaN
1   A1  B1  C1  NaN
2   A2  B2  C2  C10
当然,仅存在于第一帧中的值将在另一数据帧的列中具有
NAN
值,然后您可以通过执行以下操作按此
NAN
值进行过滤

In [16]:
left.loc[pd.isnull(left['C_y']) , 'A':'C_x']
Out[16]:
    A   B   C_x
0   A0  B0  C0
1   A1  B1  C1

In [17]:
In [20]:
pd.notnull(left['C_y'])
Out[20]:
0    False
1    False
2     True
Name: C_y, dtype: bool
如果要获取
A
中的值是否存在于
B
中,可以执行以下操作

In [16]:
left.loc[pd.isnull(left['C_y']) , 'A':'C_x']
Out[16]:
    A   B   C_x
0   A0  B0  C0
1   A1  B1  C1

In [17]:
In [20]:
pd.notnull(left['C_y'])
Out[20]:
0    False
1    False
2     True
Name: C_y, dtype: bool

理想情况下,可以只使用~df1[COLS].isin(df2[COLS])作为掩码,但这需要索引标签匹配()

下面是一个简洁的表单,它使用.isin,但将第二个数据帧转换为dict,以便索引标签不需要匹配:

COLS = ['A', 'B'] # or whichever columns to use for comparison

df1[~df1[COLS].isin(df2[COLS].to_dict(
    orient='list')).all(axis=1)]

这有点复杂。我没有意识到您想要动态处理可变数量的列。如果其他人不能帮助您,我可以稍后再讨论,直到那时索引标签还需要匹配多个列-因此这有点棘手。我想知道,当代码的长度越来越长时,是否有更好的方法来表示方法#1。目前,需要不断添加
&
,才能添加更多的列。如果可以将它包装到一个列表理解(或应用函数)中会更好,因为每个列都是独立的