如何高效在Pandas中为打卡记录匹配对应排班Shift ID?
Pandas高效匹配排班表与打卡记录的向量化实现
核心方案
Pandas不支持直接带时间范围条件的merge,但可以通过先等值关联核心维度,再过滤时间范围的向量化操作替代遍历/apply,完全适配百万级数据集的性能需求。
分步实现
1. 数据预处理
先统一字段名、转换时间格式为可比较的datetime类型,避免关联时的字段不匹配问题:
# 处理排班表:拼接日期与时段,生成完整的排班起止时间 schedule['shift_start'] = pd.to_datetime(schedule['Day'] + ' ' + schedule['Start']) schedule['shift_end'] = pd.to_datetime(schedule['Day'] + ' ' + schedule['End']) # 处理打卡表:拼接日期与打卡时间,统一关联字段名 punches['punch_datetime'] = pd.to_datetime(punches['Punch Date'] + ' ' + punches['Punch time']) punches = punches.rename(columns={'Worker Id': 'Worker ID', 'Punch Date': 'Day'})
2. 等值关联+时间过滤
先基于Store ID、Worker ID、Day做左关联(保留所有打卡记录),再筛选出打卡时间落在对应排班时段内的记录:
# 基于核心维度做等值关联 merged = pd.merge(punches, schedule, on=['Store ID', 'Worker ID', 'Day'], how='left') # 向量化过滤:匹配打卡时间在排班时段内的记录 result = merged[(merged['punch_datetime'] >= merged['shift_start']) & (merged['punch_datetime'] <= merged['shift_end'])]
3. 百万级数据性能优化
- 给关联字段建立索引,大幅提升merge速度:
schedule = schedule.set_index(['Store ID', 'Worker ID', 'Day']) punches = punches.set_index(['Store ID', 'Worker ID', 'Day']) merged = punches.join(schedule, how='left').reset_index()
- 若内存不足,可改用
dask.dataframe分块处理,逻辑与Pandas完全一致,支持更大规模数据集。
关键说明
- 针对员工单日多班次的场景,上述方法会自动匹配打卡时间对应的班次,正确关联
Shift ID - 无匹配排班的打卡记录,
Shift ID会显示为NaN,可根据业务需求过滤或标记
内容的提问来源于stack exchange,提问作者Samuel Crockford
相关产品推荐
相关产品推荐

