将带起止时间的Pandas事件DataFrame转换为规则时间序列
把事件数据集转成10分钟间隔的规则时间序列
我来帮你搞定这个需求,咱们一步步来处理——毕竟你的数据里还有些时间顺序写反的情况,得先修正才行:
第一步:合并数据+修正时间异常
首先把两组数据合并,然后把时间列转成datetime格式,重点处理那些start比end晚的条目——这类情况大概率是跨天(比如当天23点开始,次日12点结束),所以咱们把这类条目的end日期加一天就行:
import pandas as pd # 加载第一组数据 df1 = pd.DataFrame({ 'start': ['2015-01-05 12:21:00', '2015-01-05 18:01:23', '2015-01-05 23:11:01'], 'end': ['2015-01-05 13:18:45', '2015-01-05 21:03:51', '2015-01-05 12:08:11'], 'value': [3, 4, 5] }) # 加载第二组表格数据 df2 = pd.DataFrame({ 'end': ['2015-01-07 11:18:45', '2015-01-07 12:08:11', '2015-01-07 17:03:51'], 'start': ['2015-01-07 11:35:00', '2015-01-07 23:11:01', '2015-01-07 18:01:23'], 'value': [3, 5, 4] }) # 把两组数据合并成一个 df = pd.concat([df1, df2], ignore_index=True) # 把start和end转成datetime类型,方便后续处理 df['start'] = pd.to_datetime(df['start']) df['end'] = pd.to_datetime(df['end']) # 修正那些start比end晚的条目:给end加一天 wrong_order_mask = df['start'] > df['end'] df.loc[wrong_order_mask, 'end'] += pd.Timedelta(days=1)
第二步:生成10分钟间隔的时间轴
接下来咱们要创建一个完整的10分钟间隔序列,覆盖从数据里最早的开始时间到最晚的结束时间,确保每个间隔都是规整的10分钟:
# 找到整个数据集的时间边界 earliest_time = df['start'].min() latest_time = df['end'].max() # 生成10分钟间隔的时间序列,把起始时间向下取整到最近的10分钟,结束时间向上取整 time_intervals = pd.date_range( start=earliest_time.floor('10T'), end=latest_time.ceil('10T'), freq='10T' ) # 把时间序列转成带间隔起止的DataFrame interval_df = pd.DataFrame({ 'interval_start': time_intervals, 'interval_end': time_intervals + pd.Timedelta(minutes=10) })
第三步:匹配事件和时间间隔,计算每个间隔的累计value
现在要判断每个事件的时间范围覆盖了哪些10分钟间隔,然后把对应的value累加到这些间隔里。咱们用交叉连接+筛选重叠的方式来实现:
# 给原数据和间隔数据加临时索引,方便后续匹配 df['event_id'] = df.index interval_df['interval_id'] = interval_df.index # 做交叉连接,把每个事件和所有时间间隔配对 cross_matched = df.merge(interval_df, how='cross') # 筛选出事件和间隔重叠的记录:事件开始时间 < 间隔结束时间,且事件结束时间 > 间隔开始时间 overlap_mask = (cross_matched['start'] < cross_matched['interval_end']) & (cross_matched['end'] > cross_matched['interval_start']) overlapped_records = cross_matched[overlap_mask] # 按时间间隔分组,把每个间隔里的value加起来 final_result = overlapped_records.groupby(['interval_start', 'interval_end'])['value'].sum().reset_index() # 如果你想显示所有间隔(包括没有事件覆盖、value为0的),就用左连接填充0 full_result = interval_df.merge(final_result, on=['interval_start', 'interval_end'], how='left').fillna({'value': 0})
最后说下结果
full_result就是你要的10分钟间隔规则序列啦!其中interval_start是每个间隔的起始时间,value是这个间隔内所有覆盖事件的value总和。要是某个10分钟里没有任何事件,value就会显示0。
举个例子,第一组数据里那条start是2015-01-05 23:11:01的记录,修正后end变成2015-01-06 12:08:11,它会覆盖从2015-01-05 23:10到2015-01-06 12:10的所有10分钟间隔,每个间隔都会加上5。
内容的提问来源于stack exchange,提问作者fparaggio
相关产品推荐
相关产品推荐

