
本文介绍如何使用pandas对hr系统中同一员工的多条任职记录进行去重聚合:以最高fte值对应部门为主岗位,同时将所有部门(按fte降序)拼接为描述字段,并支持带fte数值的格式化输出。
本文介绍如何使用pandas对hr系统中同一员工的多条任职记录进行去重聚合:以最高fte值对应部门为主岗位,同时将所有部门(按fte降序)拼接为描述字段,并支持带fte数值的格式化输出。
在人力资源数据处理中,员工常存在多角色、跨部门、多合同类型等复合任职情况(如兼职教师同时在School 1、School 2、School 3承担不同FTE比例的工作)。原始数据每日更新,存在大量逻辑重复(仅EntryID和ChangeDate不同),需在夜间ETL任务中完成语义级去重与结构化聚合——即保留业务关键字段(如最高FTE对应的主部门),同时汇总全部关联信息(如所有部门+对应FTE)。
核心目标有三:
✅ 以 Employee# 为分组键;
✅ 主部门(Department)取该员工FTE最大值对应的一行(非简单取首/末);
✅ Description 字段需按FTE降序排列,并支持两种格式:
▸ 基础版:"School 2, School 1, School 3"
▸ 增强版:"School 2 (0.5330 FTE), School 1 (0.1801 FTE), School 3 (0.1000 FTE)"
✅ 正确实现步骤(推荐方案)
import pandas as pd
# 假设原始DataFrame名为df,包含列:Employee#, Firstname, Lastname, Type, Title, Department, Starting, Ending, FTE
# 第一步:按Employee#升序 + FTE降序排序(确保每组内最高FTE排最前)
df_sorted = df.sort_values(['Employee#', 'FTE'], ascending=[True, False])
# 第二步:分组聚合 —— 关键在于分离“主字段”与“汇总字段”
agg_dict = {
'Firstname': 'first',
'Lastname': 'first',
'Type': 'first',
'Title': 'first',
'Starting': 'first',
'Ending': 'first',
'FTE': 'first', # 取最高FTE值(因已排序)
# 拼接所有Department(按FTE降序),并附带FTE数值(增强版)
'Description': lambda x: ', '.join([
f"{dept} ({fte:.4f} FTE)"
for dept, fte in zip(
df_sorted.loc[x.index, 'Department'],
df_sorted.loc[x.index, 'FTE']
)
]),
# 主部门:直接取排序后每组第一个Department
'Department': 'first'
}
result = df_sorted.groupby('Employee#').agg(agg_dict).reset_index()
⚠️ 注意事项:
- 不可直接对
Department用', '.join后再取first:这会导致主部门丢失语义(如取到拼接字符串而非真实部门名);必须通过排序保障'first'即为最高FTE部门。lambda x:中的x.index是关键——它确保能精准定位当前分组在原排序DataFrame中的位置,从而关联到对应FTE值,避免索引错位。- 若需去除重复部门(如同一部门出现多次但FTE微调),可在
Description生成前加去重逻辑:list(dict.fromkeys(zip(depts, ftes)))。
? 输出效果示例
| Employee# | Firstname | Lastname | Type | Title | Department | Description | Starting | Ending | FTE |
|---|---|---|---|---|---|---|---|---|---|
| 1234 | Tom | Jones | CONP | TEACHER | School 2 | School 2 (0.5330 FTE), School 1 (0.1801 FTE), School 3 (0.1000 FTE) | 20240826 | 99999999 | 0.5330 |
? 扩展建议
-
时间字段优化:
Starting取最小值(最早入职)、Ending取最大值(最晚到期),可改用'Starting': 'min','Ending': 'max'; -
动态权重支持:若未来需按
Type优先级(如CONP > TEPT)而非FTE排序,可添加category类型并自定义排序顺序; -
空值鲁棒性:在
agg前加入df.dropna(subset=['Employee#', 'FTE'])防止分组异常。
该方案兼顾准确性、可读性与可维护性,适用于高频运行的HR数据同步任务,且易于适配SQL或Spark等其他引擎的等效逻辑。










