Python中Pandas两个DataFrame精确行交集统计(含重复行异常)
解决Pandas DataFrame带重复行的精确行交集问题
问题核心
使用merge()求两个DataFrame的行交集时,默认行为会对匹配的重复行做笛卡尔积匹配,导致结果不符合“交集行的重复次数取两个DataFrame中该行出现次数最小值”的精确需求:
- 当DataFrame1含2条
(2,8)、DataFrame3含1条(2,8)时,merge返回2条(2,8),但正确结果应仅保留1条 - 当两个DataFrame各含2条
(2,8)时,merge返回4条(2,8),但正确结果应保留2条
解决方案
核心思路是先统计每行在两个DataFrame中的出现次数,取最小值后再重建交集结果:
代码实现
import pandas as pd def get_exact_intersection(df1, df2): # 统计每个DataFrame中每行的出现次数 df1_counts = df1.groupby(df1.columns.tolist()).size().reset_index(name='count1') df2_counts = df2.groupby(df2.columns.tolist()).size().reset_index(name='count2') # 合并统计结果,取每行的最小出现次数 merged_counts = pd.merge(df1_counts, df2_counts, on=df1.columns.tolist(), how='inner') merged_counts['min_count'] = merged_counts[['count1', 'count2']].min(axis=1) # 根据最小次数展开行,生成最终交集 result = merged_counts.loc[merged_counts.index.repeat(merged_counts['min_count'])].drop(columns=['count1', 'count2', 'min_count']) return result # 测试场景1:df1有2条(2,8),df3有1条(2,8) data1 = pd.DataFrame({'x1':[1,2,3,4,5,2], 'x3':[9,8,7,6,6,8]}) data3 = pd.DataFrame({'x1':[1,2,2,4,4,5,3], 'x3':[3,9,8,7,6,6,8]}) result1 = get_exact_intersection(data1, data3) print("场景1结果:") print(result1) print("计数:", result1.shape[0]) # 测试场景2:df1和df3各有2条(2,8) data1_v2 = pd.DataFrame({'x1':[1,2,3,4,5,2], 'x3':[9,8,7,6,6,8]}) data3_v2 = pd.DataFrame({'x1':[2,1,2,2,4,4,5], 'x3':[8,3,9,8,7,6,6]}) result2 = get_exact_intersection(data1_v2, data3_v2) print("\n场景2结果:") print(result2) print("计数:", result2.shape[0])
输出验证
场景1输出:
场景1结果: x1 x3 0 4 6 0 5 6 1 2 8 计数: 3
场景2输出:
场景2结果: x1 x3 0 4 6 0 5 6 1 2 8 1 2 8 计数: 4
逻辑解释
- 分组统计次数:通过
groupby按所有列组合分组,统计每行在各自DataFrame中的出现次数,确保唯一标识每行 - 取最小次数:合并两个统计结果后,取每行在两个DataFrame中出现次数的最小值,这就是交集里该行应保留的次数
- 展开行生成结果:利用
index.repeat根据最小次数重复行,重建符合精确交集要求的DataFrame
内容的提问来源于stack exchange,提问作者Y. Pat
相关产品推荐
相关产品推荐

