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

按时间规则调整DataFrame行:规整员工打卡时间至对应列

员工打卡时间规整实现方案

现有代码与初始输出

现有用于生成打卡日志的Pandas代码:

dic = {'Employee ID':emp_id, 'Log Date':emp_logdate, 'Log Time':emp_logtime}
df = pd.DataFrame(dic).groupby(['Employee ID','Log Date']).agg({'Log Date':'first', 'Log Time': lambda x: ', '.join(x.unique())})['Log Time'].astype(str).str.split(', ', expand=True).reset_index()

运行后得到的初始DataFrame(仅展示时间列):

'7:20',  '11:50', '12:49', '17:20'
'7:02',  '11:36', '12:59'   
'11:33', '12:40', '17:06'   
'11:38'

需求说明

需要将零散的打卡时间按规则归类到指定列:

  • 7点左右的时间 → AM In列
  • 11点左右的时间 → AM Out列
  • 12点左右的时间 → PM In列
  • 17点左右的时间 → PM Out列
    缺失时段的位置填充空值,最终得到规整的结构化数据。

实现方案

步骤1:定义时间分类逻辑

先通过提取时间的小时部分,为每个目标列设置匹配范围:

import pandas as pd

def classify_time(time_str):
    if pd.isna(time_str):
        return None
    # 转换为时间格式并提取小时
    hour = pd.to_datetime(time_str, format='%H:%M').hour
    if 6 <= hour <= 8:    # 匹配7点左右的打卡
        return 'AM In'
    elif 10 <= hour <= 12: # 匹配11点左右的打卡
        return 'AM Out'
    elif 12 <= hour <= 13: # 匹配12点左右的打卡
        return 'PM In'
    elif 16 <= hour <= 18: # 匹配17点左右的打卡
        return 'PM Out'
    else:
        return None

步骤2:逐行处理重组数据(适合小数据量)

保留原数据的Employee ID和Log Date列,遍历每行时间值并按规则填充到目标列:

# 获取所有时间列(排除前两列的ID和日期)
time_cols = df.columns[2:]
# 初始化结果DataFrame,添加目标列并设为空值
target_cols = ['AM In', 'AM Out', 'PM In', 'PM Out']
result_df = df[['Employee ID', 'Log Date']].copy()
for col in target_cols:
    result_df[col] = ''

# 遍历每行处理时间分类
for idx, row in df.iterrows():
    for col in time_cols:
        time_val = row[col]
        if pd.notna(time_val):
            col_type = classify_time(time_val)
            # 仅填充空的目标列(避免同一时段多个打卡覆盖)
            if col_type and result_df.at[idx, col_type] == '':
                result_df.at[idx, col_type] = time_val

替代方案:向量化处理(适合大数据量)

用melt和pivot实现批量转换,效率更高:

# 将宽格式时间列转为长格式,过滤空值
melted = df.melt(id_vars=['Employee ID', 'Log Date'], value_name='Log Time').dropna(subset=['Log Time'])
# 为每个时间标记所属列类型
melted['Col_Type'] = melted['Log Time'].apply(classify_time)
# 去重:同一员工同一日期同一时段仅保留第一个打卡
melted = melted.drop_duplicates(subset=['Employee ID', 'Log Date', 'Col_Type'])
# 转回宽格式,补全目标列并填充空值
result_df = melted.pivot(index=['Employee ID', 'Log Date'], columns='Col_Type', values='Log Time').reset_index()
result_df = result_df.reindex(columns=['Employee ID', 'Log Date'] + target_cols).fillna('')

最终效果

运行后得到的规整数据示例:

Employee ID  Log Date AM In AM Out PM In PM Out
0            2024-05-01  7:20  11:50 12:49 17:20
1            2024-05-01  7:02  11:36 12:59       
2            2024-05-02        11:33 12:40 17:06
3            2024-05-02        11:38            

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 19:45:34