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

如何基于员工班次起止时间生成15分钟粒度的在岗人数统计数组?

问题:基于员工班次的15分钟粒度在岗人数统计

技术需求

如何基于员工班次的Start_Time和End_Time,生成按日期及15分钟增量统计在岗人数的数组或DataFrame?

输入数据

员工排班数据包含Employee_ID、Start_Time、End_Time字段,具体数据如下:

员工ID开始时间结束时间
1202303150100000000000000202303150245000000000000
2202303150015000000000000202303150700000000000000
3202303150230000000000000202303160100000000000000

期望输出

按日期+15分钟粒度统计在岗人数的DataFrame,支持跨天班次延续统计,示例如下:

日期1212:1512:3012:4500:150:300:4511:15...24
2023/3/150111222222...1
2023/3/161111000000...0

当前进展与问题

已实现小时粒度统计,但无法准确处理非整点起止的班次(例如2:45开始的班次被错误记录为2:00开始)。现有实现代码存在逻辑缺陷,需要优化为15分钟粒度的精准统计。

解决方案

以下是优化后的代码,通过时间序列展开和区间匹配实现精准统计:

步骤1:数据预处理(解析时间字段)

首先将原始的字符串格式时间转换为datetime类型,方便后续时间操作:

import pandas as pd
import numpy as np

# 构造示例数据
data = {
    'Employee_ID': [1, 2, 3],
    'Start_Time': ['202303150100000000000000', '202303150015000000000000', '202303150230000000000000'],
    'End_Time': ['202303150245000000000000', '202303150700000000000000', '202303160100000000000000']
}
df = pd.DataFrame(data)

# 解析时间字符串为datetime类型
df['Start_Time'] = pd.to_datetime(df['Start_Time'], format='%Y%m%d%H%M%S%f')
df['End_Time'] = pd.to_datetime(df['End_Time'], format='%Y%m%d%H%M%S%f')

步骤2:生成15分钟粒度的时间序列

覆盖所有班次涉及的日期范围,生成每15分钟一个间隔的时间点:

# 获取所有班次的最小开始时间和最大结束时间,确定时间范围
min_time = df['Start_Time'].min().floor('D')  # 从最早日期的0点开始
max_time = df['End_Time'].max().ceil('D')     # 到最晚日期的次日0点结束

# 生成15分钟间隔的时间序列
time_intervals = pd.date_range(start=min_time, end=max_time, freq='15min')

# 将时间序列拆分为日期和时段列
time_df = pd.DataFrame({'timestamp': time_intervals})
time_df['Date'] = time_df['timestamp'].dt.date
time_df['Time_Slot'] = time_df['timestamp'].dt.strftime('%H:%M')
# 处理00:00显示为24:00,匹配期望输出格式
time_df['Time_Slot'] = time_df['Time_Slot'].replace('00:00', '24:00')

步骤3:匹配每个时段的在岗员工数

通过交叉连接和区间判断,统计每个时段的在岗人数:

# 交叉连接员工表和时段表,生成所有可能的员工-时段组合
cross_df = df.merge(time_df, how='cross')

# 判断员工在该时段是否在岗:时段的起始时间在员工班次的[Start_Time, End_Time)区间内
cross_df['On_Duty'] = (cross_df['timestamp'] >= cross_df['Start_Time']) & (cross_df['timestamp'] < cross_df['End_Time'])

# 按日期和时段分组,统计在岗人数
result_df = cross_df.groupby(['Date', 'Time_Slot'])['On_Duty'].sum().unstack(fill_value=0)

# 调整时段顺序,匹配期望输出的排列逻辑
slot_order = [
    '12:00', '12:15', '12:30', '12:45',
    '00:15', '00:30', '00:45',
    '01:00', '01:15', '01:30', '01:45',
    '02:00', '02:15', '02:30', '02:45',
    '03:00', '03:15', '03:30', '03:45',
    '04:00', '04:15', '04:30', '04:45',
    '05:00', '05:15', '05:30', '05:45',
    '06:00', '06:15', '06:30', '06:45',
    '07:00', '07:15', '07:30', '07:45',
    '08:00', '08:15', '08:30', '08:45',
    '09:00', '09:15', '09:30', '09:45',
    '10:00', '10:15', '10:30', '10:45',
    '11:00', '11:15', '11:30', '11:45',
    '24:00'
]
# 调整列顺序,补充缺失的时段(如果有)
result_df = result_df.reindex(columns=slot_order, fill_value=0)

# 重置索引,将Date作为列
result_df = result_df.reset_index()
# 格式化日期显示为YYYY/M/D格式
result_df['Date'] = result_df['Date'].apply(lambda x: x.strftime('%Y/%m/%d'))

最终输出效果

运行上述代码后,result_df即为符合需求的DataFrame,包含日期列和每15分钟的在岗人数统计,支持跨天班次的正确统计。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 19:29:44