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

基于指定列筛选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)

代码优势

  1. 通用性强:无需针对每个岗位写单独逻辑,新增岗位自动适配
  2. 效率更高:用集合存储已选候选人,查询时间复杂度为O(1),远优于列表的O(n)
  3. 逻辑清晰:分组处理每个岗位,过滤-选中-记录的流程一目了然

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 07:32:18