
在数据分析和数据质量管理中,经常需要比较两个结构相似的DataFrame,以找出它们之间的具体差异。例如,比较同一数据集在不同时间点的快照,或者比较不同数据源中相同实体的信息。常见的需求是不仅要识别出有差异的行,还要进一步识别出这些行中具体是哪些列的值发生了变化,并最终只保留这些差异信息以及作为标识的维度列。
考虑以下两个DataFrame df1 和 df2:
import pandas as pd
data1 = {
'pet_name': ['Patrick', 'Patrick', 'Patrick', 'Patrick'],
'exam_day': ['2023-01-01', '2023-01-02', '2023-01-03', '2023-01-04'],
'result_1': [1, 2, 3, 4],
'result_2': [10, 20, 30, 40],
'pre_result_1': [123, 123, 123, 123]
}
df1 = pd.DataFrame(data1)
data2 = {
'pet_name': ['Patrick', 'Patrick', 'Patrick', 'Patrick'],
'exam_day': ['2023-01-01', '2023-01-02', '2023-01-03', '2023-01-04'],
'result_1': [1, 99, 3, 4], # Difference here (2 vs 99)
'result_2': [10, 20, 30, 100], # Difference here (40 vs 100)
'pre_result_1': [123, 123, 123, 123]
}
df2 = pd.DataFrame(data2)
print("df1:")
print(df1)
print("\ndf2:")
print(df2)输出:
df1: pet_name exam_day result_1 result_2 pre_result_1 0 Patrick 2023-01-01 1 10 123 1 Patrick 2023-01-02 2 20 123 2 Patrick 2023-01-03 3 30 123 3 Patrick 2023-01-04 4 40 123 df2: pet_name exam_day result_1 result_2 pre_result_1 0 Patrick 2023-01-01 1 10 123 1 Patrick 2023-01-02 99 20 123 2 Patrick 2023-01-03 3 30 123 3 Patrick 2023-01-04 4 100 123
我们的目标是得到一个DataFrame,其中只包含 pet_name 和 exam_day 作为标识列,以及所有值存在差异的列。例如,对于上述数据,期望的输出应类似:
pet_name exam_day result_1 result_2 0 Patrick 2023-01-02 2.0 NaN 1 Patrick 2023-01-02 99.0 NaN 2 Patrick 2023-01-04 NaN 40.0 3 Patrick 2023-01-04 NaN 100.0
可以看到,pre_result_1 列因其值在两个DataFrame中完全相同而被移除。
Pandas 提供了 DataFrame.compare 方法,专门用于执行元素级别的比较,并返回一个突出显示差异的DataFrame。这是实现我们目标的最有效工具。
DataFrame.compare(other, align_axis=1, keep_equal=False, keep_shape=False)
compare 方法的强大之处在于它会自动识别并只返回那些值存在差异的列。
为了达到期望的输出,我们需要执行以下步骤:
下面是具体的实现代码:
# 1. 设置索引
df1_indexed = df1.set_index(['pet_name', 'exam_day'])
df2_indexed = df2.set_index(['pet_name', 'exam_day'])
# 2. 执行比较
# compare方法默认keep_equal=False,因此会自动移除完全相同的列
diff_df_raw = df1_indexed.compare(df2_indexed, align_axis=0)
print("--- 原始 compare 输出 ---")
print(diff_df_raw)
# 3. 后处理索引:删除由 compare 产生的 'self'/'other' 级别
# 这个级别是行MultiIndex的最后一个级别
diff_df_processed = diff_df_raw.droplevel(-1)
# 4. 重置索引,将维度列变回普通列
final_diff_df = diff_df_processed.reset_index()
print("\n--- 最终差异 DataFrame ---")
print(final_diff_df)代码解析与输出:
首先,df1_indexed.compare(df2_indexed, align_axis=0) 的输出 diff_df_raw 如下:
--- 原始 compare 输出 ---
result_1 result_2
pet_name exam_day
Patrick 2023-01-02 self 2.0 NaN
other 99.0 NaN
2023-01-04 self NaN 40.0
other NaN 100.0可以看到,compare 方法成功地识别了 result_1 和 result_2 列中的差异。它创建了一个MultiIndex行,其中包含 pet_name、exam_day 以及一个指示数据来源(self 或 other)的级别。同时,result_1 和 result_2 列本身也带有MultiIndex(('result_1', 'self'), ('result_1', 'other') 等)。这里由于 keep_equal=False,pre_result_1 列被自动移除了。
然后,droplevel(-1) 操作移除了行MultiIndex中的最后一个级别('self' 或 'other'),使得行索引只剩下 ('pet_name', 'exam_day')。
最后,reset_index() 将 pet_name 和 exam_day 从索引变回普通列,得到我们期望的最终结果:
--- 最终差异 DataFrame --- pet_name exam_day result_1 result_2 0 Patrick 2023-01-02 2.0 NaN 1 Patrick 2023-01-02 99.0 NaN 2 Patrick 2023-01-04 NaN 40.0 3 Patrick 2023-01-04 NaN 100.0
这个结果清晰地展示了两个DataFrame之间的所有差异,并且只保留了发生变化的列以及作为行标识的维度列。
通过 DataFrame.compare 方法,结合适当的索引设置和后处理,我们可以高效且准确地从两个Pandas DataFrame中提取出所有值存在差异的行和列。这种方法不仅简化了差异识别过程,而且提供了清晰、易于理解的差异报告,对于数据验证、版本控制和数据质量监控等场景都非常有用。掌握此技巧,将大大提升您在Pandas中处理数据差异的能力。
以上就是Pandas DataFrame差异提取:仅保留差异行与列的教程的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号