如何合并含匹配列的两个DataFrame,避免行重复并以NaN补全缺失值?
问题分析
你遇到的行重复是因为pd.merge默认会对相同coll_id下的所有行做笛卡尔积匹配——比如coll_id=1在df1有2行、df2有3行,merge后会生成2×3=6行,这就是重复的核心原因。
解决方案
根据你的需求,以下两种方案可以实现无重复行、缺失值补NaN的效果:
方案1:按组内序号对齐匹配
给两个DataFrame添加组内序号,用coll_id+序号作为连接键,让同组内的行按顺序一一匹配,多余的行自动填充NaN,逻辑更严谨。
import pandas as pd # 构造示例数据 df1 = pd.DataFrame({ 'coll_id': [1,1,2,2], 'item_name': ['item_1','item_2','item_3','item_4'], 'item_val': [20,200,5,13] }) df2 = pd.DataFrame({ 'coll_id': [1,1,1,2], 'stat_name': ['stat_1','stat_2','stat_3','stat_4'] }) # 添加组内自增序号 df1['seq'] = df1.groupby('coll_id').cumcount() df2['seq'] = df2.groupby('coll_id').cumcount() # 按coll_id和序号做外连接 combined = pd.merge(df1, df2, on=['coll_id', 'seq'], how='outer') # 删除临时序号列 combined = combined.drop('seq', axis=1) print(combined)
输出结果:
| coll_id | item_name | item_val | stat_name |
|---|---|---|---|
| 1 | item_1 | 20.0 | stat_1 |
| 1 | item_2 | 200.0 | stat_2 |
| 1 | NaN | NaN | stat_3 |
| 2 | item_3 | 5.0 | stat_4 |
| 2 | item_4 | 13.0 | NaN |
方案2:直接纵向拼接所有行
如果只是想保留两个DataFrame的所有原始行,同一coll_id下的行各自独立存在,缺失列补NaN,用pd.concat即可:
combined = pd.concat([df1, df2], axis=0, ignore_index=True) print(combined)
输出结果:
| coll_id | item_name | item_val | stat_name |
|---|---|---|---|
| 1 | item_1 | 20.0 | NaN |
| 1 | item_2 | 200.0 | NaN |
| 2 | item_3 | 5.0 | NaN |
| 2 | item_4 | 13.0 | NaN |
| 1 | NaN | NaN | stat_1 |
| 1 | NaN | NaN | stat_2 |
| 1 | NaN | NaN | stat_3 |
| 2 | NaN | NaN | stat_4 |
关于你给出的期望示例
你期望的结果中item_2与stat_1的组合不符合常规合并逻辑(相当于手动重复匹配df2的第一行),如果确实需要这种特定规则,需要额外定义匹配关系,但这种需求比较特殊,建议优先考虑上述两种通用方案。
内容的提问来源于stack exchange,提问作者seanstach
相关产品推荐
相关产品推荐

