如何在Pandas中将时间序列转换为连续区间?
高效处理大规模时间序列的连续模式区间提取
问题描述
给定如下大规模时间序列数据:
mode timestamp 0 A 2021-06-29 00:00:00-04:00 1 A 2021-06-29 01:00:00-04:00 2 A 2021-06-29 02:00:00-04:00 3 A 2021-06-29 03:00:00-04:00 4 B 2021-06-29 04:00:00-04:00 5 B 2021-06-29 05:00:00-04:00 6 B 2021-06-29 06:00:00-04:00 7 B 2021-06-29 07:00:00-04:00 8 B 2021-06-29 08:00:00-04:00 9 B 2021-06-29 09:00:00-04:00 10 B 2021-06-29 10:00:00-04:00 11 A 2021-06-29 11:00:00-04:00 12 A 2021-06-29 12:00:00-04:00 13 A 2021-06-29 13:00:00-04:00 14 A 2021-06-29 14:00:00-04:00 15 A 2021-06-29 15:00:00-04:00 16 A 2021-06-29 16:00:00-04:00 17 A 2021-06-29 17:00:00-04:00 18 A 2021-06-29 18:00:00-04:00 19 A 2021-06-29 19:00:00-04:00 20 C 2021-06-29 20:00:00-04:00 21 C 2021-06-29 21:00:00-04:00 22 C 2021-06-29 22:00:00-04:00 23 C 2021-06-29 23:00:00-04:00 24 C 2021-06-29 00:00:00-04:00 25 C 2021-06-29 01:00:00-04:00 26 C 2021-06-29 02:00:00-04:00 27 C 2021-06-29 03:00:00-04:00
需要生成字典列表,每个字典对应连续相同mode的时间区间,包含mode、start_time和end_time,示例输出:
[ {"mode": "A", "start_time": "2021-06-29 00:00:00-04:00", "end_time": "2021-06-29 03:00:00-04:00"}, {"mode": "B", "start_time": "2021-06-29 04:00:00-04:00", "end_time": "2021-06-29 10:00:00-04:00"}, {"mode": "A", "start_time": "2021-06-29 11:00:00-04:00", "end_time": "2021-06-29 19:00:00-04:00"}, {"mode": "C", "start_time": "2021-06-29 20:00:00-04:00", "end_time": "2021-06-29 03:00:00-04:00"}, ]
由于数据量极大,循环遍历速度过慢,需高效实现方法。
高效实现方法:使用Pandas向量化处理
对于大规模时间序列,避免Python循环,直接用Pandas的分组和窗口函数处理,效率提升显著。
步骤1:加载数据到DataFrame
假设数据已为Pandas DataFrame格式,若为原始文本可通过pd.read_csv/pd.read_table加载:
import pandas as pd # 示例数据加载(实际根据数据源调整) data = pd.DataFrame({ 'mode': ['A']*4 + ['B']*7 + ['A']*9 + ['C']*8, 'timestamp': [ '2021-06-29 00:00:00-04:00', '2021-06-29 01:00:00-04:00', '2021-06-29 02:00:00-04:00', '2021-06-29 03:00:00-04:00', '2021-06-29 04:00:00-04:00', '2021-06-29 05:00:00-04:00', '2021-06-29 06:00:00-04:00', '2021-06-29 07:00:00-04:00', '2021-06-29 08:00:00-04:00', '2021-06-29 09:00:00-04:00', '2021-06-29 10:00:00-04:00', '2021-06-29 11:00:00-04:00', '2021-06-29 12:00:00-04:00', '2021-06-29 13:00:00-04:00', '2021-06-29 14:00:00-04:00', '2021-06-29 15:00:00-04:00', '2021-06-29 16:00:00-04:00', '2021-06-29 17:00:00-04:00', '2021-06-29 18:00:00-04:00', '2021-06-29 19:00:00-04:00', '2021-06-29 20:00:00-04:00', '2021-06-29 21:00:00-04:00', '2021-06-29 22:00:00-04:00', '2021-06-29 23:00:00-04:00', '2021-06-29 00:00:00-04:00', '2021-06-29 01:00:00-04:00', '2021-06-29 02:00:00-04:00', '2021-06-29 03:00:00-04:00' ] })
步骤2:生成连续相同mode的分组标识
通过shift()对比当前行与上一行的mode,生成分组标签:
# 标记mode变化的位置,生成分组ID data['group_id'] = (data['mode'] != data['mode'].shift()).cumsum()
步骤3:按分组聚合提取时间区间
对每个分组聚合,取mode的首个值、timestamp的首个值(起始时间)和最后一个值(结束时间):
result_df = data.groupby('group_id').agg( mode=('mode', 'first'), start_time=('timestamp', 'first'), end_time=('timestamp', 'last') ).reset_index(drop=True)
步骤4:转换为目标字典列表
用Pandas内置的to_dict('records')方法直接转换,高效生成所需格式:
result_list = result_df.to_dict('records')
运行后result_list即为符合要求的字典列表。
效率说明
Pandas的分组、聚合操作均为底层C实现的向量化运算,完全规避了Python循环的解释器开销,处理百万级以上数据时,速度比纯Python循环快数倍甚至数十倍。
内容的提问来源于stack exchange,提问作者Hakim
相关产品推荐
相关产品推荐

