两个数据框架的差分

我需要按行比较两个不同大小的数据帧,并打印出不匹配的行。让我们看看以下两个例子:

df1 = DataFrame({
'Buyer': ['Carl', 'Carl', 'Carl'],
'Quantity': [18, 3, 5, ]})


df2 = DataFrame({
'Buyer': ['Carl', 'Mark', 'Carl', 'Carl'],
'Quantity': [2, 1, 18, 5]})

什么是对 df2进行行向分析并打印出 df1以外的行的最有效方法,例如。

Buyer     Quantity
Carl         2
Mark         1

重要提示: 我不想有行:

Buyer     Quantity
Carl         3

差异包括:

我已经试过了: 逐行比较两个不同长度的数据框架,并为每行添加具有相同值的列 比较两个数据框架并输出它们的差异

但这些和我的问题不相符。

93232 次浏览
diff = set(zip(df2.Buyer, df2.Quantity)) - set(zip(df1.Buyer, df1.Quantity))

这是我想到的第一个解决方案。然后您可以将差异集放回到 DF 中进行演示。

如果您只关心将新买家添加到另一个 df,请尝试以下操作:

df_delta=df2[df2['Buyer'].apply(lambda x: x not in df1['Buyer'].values)]

你可能会发现这是最好的:

df2[ ~df2.isin(df1)].dropna()

@ EdChum 的回答不言自明。但是使用 not 'both'条件更有意义,你不需要关心比较的顺序,这就是一个真正的 差异应该是什么。为了回答你的问题:

merged = df1.merge(df2, indicator=True, how='outer')
merged.loc = [merged['_merge'] != 'both']

在熊猫1.1.0中,有熊猫:

df1.compare(df2)

Https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas

一个重要的边缘案例

考虑以下情况,其中在第二个数据帧中有一个额外的重复条目

df1 = DataFrame({ 'Buyer':    ['Carl', 'Carl', 'Carl'],
'Quantity': [   18 ,     3 ,     5 ]  })


df2 = DataFrame({ 'Buyer':    ['Carl', 'Mark', 'Carl', 'Carl', 'Carl'],
'Quantity': [    2 ,     1 ,    18 ,     5 ,     5 ]  })

EdChum 的回答是:

merged = df1.merge(df2, indicator=True, how='outer')
print(merged[merged['_merge'] == 'right_only'])


Buyer  Quantity      _merge
4  Carl         2  right_only
5  Mark         1  right_only

正如您所看到的,解决方案忽略了额外的重复值,这取决于您正在执行的操作是您希望避免的。

这里有一个解决方案,更有可能做你想做的事情:

df1['duplicate_counter'] = df1.groupby(list(df1.columns)).cumcount()
df2['duplicate_counter'] = df2.groupby(list(df2.columns)).cumcount()
merged = df1.merge(df2, indicator=True, how='outer')
merged[merged['_merge'] == 'right_only']


Buyer  Quantity  duplicate_counter      _merge
3  Carl         2                  0  right_only
4  Mark         1                  0  right_only
5  Carl         5                  1  right_only

重复计数器确保每一行都是唯一的,这意味着不会删除重复值。合并之后,可以删除 copy _ counter。