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。目前,需要不断添加
&
,才能添加更多的列。如果可以将它包装到一个列表理解(或应用函数)中会更好,因为每个列都是独立的