You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何匹配两个Pandas DataFrame,识别匹配行并展示差异内容

问题原因

你原有代码是基于行索引位置逐行对比,两个DataFrame仅行顺序不同时,同索引位置的内容不一致就会被误识别为差异。

修复代码(按行内容匹配,忽略顺序)

方案1:基于唯一主键对齐对比(推荐,适用有唯一标识列的场景,比如本例的Name列)

这种方式可以精准找到两个表中同主键的行差异,也能自动识别行数不同的情况:

import pandas as pd
import numpy as np

# 样例数据
df1 = pd.DataFrame([['tom', 10],['nick',15], ['juli',14]], columns = ['Name', 'Age'])
df2 = pd.DataFrame([['nick', 15],['tom', 10], ['juli',14]], columns = ['Name', 'Age'])

# 以Name为唯一主键做外连接对齐,标记行来源
df_compare = df1.merge(df2, on='Name', how='outer', suffixes=('_df1', '_df2'), indicator=True)

# 处理行数不同的情况:提取仅在单表存在的行
only_df1 = df_compare[df_compare['_merge'] == 'left_only']
only_df2 = df_compare[df_compare['_merge'] == 'right_only']

# 提取两表都存在的行的字段差异
common_rows = df_compare[df_compare['_merge'] == 'both'].copy()
diff_rows = []
for col in df1.columns:
    if col == 'Name': # 跳过主键列
        continue
    mask = common_rows[f'{col}_df1'] != common_rows[f'{col}_df2']
    diff_part = common_rows[mask][['Name', f'{col}_df1', f'{col}_df2']]
    diff_part['diff_col'] = col
    diff_rows.append(diff_part)

# 合并所有差异
if diff_rows:
    divergences = pd.concat(diff_rows).set_index(['Name', 'diff_col']).rename(columns={'Age_df1':'df1', 'Age_df2':'df2'})
else:
    divergences = pd.DataFrame(columns=['df1', 'df2'])

print("仅在df1存在的行:")
print(only_df1[['Name', 'Age_df1']] if len(only_df1) > 0 else "无")
print("\n仅在df2存在的行:")
print(only_df2[['Name', 'Age_df2']] if len(only_df2) > 0 else "无")
print("\n共同存在行的字段差异:")
print(divergences)

你的样例运行后,共同存在行的差异会输出你期望的空DataFrame结果。

方案2:无主键时,校验行集合完全一致(忽略顺序)

如果没有唯一主键,仅需要判断两个表的所有行的集合完全相等,直接排序后对比即可:

# 按所有列排序后重置索引,消除行顺序影响
df1_sorted = df1.sort_values(by=list(df1.columns)).reset_index(drop=True)
df2_sorted = df2.sort_values(by=list(df2.columns)).reset_index(drop=True)

# 优先判断行数是否相等
if len(df1_sorted) != len(df2_sorted):
    print(f"两个DataFrame行数不同,df1有{len(df1)}行,df2有{len(df2)}行")
else:
    # 复用你原有逻辑对比排序后的表
    ne_stacked = (df1_sorted != df2_sorted).stack()
    changed = ne_stacked[ne_stacked]
    changed.index.names = ['id', 'col']
    difference_locations = np.where(df1_sorted != df2_sorted)
    changed_from = df1_sorted.values[difference_locations]
    changed_to = df2_sorted.values[difference_locations]
    divergences = pd.DataFrame({'df1': changed_from, "df2": changed_to}, index=changed.index)
    print(divergences)

行数不同的处理逻辑

  • 用方案1的外连接方式时,会自动识别仅在df1存在的行和仅在df2存在的行,可以直接输出这些行告知用户哪边多了数据
  • 用方案2的排序对比方式时,优先判断len(df1) == len(df2),不相等直接提示行数差异,不需要再做字段级对比

内容的提问来源于stack exchange,提问作者danielssl

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 12:54:03