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

Python中对比同结构DataFrame:如何在差异结果中标记记录所属原DataFrame及差异列

解决DataFrame差异对比的来源标识与列差异问题

没问题!你现在的代码能找出两个DataFrame的差异记录,但缺少了记录来源和具体差异列的信息,我给你两个实用方案:

方案一:实现你期望的输出格式

这个方案会给每个记录加上来源DataFrame的标识,生成你想要的结果:

import pandas as pd

# 示例数据(替换成你的真实DataFrame即可)
df1 = pd.DataFrame({
    'Name': ['Naxi', 'Karan', 'Tanya'],
    'Age': [27, 25, 27],
    'Gender': ['Male', 'Male', 'Female']
})

df2 = pd.DataFrame({
    'Name': ['Naxi', 'Tanya', 'Karan'],
    'Age': [27, 27, 24],
    'Gender': ['Male', 'Female', 'Male']
})

# 1. 给每个DataFrame添加来源标识列
df1['Dataframe'] = 'df1'
df2['Dataframe'] = 'df2'

# 2. 合并两个DataFrame
combined_df = pd.concat([df1, df2])

# 3. 按原始数据列(排除来源列)分组,找出只出现一次的记录(即差异记录)
original_columns = df1.columns.drop('Dataframe')
grouped = combined_df.groupby(list(original_columns))

# 提取差异记录的索引
diff_indices = []
for group in grouped.groups.values():
    if len(group) == 1:
        diff_indices.extend(group)

# 4. 获取最终差异结果并保存
diff_result = combined_df.loc[diff_indices].sort_values('Name')
print(diff_result)
diff_result.to_csv('diff_with_source.csv', index=False)

运行后生成的diff_with_source.csv内容和你期望的完全一致:

NameAgeGenderDataframe
Karan25Maledf1
Karan24Maledf2

方案二:额外标记具体差异列

如果想进一步知道哪些列的值不一样,可以用这个增强版方案,它会新增一列显示差异的列名:

import pandas as pd

# 复用前面的df1和df2数据
df1['Dataframe'] = 'df1'
df2['Dataframe'] = 'df2'
original_columns = df1.columns.drop('Dataframe')

# 1. 按主键(这里用Name)做外连接合并
merged = pd.merge(
    df1.drop('Dataframe', axis=1), 
    df2.drop('Dataframe', axis=1), 
    on='Name', 
    how='outer', 
    suffixes=('_df1', '_df2'), 
    indicator=True
)

# 2. 找出所有非完全匹配的行
diff_rows = merged[merged['_merge'] != 'both']

# 3. 定义函数,找出每行的差异列
def get_diff_columns(row):
    diff_cols = []
    for col in original_columns.drop('Name'):
        if row[f'{col}_df1'] != row[f'{col}_df2']:
            diff_cols.append(col)
    return ', '.join(diff_cols) if diff_cols else 'Only in one dataframe'

diff_rows['Diff_Columns'] = diff_rows.apply(get_diff_columns, axis=1)

# 4. 整理成易读的格式
final_result = pd.DataFrame()
for _, row in diff_rows.iterrows():
    if row['_merge'] == 'left_only':
        final_result = pd.concat([final_result, pd.DataFrame({
            'Name': [row['Name']],
            'Age': [row['Age_df1']],
            'Gender': [row['Gender_df1']],
            'Dataframe': ['df1'],
            'Diff_Columns': ['Only in df1']
        })])
    elif row['_merge'] == 'right_only':
        final_result = pd.concat([final_result, pd.DataFrame({
            'Name': [row['Name']],
            'Age': [row['Age_df2']],
            'Gender': [row['Gender_df2']],
            'Dataframe': ['df2'],
            'Diff_Columns': ['Only in df2']
        })])
    else:
        # 两边都存在但值有差异的情况
        final_result = pd.concat([final_result, pd.DataFrame({
            'Name': [row['Name'], row['Name']],
            'Age': [row['Age_df1'], row['Age_df2']],
            'Gender': [row['Gender_df1'], row['Gender_df2']],
            'Dataframe': ['df1', 'df2'],
            'Diff_Columns': [row['Diff_Columns']]*2
        })])

final_result = final_result.reset_index(drop=True)
print(final_result)
final_result.to_csv('diff_with_details.csv', index=False)

这个方案的输出会更详细,能直接看到差异点:

NameAgeGenderDataframeDiff_Columns
Karan25Maledf1Age
Karan24Maledf2Age

核心思路说明

  • 基础方案通过给每个DataFrame添加来源标识,再按原始数据列分组,筛选出只出现一次的记录,就能准确定位差异记录及其来源。
  • 增强方案通过外连接合并两个表,对比每行的列值,标记出具体的差异列,让结果的可读性更强。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 14:02:43