如何基于Pandas DataFrame周期事件生成离散事件DataFrame
问题描述
我有如下结构的Pandas DataFrame:
duration,window_start,window_end,REPETITIONS 0 days 01:00:00,2023-12-31,2024-01-07,5 0 days 00:30:00,2021-10-28,2021-11-02,10 0 days 00:20:00,2022-12-24,2023-01-04,15 0 days 01:00:00,2023-06-15,2023-06-17,20
需要根据REPETITIONS、window_start和window_end,把这些周期事件转换成包含start和end时间的DataFrame,最终要生成5+10+15+20=50条离散事件记录。我想实现向量化转换,但一直找不到避免逐行循环的方法。
当前我的代码如下:
import pandas as pd import numpy as np periodic = pd.read_csv("events.csv",header=0,parse_dates=["start_date", "end_date"], index_col="id") start = periodic.apply(lambda row: np.linspace(row["window_start"].value, row["window_end"].value, row["REPETITIONS"]), axis=1) start = start.apply(lambda row: pd.to_datetime(row)) end = start + periodic["duration"]
这段代码生成了两个独立的Series:start和end,每个Series的每个id对应一个DateTimeIndex,示例如下:
start.head() 1,"DatetimeIndex([ '2021-12-31 00:00:00', '2022-01-01 00:01:00', '2021-01-01 00:02:00', '2021-01-01 00:03:00', end.head() 1,"DatetimeIndex([ '2021-12-31 01:00:00', '2022-01-01 00:02:00', '2021-01-01 00:03:00', '2021-01-01 00:04:00',
我的目标是得到如下格式的结果:
id, start, end 1,'2021-12-31 00:00:00','2021-12-31 00:01:00' 1,'2021-12-31 00:00:00','2021-12-31 00:01:00' 1,'2021-12-31 00:00:00','2021-12-31 00:01:00' ... 2,'2021-10-28 00:00:00','2021-10-28 00:30:00' 2,'2021-10-28 13:20:00','2021-10-28 13:50:00'
解决方案
1. 修正数据读取逻辑
你当前代码里的parse_dates参数写错了,原始数据的日期列是window_start和window_end,不是start_date/end_date,先修正读取代码:
import pandas as pd import numpy as np # 正确读取数据,解析对应日期列 periodic = pd.read_csv( "events.csv", header=0, parse_dates=["window_start", "window_end"], index_col=False ) # 生成自增id(如果原csv没有id列的话) periodic["id"] = periodic.index + 1
2. 向量化生成离散事件
用explode方法展开每个id对应的多个start时间,同时关联duration计算end时间,全程无需循环:
# 生成每个id对应的等间隔start时间序列 periodic["start"] = periodic.apply( lambda row: pd.date_range( start=row["window_start"], end=row["window_end"], periods=row["REPETITIONS"] ), axis=1 ) # 展开序列,生成每条离散记录 result = periodic.explode("start").reset_index(drop=True) # 计算end时间 result["end"] = result["start"] + pd.to_timedelta(result["duration"]) # 保留需要的列 result = result[["id", "start", "end"]]
关键说明
pd.date_range直接生成等间隔时间序列,比先转数值用np.linspace再转回datetime更高效explode是Pandas原生的向量化操作,会把单元格里的序列拆成单独行,自动关联原行的所有字段- 最终结果完全符合目标格式,且没有逐行循环,处理大数据集时性能优势明显
内容的提问来源于stack exchange,提问作者Cumulus
相关产品推荐
相关产品推荐

