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

如何在Python中对比DataFrame,识别单元格变更、新增条目并记录日期?

对比两个DataFrame并标记差异、新增项及变更日期

要实现你的需求,核心是通过唯一标识列(比如示例中的ID)匹配两个DataFrame的行,再结合列值对比区分状态,同时添加变更日期。以下是基于pandas的完整实现方案:


步骤1:模拟示例数据

先还原示例中的两个DataFrame(你可以替换成自己的真实数据):

import pandas as pd
from datetime import datetime

# 原始数据df1
df1 = pd.DataFrame({
    'ID': [1, 2, 3],
    'Name': ['Alice', 'Bob', 'Charlie'],
    'Age': [25, 30, 35]
})

# 更新后的数据df2
df2 = pd.DataFrame({
    'ID': [1, 2, 4],
    'Name': ['Alice', 'Bob', 'Dave'],
    'Age': [26, 30, 28]
})

步骤2:合并数据并标记来源

用outer join合并两个DataFrame,通过_merge字段区分行的来源(仅在df1、仅在df2、两边都有):

merged = pd.merge(df2, df1, on='ID', how='outer', suffixes=('_new', '_old'), indicator=True)

步骤3:标记状态与变更日期

初始化状态列和变更日期列,根据行的来源和列值匹配情况标记状态:

# 初始化列
merged['Status'] = ''
merged['Change Date'] = pd.NaT
current_date = datetime.today().strftime('%Y-%m-%d')

# 标记新增条目(仅在df2中存在)
merged.loc[merged['_merge'] == 'left_only', ['Status', 'Change Date']] = ['New Entry', current_date]

# 标记无变更条目(ID匹配且所有非ID列值一致)
non_id_cols = [col for col in df1.columns if col != 'ID']
match_mask = merged.apply(lambda row: all(row[f'{col}_new'] == row[f'{col}_old'] for col in non_id_cols), axis=1)
merged.loc[match_mask, 'Status'] = 'No Change'

# 标记更新条目(ID匹配但存在列值变更)
update_mask = (merged['_merge'] == 'both') & ~match_mask
merged.loc[update_mask, ['Status', 'Change Date']] = ['Updated', current_date]

# 可选:标记移除条目(仅在df1中存在)
merged.loc[merged['_merge'] == 'right_only', ['Status', 'Change Date']] = ['Removed', current_date]

步骤4:整理输出结果

将合并后的数据整理成目标格式,保留需要的列:

# 填充移除条目的原始值
for col in non_id_cols:
    merged[col] = merged[f'{col}_new'].fillna(merged[f'{col}_old'])

# 生成最终结果df3
output_cols = ['ID'] + non_id_cols + ['Status', 'Change Date']
df3 = merged[output_cols].sort_values('ID').reset_index(drop=True)

print(df3)

运行后输出的df3如下:

ID     Name  Age     Status Change Date
0   1    Alice   26     Updated  2024-05-20
1   2      Bob   30  No Change         NaT
2   3  Charlie   35     Removed  2024-05-20
3   4     Dave   28  New Entry  2024-05-20

额外:标记具体变更的单元格

如果需要明确指出哪几列发生了变更,可以添加Changed Columns列:

def get_changed_columns(row):
    changed = []
    for col in non_id_cols:
        if row[f'{col}_new'] != row[f'{col}_old']:
            changed.append(col)
    return ', '.join(changed) if changed else None

merged['Changed Columns'] = merged.apply(get_changed_columns, axis=1)

# 更新输出列
output_cols.append('Changed Columns')
df3 = merged[output_cols].sort_values('ID').reset_index(drop=True)

此时df3会新增一列显示变更的列名,比如ID=1的行显示Age。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 18:25:36