如何用Pandas创建isRunning列,处理无END标记的Session任务状态
在Pandas DataFrame中创建isRunning列的解决方案
问题分析
需要根据Task列的START/END状态标记isRunning列,同时处理特殊场景:如果某个Session仅存在START值而无END值,则该Session从START出现开始到结束的所有行,isRunning都标记为True。
示例数据
先构造符合需求的测试数据:
import pandas as pd data = { 'Session': [1,1,1,2,2,2,3,3], 'Task': ['START', 'PROCESS', 'END', 'START', 'END', 'IDLE', 'START', 'PROCESS'], 'Timestamp': ['2024-01-01 10:00', '2024-01-01 10:05', '2024-01-01 10:10', '2024-01-01 11:00', '2024-01-01 11:05', '2024-01-01 11:10', '2024-01-01 12:00', '2024-01-01 12:05'] } df = pd.DataFrame(data)
解决方案1:分组遍历实现(直观易理解)
通过按Session分组,遍历每个分组内的Task状态,同时判断该Session是否存在END记录:
def assign_is_running(group): # 检查当前Session是否包含END任务 has_end = 'END' in group['Task'].values running = False is_running_list = [] for task in group['Task']: if task == 'START': running = True elif task == 'END': running = False # 若Session无END记录,一旦开启running就保持True if not has_end and running: running = True is_running_list.append(running) group['isRunning'] = is_running_list return group # 应用分组处理 df = df.groupby('Session', group_keys=False).apply(assign_is_running)
运行后结果:
Session Task Timestamp isRunning 0 1 START 2024-01-01 10:00 True 1 1 PROCESS 2024-01-01 10:05 True 2 1 END 2024-01-01 10:10 False 3 2 START 2024-01-01 11:00 True 4 2 END 2024-01-01 11:05 False 5 2 IDLE 2024-01-01 11:10 False 6 3 START 2024-01-01 12:00 True 7 3 PROCESS 2024-01-01 12:05 True
解决方案2:向量化实现(高效处理大数据)
避免循环,利用Pandas的累积求和功能实现,适合数据量较大的场景:
# 初始化isRunning列 df['isRunning'] = False # 标记START和END的位置 df['start_flag'] = df['Task'] == 'START' df['end_flag'] = df['Task'] == 'END' # 计算每个Session内START与END的累积次数差,判断是否处于运行状态 df['isRunning'] = df.groupby('Session')['start_flag'].cumsum() > df.groupby('Session')['end_flag'].cumsum() # 处理无END记录的Session:将该Session第一个START之后的所有行设为True no_end_sessions = df.groupby('Session').filter(lambda x: 'END' not in x['Task'])['Session'].unique() for session in no_end_sessions: first_start_idx = df[(df['Session'] == session) & (df['Task'] == 'START')].index[0] df.loc[(df['Session'] == session) & (df.index >= first_start_idx), 'isRunning'] = True # 清理临时列 df.drop(['start_flag', 'end_flag'], axis=1, inplace=True)
关键逻辑说明
- 分组处理:所有操作基于
Session分组,确保每个Session的状态独立计算,互不干扰 - END存在性判断:针对无
END的Session,强制保持START触发后的运行状态为True - 状态流转:正常场景下,
START触发运行状态开启,END触发关闭;中间非START/END的Task保持当前状态
内容的提问来源于stack exchange,提问作者user20400952
相关产品推荐
相关产品推荐

