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

如何匹配含重复项的DataFrame对并保留未匹配项?

处理含重复项的DataFrame中(ID, Value)对的匹配与剩余实例保留

可以通过给重复的(ID, Value)对添加组内序号的方式实现精准匹配,再找出未匹配的实例。以下是两种可行方案:

方法一:组内编号+外连接筛选

这种方法通过给每个重复的匹配对添加唯一序号,实现一对一的精准匹配,再筛选出未匹配的行:

  1. 为两个DataFrame的每个(ID, Value)组添加累计计数,用来区分同组内的重复实例
  2. 基于ID、Value和计数列做外连接,保留所有行
  3. 筛选出仅在其中一个DataFrame中存在的行,即为未匹配的实例
import pandas as pd

# 修正示例数据:字符串需加引号
df_1 = pd.DataFrame(data={'ID':['A', 'A', 'A', 'A','B','B','B','D'], 'Value':[1, 1, 1, 2, 1, 1, 2,3]})
df_2 = pd.DataFrame(data={'ID':['A','A','A','B','B','C'], 'Value':[1,1,2,1,2,4]})

# 给每个(ID, Value)组添加组内序号(从0开始计数)
df_1['match_idx'] = df_1.groupby(['ID', 'Value']).cumcount()
df_2['match_idx'] = df_2.groupby(['ID', 'Value']).cumcount()

# 外连接,标记行的来源
merged = pd.merge(df_1, df_2, on=['ID', 'Value', 'match_idx'], how='outer', indicator=True)

# 筛选出仅在df1或仅在df2中的行
remaining_rows = merged[merged['_merge'] != 'both']

# 整理成目标格式
remaining_df = remaining_rows[['ID', 'Value']].reset_index(drop=True)
print(remaining_df)

运行结果与你期望的一致:

ID  Value
0  A      1
1  B      1
2  B      2
3  C      4
4  D      3

方法二:基于统计差值生成剩余行(对应你的思路)

如果你想通过拼接字段、统计数量的方式实现,可以按以下步骤操作:

  1. 分别统计两个DataFrame中每个(ID, Value)对的出现次数
  2. 合并统计结果,计算每个对的数量差值
  3. 根据差值生成对应的剩余行
# 统计每个(ID, Value)对的出现次数
counts_df1 = df_1.groupby(['ID', 'Value']).size().reset_index(name='count_df1')
counts_df2 = df_2.groupby(['ID', 'Value']).size().reset_index(name='count_df2')

# 合并统计结果,缺失的数量补0
total_counts = pd.merge(counts_df1, counts_df2, on=['ID', 'Value'], how='outer').fillna(0)

# 计算每个对需要保留的实例数量:取两边数量的差值(仅保留正数)
total_counts['remaining_num'] = total_counts.apply(
    lambda row: max(row['count_df1'] - row['count_df2'], 0) if row['count_df1'] > row['count_df2'] 
    else max(row['count_df2'] - row['count_df1'], 0),
    axis=1
)

# 根据剩余数量生成重复行
remaining_df = total_counts[total_counts['remaining_num'] > 0].apply(
    lambda row: pd.DataFrame({'ID': [row['ID']]*int(row['remaining_num']), 'Value': [row['Value']]*int(row['remaining_num'])}),
    axis=1
).concat().reset_index(drop=True)

print(remaining_df)

这个方案的核心是先统计每个匹配对的数量差,再根据差值生成对应的剩余实例,完全贴合你最初的思路。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 08:08:35