如何按特定规则计算时间区间序列中1小时间隔的总次数?
问题描述
给定一个已排序的时间区间DataFrame(数据及初始化代码如下),需要按以下规则统计1小时间隔的总操作次数:
- 从第一个区间的
start_time开始,每次添加1小时; - 若结果时间在DataFrame的某个区间内,则以该结果时间继续添加1小时;
- 若结果时间不在任何区间内(处于两个区间之间),则取下一个区间的
start_time继续添加1小时; - 当结果时间大于等于最后一个区间的
end_time时停止,统计添加1小时的总次数。
初始化DataFrame的代码:
import pandas as pd from io import StringIO s="""start_time,end_time 2022-01-01 12:30:00,2022-01-01 12:45:00 2022-01-01 13:05:00,2022-01-01 13:50:00 2022-01-01 14:00:00,2022-01-01 14:20:00 2022-01-01 16:00:00,2022-01-01 16:45:00 2022-01-01 17:20:00,2022-01-01 17:35:00 2022-01-01 17:45:00,2022-01-01 18:30:00 2022-01-01 19:00:00,2022-01-01 19:25:00""" df = pd.read_csv(StringIO(s), sep=",") df.start_time = pd.to_datetime(df.start_time) df.end_time = pd.to_datetime(df.end_time)
示例计算过程:
- 12:30 + 1H → 13:30(在13:05-13:50区间内,继续从13:30添加)
- 13:30 +1H →14:30(不在任何区间,取下一个区间的16:00)
3.16:00+1H→17:00(不在任何区间,取下一个区间的17:20)
4.17:20+1H→18:20(在17:45-18:30区间内,继续从18:20添加)
5.18:20+1H→19:20(在最后一个区间内,继续添加)
6.19:20+1H→20:20(大于最后一个区间的end_time,停止)
最终输出为6;若最后一个区间的end_time为19:20:00,则输出为5。
解决方案
可以通过循环结合Pandas的searchsorted方法实现需求,核心逻辑是每次计算下一个时间点,判断其是否处于某个区间内,若不在则定位到后续最近的区间开始时间,直到满足停止条件。
代码实现
import pandas as pd from io import StringIO # 初始化DataFrame s="""start_time,end_time 2022-01-01 12:30:00,2022-01-01 12:45:00 2022-01-01 13:05:00,2022-01-01 13:50:00 2022-01-01 14:00:00,2022-01-01 14:20:00 2022-01-01 16:00:00,2022-01-01 16:45:00 2022-01-01 17:20:00,2022-01-01 17:35:00 2022-01-01 17:45:00,2022-01-01 18:30:00 2022-01-01 19:00:00,2022-01-01 19:25:00""" df = pd.read_csv(StringIO(s), sep=",") df.start_time = pd.to_datetime(df.start_time) df.end_time = pd.to_datetime(df.end_time) # 提取关键数组,简化后续操作 starts = df.start_time.values ends = df.end_time.values last_end = ends[-1] current_time = starts[0] count = 0 while True: # 执行加1小时操作,计数加1 next_time = current_time + pd.Timedelta(hours=1) count += 1 # 检查是否满足停止条件 if next_time >= last_end: break # 用searchsorted定位next_time对应的区间位置 idx = starts.searchsorted(next_time, side='left') # 情况1:next_time落在某个已存在的区间内 if idx > 0 and next_time <= ends[idx-1]: current_time = next_time # 情况2:next_time处于区间间隙,取下一个区间的开始时间 else: current_time = starts[idx] print(count)
逻辑解释
- 初始化变量:提取
start_time和end_time的数组,获取最后一个区间的结束时间last_end,将初始时间设为第一个区间的开始时间,计数初始化为0。 - 循环处理:
- 每次给当前时间加1小时,同时计数加1;
- 若加时后的时间大于等于
last_end,直接终止循环; - 使用
searchsorted找到第一个大于next_time的start_time索引idx:- 若
idx>0且next_time小于等于前一个区间的结束时间,说明next_time在某个区间内,将当前时间更新为next_time; - 否则说明
next_time处于区间间隙,将当前时间更新为下一个区间的开始时间starts[idx]。
- 若
- 输出结果:循环结束后,输出总操作次数。
运行上述代码可得到示例结果6;若修改最后一个区间的end_time为19:20:00,运行后会得到结果5,符合需求。
内容的提问来源于stack exchange,提问作者theodosis
相关产品推荐
相关产品推荐

