
本文旨在提供一种高效、专业的Pandas DataFrame差异比较方法。通过利用DataFrame.compare()函数,结合索引设置和结果重塑技巧,我们能够精确地识别两个DataFrame之间在行和列上的差异,并最终生成一个仅包含这些差异化数据的简洁视图,从而简化数据审计和变更追踪工作。
引言:识别Pandas DataFrame中的差异
在数据分析和处理的日常工作中,我们经常需要比较两个结构相似的Pandas DataFrame,以找出它们之间的不同之处。例如,比较不同时间点的数据快照,或验证数据处理前后的变化。理想情况下,我们希望得到的输出不仅能指出哪些行存在差异,还能明确显示这些差异具体发生在哪些列上,并且只保留这些差异化的信息,剔除完全相同的部分。
考虑以下两个DataFrame df1 和 df2:
import pandas as pddata1 = { '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: df1 has 2, df2 has 99 'result_2': [10, 20, 30, 100], # Another difference for demonstration '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_10 Patrick 2023-01-01 1 10 1231 Patrick 2023-01-02 2 20 1232 Patrick 2023-01-03 3 30 1233 Patrick 2023-01-04 4 40 123
df2:
pet_name exam_day result_1 result_2 pre_result_10 Patrick 2023-01-01 1 10 1231 Patrick 2023-01-02 99 20 1232 Patrick 2023-01-03 3 30 1233 Patrick 2023-01-04 4 100 123
我们注意到 df1 和 df2 在以下位置存在差异:
pet_name=’Patrick’, exam_day=’2023-01-02′ 行的 result_1 列:df1 为 2,df2 为 99。pet_name=’Patrick’, exam_day=’2023-01-04′ 行的 result_2 列:df1 为 40,df2 为 100。
如果仅仅使用 merge(…, indicator=True, how=”outer”) 并过滤 _merge != “both”,虽然能识别出有差异的行,但会保留所有列,并且对同一差异行会分别显示 left_only 和 right_only 两条记录,无法直接突出差异所在的具体列。我们的目标是获得一个更精炼的视图,仅包含差异行和差异列,同时保留关键的标识列。
核心解决方案:使用DataFrame.compare()
Pandas 1.1.0 版本引入的 DataFrame.compare() 方法是专门为解决这类问题而设计的。它能够进行元素级别的比较,并以一种结构化的方式展示差异。
步骤一:准备数据——设置索引
为了让 compare() 方法能够正确地对齐和比较行,我们需要将DataFrame中的关键标识列(例如 pet_name 和 exam_day)设置为索引。这些列通常被称为“维度”列或“主键”列,它们在比较过程中不应被视为可变的值,而是作为行的唯一标识符。
df1_indexed = df1.set_index(['pet_name', 'exam_day'])df2_indexed = df2.set_index(['pet_name', 'exam_day'])print("df1_indexed (partial view):")print(df1_indexed.head(2))
输出示例:
df1_indexed (partial view): result_1 result_2 pre_result_1pet_name exam_day Patrick 2023-01-01 1 10 123 2023-01-02 2 20 123
通过设置索引,compare() 方法将基于这些索引值来匹配行。
步骤二:执行比较——compare(align_axis=0)
接下来,我们使用 compare() 方法对两个已设置索引的DataFrame进行比较。关键参数是 align_axis=0,它指示 compare() 在行级别进行对齐。
diff_df_raw = df1_indexed.compare(df2_indexed, align_axis=0)print("Raw comparison output (diff_df_raw):")print(diff_df_raw)
输出示例:
Raw comparison output (diff_df_raw): result_1 result_2pet_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() 方法的输出特点:
行索引: compare() 会在原始索引的基础上增加一个内部级别 (self 和 other),用于区分 df1 (self) 和 df2 (other) 中的值。列过滤: compare() 会自动过滤掉所有值都完全相同的列。在我们的例子中,pre_result_1 列在两个DataFrame中完全相同,因此它没有出现在输出中。NaN 填充: 对于在特定行中没有差异的列,compare() 会用 NaN 填充。例如,在 2023-01-02 的差异行中,result_2 并没有差异,因此显示为 NaN。
步骤三:重塑输出——droplevel()与reset_index()
为了将 compare() 的输出重塑成我们期望的简洁格式(即每行显示一个差异值,且包含原始的关键标识列),我们需要进行额外的后处理。
droplevel(-1): 这一步用于删除行索引中表示 self/other 的最内层级别。这样,对于同一个 (pet_name, exam_day) 组合,来自 self 和 other 的差异值将作为独立的
以上就是高效识别Pandas DataFrame差异并仅保留差异化数据的详细内容,更多请关注创想鸟其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1373057.html
微信扫一扫
支付宝扫一扫