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

如何追踪两个表头相同但行数不同的DataFrame的变更?

问题描述

我有以下两个DataFrame:

第一个DataFrame:

col1  col2
a  foo   NaN
b  qux   2.0
c  bar   NaN
d  baz   4.0

第二个DataFrame:

col1  col2
a  foo   NaN
c  NaN   3.0
d  baz   5.0
e  xxx   6.0

我期望得到如下格式的Python字典:

out_dict = {
    "b": "deleted", #因为b在df2中已消失
    "c": {"col1": None, "col2": 3}, #因为c的整行在df2中已更新
    "d": {"col2": 5}, #因为仅d的col2在df2中已更新
    "e": {"col1": "xxx", "col2": 6} #因为e是df2中新增的行
}

说明:两个DataFrame的表头始终相同,但行数可能不同。

创建这两个DataFrame的代码如下:

import pandas as pd
import numpy as np

df1 = pd.DataFrame({'col1': {'a': 'foo', 'b': 'qux', 'c': 'bar', 'd': 'baz'},
 'col2': {'a': np.nan, 'b': 2.0, 'c': np.nan, 'd': 4.0}})

df2 = pd.DataFrame({'col1': {'a': 'foo', 'c': np.nan, 'd': 'baz', 'e': 'xxx'},
 'col2': {'a': np.nan, 'c': 3.0, 'd': 5.0, 'e': 6.0}})

我尝试使用df1.compare(df2),但出现错误:

ValueError: Can only compare identically-labeled (both index and columns) DataFrame objects

恳请各位提供帮助 :)

解决方案

直接通过索引对比和值检查来生成目标字典,代码实现如下:

import pandas as pd
import numpy as np

df1 = pd.DataFrame({'col1': {'a': 'foo', 'b': 'qux', 'c': 'bar', 'd': 'baz'},
 'col2': {'a': np.nan, 'b': 2.0, 'c': np.nan, 'd': 4.0}})

df2 = pd.DataFrame({'col1': {'a': 'foo', 'c': np.nan, 'd': 'baz', 'e': 'xxx'},
 'col2': {'a': np.nan, 'c': 3.0, 'd': 5.0, 'e': 6.0}})

out_dict = {}

# 处理被删除的行:df1有但df2没有的索引
deleted_indices = df1.index.difference(df2.index)
for idx in deleted_indices:
    out_dict[idx] = "deleted"

# 处理新增的行:df2有但df1没有的索引,转NaN为None
added_indices = df2.index.difference(df1.index)
for idx in added_indices:
    row_data = df2.loc[idx].replace({np.nan: None}).to_dict()
    out_dict[idx] = row_data

# 处理有更新的行:对比共有的索引,收集值变化的列
common_indices = df1.index.intersection(df2.index)
for idx in common_indices:
    changes = {}
    for col in df1.columns:
        val1 = df1.loc[idx, col]
        val2 = df2.loc[idx, col]
        # 跳过两个都是NaN的情况,否则检查值是否不同
        if pd.isna(val1) and pd.isna(val2):
            continue
        elif val1 != val2:
            changes[col] = None if pd.isna(val2) else val2
    if changes:
        out_dict[idx] = changes

print(out_dict)

运行后输出:

{'b': 'deleted', 'c': {'col1': None, 'col2': 3.0}, 'd': {'col2': 5.0}, 'e': {'col1': 'xxx', 'col2': 6.0}}

注意:因为NaN本身不等于NaN,所以必须用pd.isna()来判断空值,避免误判;同时把df2中的NaN转为None,匹配目标字典的格式要求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 09:23:04