如何按id2过滤去重并合并两个Pandas DataFrame
解决Pandas DataFrame按组合并去重行的问题
核心思路
先提取DF1中所有已存在的(id2, id3)组合,以此过滤DF2,保留DF2中同id2下id3未在DF1出现过的行,最后将过滤后的DF2行与DF1合并,并按id2分组排序,确保原DF1行在前、新增行在后。
代码实现
假设我们有示例数据:
import pandas as pd # 示例DF1 df1 = pd.DataFrame({ 'rowid': [1, 2, 3], 'city': ['北京', '上海', '广州'], 'id2': ['A', 'A', 'B'], 'id3': ['X', 'Y', 'X'] }) # 示例DF2 df2 = pd.DataFrame({ 'city': ['北京', '上海', '深圳', '广州'], 'id2': ['A', 'A', 'A', 'B'], 'id3': ['X', 'Z', 'Y', 'Z'] })
步骤1:标记DF1的已存在组合
创建一个包含DF1所有(id2, id3)组合的集合,用于快速过滤:
existing_pairs = set(df1[['id2', 'id3']].itertuples(index=False, name=None))
步骤2:过滤DF2,保留不重复的行
筛选DF2中(id2, id3)不在existing_pairs里的行:
df2_filtered = df2[~df2[['id2', 'id3']].itertuples(index=False, name=None).isin(existing_pairs)]
步骤3:合并并排序,保证分组结构
给DF1和过滤后的DF2添加排序标记,确保同id2分组内原DF1行优先排列:
df1['sort_key'] = 0 # 原数据标记为0,排在前面 df2_filtered['sort_key'] = 1 # 新增数据标记为1,排在后面 df2_filtered['rowid'] = None # 新增行无rowid,设为None或空值 # 合并后按id2和sort_key排序,最后删除临时排序标记 result = pd.concat([df1, df2_filtered]).sort_values(by=['id2', 'sort_key']).drop('sort_key', axis=1)
最终结果
输出的result结构如下:
| rowid | city | id2 | id3 |
|---|---|---|---|
| 1 | 北京 | A | X |
| 2 | 上海 | A | Y |
| None | 上海 | A | Z |
| 3 | 广州 | B | X |
| None | 广州 | B | Z |
关键说明
- 使用
itertuples生成元组集合,相比逐行判断效率更高,适合处理大量数据 sort_key字段避免合并后同组内原数据和新增数据顺序混乱- 若需对rowid做特殊处理(比如填充特定标识),可直接修改
df2_filtered['rowid']的赋值逻辑
内容的提问来源于stack exchange,提问作者padawan
相关产品推荐
相关产品推荐

