基于指定列筛选DataFrame首行并去重ID_Y的Pandas实现求助
问题描述
现有三个DataFrame:
df1
CAT1 CAT2 CAT3 ID_X A1 B C X1 A1 B C X2 A2 B C X3 A2 B C X4 A2 B C X5 A3 B C X6 A4 B C X7
df2
CAT1 CAT2 CAT3 ID_Y A1 B C Y1 A1 B C Y2 A1 B C Y3 A2 B C Y4 A2 B C Y5 A3 B C Y6 A5 B C Y7
df3
ID_X ID_Y ID_XY X1 Y1 X1Y1 X2 Y3 X2Y3 X3 Y4 X3Y4 X4 Y5 X4Y5 X6 Y6 X6Y6
需要通过以下三步得到最终结果:
Step1:内连接并生成ID_XY列
按CAT1、CAT2、CAT3内连接df1与df2,基于ID_X和ID_Y生成ID_XY列,得到df_merge。
修正后代码(原代码中
merge1为笔误,应为df_merge)
df_merge = pd.merge(df1, df2, how="inner", on=["CAT1", "CAT2", "CAT3"]) df_merge['ID_XY'] = df_merge['ID_X'] + df_merge['ID_Y']
Step2:移除已存在的ID_XY行
移除df_merge中ID_XY存在于df3的行,得到df_merge1。
代码
df_merge1 = df_merge[~df_merge.ID_XY.isin(df3.ID_XY)]
df_merge1结果
CAT1 CAT2 CAT3 ID_X ID_Y ID_XY A1 B C X1 Y2 X1Y2 A1 B C X1 Y3 X1Y3 A1 B C X2 Y1 X2Y1 A1 B C X2 Y2 X2Y2 A2 B C X3 Y5 X3Y5 A2 B C X4 Y4 X4Y4 A2 B C X5 Y4 X5Y4 A2 B C X5 Y5 X5Y5
Step3:岗位与候选人分配(高效解决方案)
需求核心:将ID_X视为岗位,ID_Y视为候选人,需为每个岗位分配第一个未被其他岗位选中的候选人,即同一岗位仅选首行候选,且候选人不可重复分配。最终目标df_final如下:
df_final结果
CAT1 CAT2 CAT3 ID_X ID_Y ID_XY A1 B C X1 Y2 X1Y2 A1 B C X2 Y1 X2Y1 A2 B C X3 Y5 X3Y5 A2 B C X4 Y4 X4Y4
替代手动拆分的高效代码
无需硬编码岗位名称,通过分组+状态追踪实现,适配任意数量的岗位:
# 复制数据避免修改原表 df_temp = df_merge1.copy() # 用集合存储已选中的候选人,查询效率远高于列表 selected_y = set() # 存储最终分配结果 result = [] # 按ID_X分组,保证每个岗位仅处理一次,保留原顺序 for _, group in df_temp.groupby('ID_X', sort=False): # 过滤已被选中的候选人,取第一个可用行 available = group[~group['ID_Y'].isin(selected_y)].iloc[:1] if not available.empty: result.append(available) # 将选中的候选人加入集合 selected_y.add(available['ID_Y'].values[0]) # 合并结果并重置索引 df_final = pd.concat(result, ignore_index=True)
代码优势
- 通用性强:无需针对每个岗位写单独逻辑,新增岗位自动适配
- 效率更高:用集合存储已选候选人,查询时间复杂度为O(1),远优于列表的O(n)
- 逻辑清晰:分组处理每个岗位,过滤-选中-记录的流程一目了然
内容的提问来源于stack exchange,提问作者AB14
相关产品推荐
相关产品推荐

