如何在Pandas中按条件计算员工岗位及岗责累计时长?
解决员工岗位累计时长计算问题(不计角色)
需求说明
需要结合员工排班数据df_aux和事件数据df_main,计算两个核心指标:
- 事件发生时,员工在当前岗位的累计时长(不计角色)
- 事件发生时,员工在当前岗位及角色的累计时长(已实现)
数据示例
先给出原始数据,后续需将时间列转为datetime类型才能进行时间运算:
import pandas as pd # 排班数据 df_aux = pd.DataFrame({'Worker' : ['Alice','Alice','Alice','Alice','Alice', 'Bob','Bob','Bob'], 'Shift_start' : ['2022-01-01 10:00:00', '2022-01-01 10:30:00', '2022-01-01 11:45:00', '2022-01-01 12:45:00', '2022-01-01 13:15:00', '2022-01-01 10:30:00', '2022-01-01 12:00:00', '2022-01-01 13:15:00'], 'Shift_end' : ['2022-01-01 10:15:00', '2022-01-01 11:45:00', '2022-01-01 12:30:00', '2022-01-01 13:15:00', '2022-01-01 14:00:00', '2022-01-01 11:30:00', '2022-01-01 13:10:00', '2022-01-01 14:30:00'], 'Position' : [1, 1, 2, 2, 2, 1, 2, 3], 'Role' : ['A', 'B', 'B', 'A', 'B', 'A', 'B', 'A']}) # 事件数据 df_main = pd.DataFrame({'Event_time' : ['2022-01-01 11:05:00', '2022-01-01 12:35:00', '2022-01-01 13:25:00'] , 'Position' : [1, 2, 2]})
第一步:数据预处理(转换时间列)
先把所有时间相关列转为datetime类型,这是时间运算的基础:
# 转换排班数据的时间列 df_aux['Shift_start'] = pd.to_datetime(df_aux['Shift_start']) df_aux['Shift_end'] = pd.to_datetime(df_aux['Shift_end']) # 转换事件数据的时间列 df_main['Event_time'] = pd.to_datetime(df_main['Event_time'])
第二步:完成已实现的「岗位+角色累计时长」计算
优化原始代码,确保逻辑正确:
# 合并事件与排班数据,按岗位匹配 df_full = df_main.merge(df_aux, on='Position') # 筛选出事件发生时正在在岗的员工(事件时间在班次起止之间) df_full = df_full[(df_full['Event_time'] > df_full['Shift_start']) & (df_full['Event_time'] < df_full['Shift_end'])] # 计算当前岗位+角色的累计时长(当前班次已进行的时间) df_full['Time_in_position_role'] = df_full['Event_time'] - df_full['Shift_start']
第三步:计算「当前岗位累计时长(不计角色)」
核心思路:对每个在岗员工,统计其在事件时间前所有同岗位班次的总时长,再加上当前班次已进行的时间:
# 定义函数,计算单个员工在指定岗位、指定时间前的累计岗位时长 def calculate_total_position_time(row): worker = row['Worker'] position = row['Position'] event_time = row['Event_time'] # 筛选该员工所有同岗位的历史班次(班次结束时间 <= 事件时间) historical_shifts = df_aux[(df_aux['Worker'] == worker) & (df_aux['Position'] == position) & (df_aux['Shift_end'] <= event_time)] # 计算历史班次的总时长 total_historical = historical_shifts['Shift_end'].sub(historical_shifts['Shift_start']).sum() # 加上当前班次已进行的时间,得到累计岗位时长 return total_historical + row['Time_in_position_role'] # 应用函数计算Time_in_position df_full['Time_in_position'] = df_full.apply(calculate_total_position_time, axis=1)
最终结果展示
运行上述代码后,df_full会包含两个目标字段:
Time_in_position_role:当前岗位+角色的累计时长Time_in_position:当前岗位的累计时长(不计角色)
比如第一个事件(2022-01-01 11:05:00,岗位1)对应的Alice,她的Time_in_position是之前10:00-10:15的15分钟,加上当前10:30到11:05的35分钟,总计50分钟。
内容的提问来源于stack exchange,提问作者datadatadata
相关产品推荐
相关产品推荐

