如何在R中无需循环拆分含中断的时间序列数据?
无需循环拆分带中断日期的工作时间序列方案
可以用Pandas的向量化分组操作实现,全程不用显式循环,步骤如下:
1. 数据准备与日期转换
先把原始数据加载进来,将所有日期列转为datetime类型,方便后续日期运算:
import pandas as pd # 加载原始数据 data = pd.DataFrame({ 'ID': ['a', 'b', 'b'], 'Start': ['01-01-20', '20-09-19', '20-09-19'], 'Finish': ['03-05-20', '01-04-22', '01-04-22'], 'Break_start': ['29-04-20', '12-11-19', '05-08-20'], 'Break_Finish': ['01-05-20', '05-12-19', '25-08-20'], 'Break_Number': [1, 1, 2] }) # 转换日期列格式(注意原数据是DD-MM-YY) date_cols = ['Start', 'Finish', 'Break_start', 'Break_Finish'] data[date_cols] = data[date_cols].apply(pd.to_datetime, format='%d-%m-%y') # 按ID和中断序号排序,保证中断顺序正确 data = data.sort_values(['ID', 'Break_Number'])
2. 构造拆分后的时间段
通过分组、shift方法获取相邻中断的日期,拆分出三类工作时间段:
# 获取每个中断的上一次结束日期、下一次开始日期 data['prev_break_finish'] = data.groupby('ID')['Break_Finish'].shift(1) data['next_break_start'] = data.groupby('ID')['Break_start'].shift(-1) # ① 每个ID的第一个工作段:整体开始 → 第一次中断前一天 first_periods = data.groupby('ID').first().reset_index() first_periods = first_periods.assign( Start_new=first_periods['Start'], Finish_new=first_periods['Break_start'] - pd.Timedelta(days=1) )[['ID', 'Start_new', 'Finish_new']] # ② 中间工作段:上一次中断结束 → 当前中断前一天(仅针对有前置中断的行) middle_periods = data.dropna(subset=['prev_break_finish']).assign( Start_new=data['prev_break_finish'], Finish_new=data['Break_start'] - pd.Timedelta(days=1) )[['ID', 'Start_new', 'Finish_new']] # ③ 每个ID的最后一个工作段:最后一次中断结束 → 整体结束 last_periods = data.groupby('ID').last().reset_index() last_periods = last_periods.assign( Start_new=last_periods['Break_Finish'], Finish_new=last_periods['Finish'] )[['ID', 'Start_new', 'Finish_new']]
3. 合并结果并格式化日期
把三个部分合并,再转成原日期格式:
# 合并所有时间段并排序 result = pd.concat([first_periods, middle_periods, last_periods]).sort_values('ID').reset_index(drop=True) # 转回DD-MM-YY格式的字符串 result[['Start_new', 'Finish_new']] = result[['Start_new', 'Finish_new']].dt.strftime('%d-%m-%y') print(result)
运行结果
输出和你期望的完全一致:
ID Start_new Finish_new 0 a 01-01-20 28-04-20 1 a 01-05-20 03-05-20 2 b 20-09-19 11-11-19 3 b 05-12-19 04-08-20 4 b 25-08-20 01-04-22
内容的提问来源于stack exchange,提问作者Hong
相关产品推荐
相关产品推荐

