两个数据帧的差异
Diff of two Dataframes
我需要按行比较两个不同大小的数据帧并打印出不匹配的行。让我们采取以下两个:
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
包含在差异中:
我已经尝试过:
和 Compare two DataFrames and output their differences side-by-side
但是这些都不符合我的问题
merge
2 dfs 使用方法 'outer' 并传递参数 indicator=True
这将告诉您这些行是否只存在于 both/left only/right 中,然后您可以在以下之后过滤合并的 df:
In [22]:
merged = df1.merge(df2, indicator=True, how='outer')
merged[merged['_merge'] == 'right_only']
Out[22]:
Buyer Quantity _merge
3 Carl 2 right_only
4 Mark 1 right_only
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 的回答是self-explained。但是使用 not 'both'
条件更有意义,你不需要关心比较的顺序,这就是真正的 diff 应该是的。为了回答你的问题:
merged = df1.merge(df2, indicator=True, how='outer')
merged.loc = [merged['_merge'] != 'both']
从 Pandas 1.1.0 开始,有 pandas.DataFrame.compare:
df1.compare(df2)
https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.compare.html
一个重要的边缘案例
考虑以下情况,您在第二个数据框中有一个额外的重复条目。 ('Carl', 5)
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
重复计数器确保每一行都是唯一的,这意味着不会删除重复值。合并后,你可以删除 duplicate_counter.
我需要按行比较两个不同大小的数据帧并打印出不匹配的行。让我们采取以下两个:
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
包含在差异中:
我已经尝试过:
但是这些都不符合我的问题
merge
2 dfs 使用方法 'outer' 并传递参数 indicator=True
这将告诉您这些行是否只存在于 both/left only/right 中,然后您可以在以下之后过滤合并的 df:
In [22]:
merged = df1.merge(df2, indicator=True, how='outer')
merged[merged['_merge'] == 'right_only']
Out[22]:
Buyer Quantity _merge
3 Carl 2 right_only
4 Mark 1 right_only
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 的回答是self-explained。但是使用 not 'both'
条件更有意义,你不需要关心比较的顺序,这就是真正的 diff 应该是的。为了回答你的问题:
merged = df1.merge(df2, indicator=True, how='outer')
merged.loc = [merged['_merge'] != 'both']
从 Pandas 1.1.0 开始,有 pandas.DataFrame.compare:
df1.compare(df2)
https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.compare.html
一个重要的边缘案例
考虑以下情况,您在第二个数据框中有一个额外的重复条目。 ('Carl', 5)
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
重复计数器确保每一行都是唯一的,这意味着不会删除重复值。合并后,你可以删除 duplicate_counter.