解决Pandas按指定列匹配DataFrame时行序导致的误判问题
问题:Pandas对比DataFrame指定列时因行序误判不匹配
我用以下Pandas代码对比两个DataFrame的指定列并找出不匹配行:
merged_df = pd.merge(df_old, df_new, on=['column1','column2','column3'], how='right', indicator=True) # Filter rows where the indicator column is 'left_only' or 'right_only' mismatched_rows = merged_df[merged_df['_merge'] == 'right_only'] #.isin(['left_only', 'right_only'])] # Drop the indicator column mismatched_rows = mismatched_rows.drop('_merge', axis=1) # Display the mismatched rows #print(mismatched_rows) mismatched_rows.to_csv(file_name + "_output_mismatched.csv",index=False)
但发现代码会因行顺序误判不匹配:当两个DataFrame的行内容完全一致仅顺序不同时,仍被判定为不匹配。例如:
# dataframe 1 column1 column2 column3 x y z a b c # dataframe 2 column1 column2 column3 a b c x y z
上述示例中两行的column1、column2、column3值完全匹配,仅行序不同,但代码仍将它们识别为不匹配。请问如何修改代码让这类行被正确判定为匹配?
解决方案
核心需求是忽略行顺序,仅根据指定列的内容判断行是否匹配,可通过以下两种方式调整代码:
方法1:外连接筛选非双向匹配行
这种方法能找出所有仅在其中一个DataFrame存在的行,完全不受行顺序影响:
# 用outer连接保留两边所有行,并标记行的来源 merged_df = pd.merge(df_old, df_new, on=['column1','column2','column3'], how='outer', indicator=True) # 筛选出仅在单表存在的行(即不匹配行) mismatched_rows = merged_df[merged_df['_merge'] != 'both'] # 拆分不同类型的不匹配结果(可选) only_in_old = mismatched_rows[mismatched_rows['_merge'] == 'left_only'].drop('_merge', axis=1) only_in_new = mismatched_rows[mismatched_rows['_merge'] == 'right_only'].drop('_merge', axis=1) # 保存结果 only_in_old.to_csv(file_name + "_only_in_old.csv", index=False) only_in_new.to_csv(file_name + "_only_in_new.csv", index=False)
方法2:处理重复行场景
如果DataFrame中存在同一列组合重复出现的情况,需要先统计每个组合的出现次数再对比差异:
# 统计旧表中每个列组合的出现次数 old_counts = df_old.groupby(['column1','column2','column3']).size().reset_index(name='count_old') # 统计新表中每个列组合的出现次数 new_counts = df_new.groupby(['column1','column2','column3']).size().reset_index(name='count_new') # 合并统计结果,缺失的次数用0填充 count_merge = pd.merge(old_counts, new_counts, on=['column1','column2','column3'], how='outer', fill_value=0) # 筛选出次数不一致的行 mismatched_counts = count_merge[count_merge['count_old'] != count_merge['count_new']] mismatched_counts.to_csv(file_name + "_mismatched_counts.csv", index=False)
原代码误判原因
原代码使用how='right'仅保留新表的行,若新表的行在旧表中存在(无论顺序),_merge会标记为both,不会被merged_df['_merge'] == 'right_only'筛选出来。你遇到的误判大概率是实际数据存在重复行,或是曾启用过isin(['left_only', 'right_only'])但未同步调整逻辑导致的。
内容的提问来源于stack exchange,提问作者Md Parvez Alam
相关产品推荐
相关产品推荐

