Python pandas实现20分钟粒度员工工作时段0/1状态标记的求助
实现方案
前置问题修正
你原示例代码存在两个会导致运行异常或结果不匹配的问题:
- 列名不匹配:构建DataFrame时写的列名是
started_work_hours,但后续转换时间格式时引用的是started_work_time,会触发KeyError报错 - 数据值不匹配:原数据里Davis的结束时间是21:30,和你给出的预期输出标记逻辑不符,这里对齐预期规则修正为10:30
完整可运行代码
import pandas as pd # 准备基础数据 id_list = ['Elton', 'Jose', 'Davis', 'Elton'] started_work_time = ['09:23', '10:32', '09:11', '10:45'] finished_work_time = ['10:10', '11:01', '10:30', '11:07'] df = pd.DataFrame({ 'id': id_list, 'started_work_time': started_work_time, 'finished_work_time': finished_work_time }) # 转换字符串时间为pandas可计算的datetime格式(补固定日期避免环境兼容问题) df['started_work_time'] = pd.to_datetime('2024-01-01 ' + df['started_work_time']) df['finished_work_time'] = pd.to_datetime('2024-01-01 ' + df['finished_work_time']) # 生成时间轴:9:00到11:00,每20分钟一个区间起始刻度 time_ticks = pd.date_range( start='2024-01-01 09:00', end='2024-01-01 11:00', freq='20min' ) # 提取刻度的时分格式作为最终结果的列名 # 注意:Windows系统将%-H:%M替换为%#H:%M col_names = [t.strftime('%-H:%M') for t in time_ticks] # 计算每个区间的结束时间(为下一个刻度的时间,最后一个区间结束为11:20) interval_ends = time_ticks[1:].append(pd.to_datetime('2024-01-01 11:20')) # 初始化结果表为全0值 result = pd.DataFrame(0, index=df.index, columns=col_names) # 逐段工作时间、逐个区间判断是否在岗 for idx, row in df.iterrows(): work_start = row['started_work_time'] work_end = row['finished_work_time'] for tick, col_name, int_end in zip(time_ticks, col_names, interval_ends): # 重叠判断规则:工作段和区间有交集即标记为1 if work_start <= int_end and work_end >= tick: result.loc[idx, col_name] = 1 # 拼接id列得到最终结果 final_df = pd.concat([df['id'], result], axis=1) print(final_df)
核心逻辑说明
- 区间划分规则:以9:00为起点,每20分钟划分为一个区间,依次为9:00-9:20、9:20-9:40、…、11:00-11:20,每个区间用其起始时间作为列名
- 在岗判断规则:只要工作时段和目标区间存在时间重叠就标记为1,重叠的判定条件为
工作开始时间 <= 区间结束时间且工作结束时间 >= 区间开始时间,和你举例的Jose的时间标记规则完全一致 - 代码采用逐行遍历的写法,没有复杂的pandas高级运算,刚接触Python也能顺着注释看懂每一步的作用
运行结果
执行代码后输出的结果和你给出的预期输出完全一致:
id 9:00 9:20 9:40 10:00 10:20 10:40 11:00 0 Elton 0 1 1 1 0 0 0 1 Jose 0 0 0 0 1 1 1 2 Davis 1 1 1 1 1 0 0 3 Elton 0 0 0 0 0 1 1
内容的提问来源于stack exchange,提问作者importm
相关产品推荐
相关产品推荐

