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

Pandas新增列计算结果重复问题求助

问题描述

现有两个Pandas DataFrame:

  1. 安全角色定义表(roleDefDF):约3000个角色,结构如下:
ROLE_NAMEDEPARTMENT_CODES
Role 1DPT_60001716,DPT_60009998
Role 2DPT_62068951
  1. 员工详情表(factTabDF):约20万名员工数据,结构如下:
INDEXEMPLOYEE_IDDEPARTMENT_CODE
0EMP_001DPT_60001716
1EMP_002DPT_62068951
2EMP_003DPT_62068951
3EMP_004DPT_60001716
4EMP_005DPT_60009998
5EMP_006DPT_60009999

需要匹配每个员工对应的可见角色,预期结果如下:

INDEXEMPLOYEE_IDROLE_NAME
0EMP_001Role 1
1EMP_002Role 2
2EMP_003Role 2
3EMP_004Role 1
4EMP_005Role 1
5EMP_006

最初通过遍历roleDefDF实现了需求,但性能极差。尝试新增列INDEX_OF_VISIBLE_EMPLOYEES存储角色可见的员工索引列表,代码如下:

roleDefDF['INDEX_OF_VISIBLE_EMPLOYEES'] = ','.join(str(x) for x in factTabDF.loc[factTabDF['DEPARTMENT_CODE'].apply(lambda x: any([x in roleDefDF['DEPARTMENT_CODES'].str.split(",",expand=False).values[0]]))].index.tolist())

预期生成的roleDefDF应该是:

ROLE_NAMEDEPARTMENT_CODESINDEX_OF_VISIBLE_EMPLOYEES
Role 1DPT_60001716,DPT_600099980,3,4
Role 2DPT_620689511,2

但实际运行后,所有行的INDEX_OF_VISIBLE_EMPLOYEES都重复第一行的值:

ROLE_NAMEDEPARTMENT_CODESINDEX_OF_VISIBLE_EMPLOYEES
Role 1DPT_60001716,DPT_600099980,3,4
Role 2DPT_620689510,3,4

请问该问题的原因是什么?如何解决?


原因分析

你的代码存在两个核心问题:

  1. 固定取第一行的部门列表:roleDefDF['DEPARTMENT_CODES'].str.split(",",expand=False).values[0]直接取了values数组的第一个元素(即Role 1的部门列表),整个过滤逻辑都基于Role 1的规则计算,自然只会得到Role 1对应的员工索引。
  2. 标量广播赋值:你计算出的是一个单一字符串(比如"0,3,4"),当把这个标量赋值给DataFrame列时,Pandas会自动将其广播到所有行,导致所有行结果完全相同。

解决方案

方案1:修正原思路,逐行处理角色表

用apply遍历roleDefDF的每一行,针对每个角色的部门列表计算对应的员工索引:

# 预处理factTabDF,建立部门到索引的映射,提升查询效率
dept_to_indices = factTabDF.groupby('DEPARTMENT_CODE')['INDEX'].apply(list).to_dict()

def get_visible_indices(row):
    depts = row['DEPARTMENT_CODES'].split(',')
    indices = []
    for dept in depts:
        indices.extend(dept_to_indices.get(dept, []))
    # 去重并排序(按需选择)
    indices = sorted(list(set(indices)))
    return ','.join(map(str, indices))

roleDefDF['INDEX_OF_VISIBLE_EMPLOYEES'] = roleDefDF.apply(get_visible_indices, axis=1)

方案2:高效关联方案(推荐,适配大数据量)

针对20万员工+3000角色的大数据量,更高效的方式是先拆分角色表的部门,再与员工表关联后聚合:

# 1. 拆分角色表的部门列,将一个角色的多个部门拆成多行
role_dept_expanded = roleDefDF.assign(DEPARTMENT_CODE=roleDefDF['DEPARTMENT_CODES'].str.split(',')).explode('DEPARTMENT_CODE')

# 2. 和员工表关联,得到每个角色对应的员工记录
role_employee_match = role_dept_expanded.merge(factTabDF, on='DEPARTMENT_CODE', how='left')

# 3. 按角色聚合,收集员工索引
role_visible_indices = role_employee_match.groupby('ROLE_NAME')['INDEX'].agg(lambda x: ','.join(map(str, sorted(x.dropna().unique())))).reset_index()

# 4. 合并回原角色表
roleDefDF = roleDefDF.merge(role_visible_indices, on='ROLE_NAME', how='left')
roleDefDF.rename(columns={'INDEX': 'INDEX_OF_VISIBLE_EMPLOYEES'}, inplace=True)
# 处理无匹配员工的角色
roleDefDF['INDEX_OF_VISIBLE_EMPLOYEES'] = roleDefDF['INDEX_OF_VISIBLE_EMPLOYEES'].fillna('')

如果最终目标是生成员工-角色匹配表,直接整理关联后的结果即可:

employee_role_match = role_employee_match[['INDEX', 'EMPLOYEE_ID', 'ROLE_NAME']].drop_duplicates()
# 合并原员工表,补充无匹配角色的员工
final_result = factTabDF[['INDEX', 'EMPLOYEE_ID']].merge(employee_role_match, on=['INDEX', 'EMPLOYEE_ID'], how='left').fillna('')

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 20:03:18