如何在Pandas中合并含重复ID的DataFrame并避免笛卡尔积
解决方法
核心思路是给每个key下的行添加组内序号,让重复的key能通过序号唯一匹配,避免生成笛卡尔积。
步骤1:给两个DataFrame添加组内序号
对left和right按key分组,用cumcount()生成每个组内的行索引(从0开始):
import pandas as pd left = pd.DataFrame( { "key": ["K0", "K0", "K1", "K2", "K2", "K3", "K4"], "A": ["A0", 2, "A1", "A2", 4, "A3", "A4"], "B": ["B0", 3, "B1", "B2", 4, "B3", "B4"], } ) right = pd.DataFrame( { "key": ["K0", "K0", "K1", "K2", "K3"], "C": ["C0", 5, "C1", "C2", "C3"], "D": ["D0", 7, "D1", "D2", "D3"], } ) # 添加组内序号 left['seq'] = left.groupby('key').cumcount() right['seq'] = right.groupby('key').cumcount()
此时left变为:
key A B seq 0 K0 A0 B0 0 1 K0 2 3 1 2 K1 A1 B1 0 3 K2 A2 B2 0 4 K2 4 4 1 5 K3 A3 B3 0 6 K4 A4 B4 0
right变为:
key C D seq 0 K0 C0 D0 0 1 K0 5 7 1 2 K1 C1 D1 0 3 K2 C2 D2 0 4 K3 C3 D3 0
步骤2:用key+seq作为合并键做左连接
现在用key和seq共同作为连接键,就能实现同key下的行一一对应匹配:
result = pd.merge(left, right, how='left', on=['key', 'seq']) # 可选:删除临时的seq列 result = result.drop('seq', axis=1)
最终结果
得到的result就是你期望的格式:
key A B C D 0 K0 A0 B0 C0 D0 1 K0 2 3 5 7 2 K1 A1 B1 C1 D1 3 K2 A2 B2 C2 D2 4 K2 4 4 C2 D2 5 K3 A3 B3 C3 D3 6 K4 A4 B4 NaN NaN
补充说明
- 这种方法依赖同key下的行顺序,确保左右表中同key的行是一一对应的(比如左表K0的第1行对应右表K0的第1行),如果行顺序不对,需要先按业务逻辑排序后再添加序号。
- 如果某个key在右表中的行数少于左表,多余的行依然会保留并填充
NaN,符合左连接的规则。
内容的提问来源于stack exchange,提问作者Detox
相关产品推荐
相关产品推荐

