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

使用Pandas计算员工班次间有效休息间隔时长

完整解决方案

原代码的核心问题是直接过滤了间隔不足15分钟的记录,且未按员工分组处理,也没覆盖“当日首行设为0”的规则。以下是符合所有要求的完整实现:

步骤1:数据预处理

先确保时间字段为datetime类型,并按员工和班次开始时间排序:

import pandas as pd

# 转换时间字段格式
df['start_time'] = pd.to_datetime(df['start_time'])
df['end_time'] = pd.to_datetime(df['end_time'])

# 按员工ID和班次开始时间排序,保证数据顺序正确
df = df.sort_values(by=['Worker_ID', 'start_time']).reset_index(drop=True)

步骤2:计算班次间隔与有效休息标识

按员工分组,计算两次班次的间隔,同时标记出需要重置为0的有效休息节点:

# 计算当前班次与上一班次的间隔时间(分钟)
df['minutes_between_shifts'] = df.groupby('Worker_ID').apply(
    lambda x: (x['start_time'] - x['end_time'].shift()).dt.total_seconds()/60
).reset_index(drop=True)

# 标记有效休息节点:当日首行 或 班次间隔≥15分钟
df['is_valid_break'] = (df['minutes_between_shifts'] >= 15) | (
    df.groupby(['Worker_ID', df['start_time'].dt.date])['start_time'].rank(method='first') == 1
)

步骤3:生成休息分组并计算累计时长

基于有效休息节点生成分组,再在每个分组内累计自上次休息后的时长:

# 按员工生成连续的休息分组ID,每遇到有效休息则分组ID递增
df['break_group'] = df.groupby('Worker_ID')['is_valid_break'].cumsum()

# 计算单个班次的时长(分钟)
df['shift_duration'] = (df['end_time'] - df['start_time']).dt.total_seconds()/60

# 累计每个休息组内的时长,shift后实现“自上次休息到当前班次开始的时长”
df['minutes_since_previous_break'] = df.groupby(['Worker_ID', 'break_group'])['shift_duration'].cumsum().shift(fill_value=0)

步骤4:重置有效休息节点的字段值

对标记为有效休息的记录,将minutes_since_previous_break设为0:

df.loc[df['is_valid_break'], 'minutes_since_previous_break'] = 0

完整代码整合

import pandas as pd

def compute_minutes_since_break(df):
    # 预处理时间字段
    df['start_time'] = pd.to_datetime(df['start_time'])
    df['end_time'] = pd.to_datetime(df['end_time'])
    
    # 排序
    df = df.sort_values(by=['Worker_ID', 'start_time']).reset_index(drop=True)
    
    # 计算班次间隔
    df['minutes_between_shifts'] = df.groupby('Worker_ID').apply(
        lambda x: (x['start_time'] - x['end_time'].shift()).dt.total_seconds()/60
    ).reset_index(drop=True)
    
    # 标记有效休息节点
    df['is_valid_break'] = (df['minutes_between_shifts'] >= 15) | (
        df.groupby(['Worker_ID', df['start_time'].dt.date])['start_time'].rank(method='first') == 1
    )
    
    # 生成休息分组
    df['break_group'] = df.groupby('Worker_ID')['is_valid_break'].cumsum()
    
    # 计算班次时长和累计值
    df['shift_duration'] = (df['end_time'] - df['start_time']).dt.total_seconds()/60
    df['minutes_since_previous_break'] = df.groupby(['Worker_ID', 'break_group'])['shift_duration'].cumsum().shift(fill_value=0)
    
    # 重置有效休息后的字段值
    df.loc[df['is_valid_break'], 'minutes_since_previous_break'] = 0
    
    # 清理中间字段(可选)
    df = df.drop(columns=['minutes_between_shifts', 'is_valid_break', 'break_group', 'shift_duration'])
    
    return df

# 使用示例
# df = pd.read_csv('your_shift_records.csv')
# df = compute_minutes_since_break(df)

关键逻辑说明

  • 分组隔离:所有计算按Worker_ID分组,避免不同员工的数据相互干扰
  • 当日首行识别:通过start_time.dt.date结合组内排名,精准定位每个员工当日的第一条班次记录
  • 有效休息覆盖:同时处理“间隔≥15分钟”和“当日首行”两种需要重置为0的场景
  • 累计时长计算:利用分组累加实现跨班次的时长统计,确保间隔不足15分钟时持续累加时长

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 22:57:49