如何高效实现Pandas带重叠的Time Indexed DataFrame重采样?
高效实现带重叠的时间序列重采样(Pandas)
问题背景
你需要对带时间索引的DataFrame执行带重叠的重采样:用10秒的窗口,每次滑动2秒(即窗口重叠8秒),最终得到窗口结束于整10秒时刻的聚合结果。之前用分组方法处理大数据集时速度太慢,想找更高效的方案。
先看你的示例数据:
>>> df data date 2018-03-09 12:00:00 1 2018-03-09 12:00:01 1 2018-03-09 12:00:02 1 2018-03-09 12:00:03 1 2018-03-09 12:00:04 1 2018-03-09 12:00:05 1 2018-03-09 12:00:06 1 2018-03-09 12:00:07 1 2018-03-09 12:00:08 1 2018-03-09 12:00:09 1 2018-03-09 12:00:10 1 2018-03-09 12:00:11 2 2018-03-09 12:00:12 2 2018-03-09 12:00:13 2 2018-03-09 12:00:14 2 2018-03-09 12:00:15 2 2018-03-09 12:00:16 2 2018-03-09 12:00:17 2 2018-03-09 12:00:18 2 2018-03-09 12:00:19 2 2018-03-09 12:00:20 2 2018-03-09 12:00:21 3 2018-03-09 12:00:22 3 2018-03-09 12:00:23 3 2018-03-09 12:00:24 3 2018-03-09 12:00:25 3 2018-03-09 12:00:26 3 2018-03-09 12:00:27 3 2018-03-09 12:00:28 3 2018-03-09 12:00:29 3 2018-03-09 12:00:30 3
期望的重采样结果:
>>> result data date 2018-03-09 12:00:10 14 2018-03-09 12:00:20 28 2018-03-09 12:00:30 34
高效解决方案
别用自定义分组了,Pandas内置的rolling方法专门解决这类带滑动窗口的时间序列聚合问题,底层是优化过的Cython实现,处理大数据集的速度比手动分组快几个量级。
实现代码
# 1. 定义10秒的滑动窗口,步长设为2秒(每2秒滑动一次) rolling_obj = df.rolling(window='10s', step='2s') # 2. 对每个窗口内的data列求和 rolling_sum = rolling_obj.sum() # 3. 筛选出窗口结束时间为整10秒的行(匹配你的需求格式) result = rolling_sum[rolling_sum.index.second % 10 == 0]
关键说明
window='10s'直接指定窗口长度为10秒,Pandas会自动处理时间索引的对齐;step='2s'设置窗口滑动步长为2秒,实现重叠效果(窗口重叠部分为10-2=8秒);- 最后筛选整10秒的索引,是为了和你给出的示例结果格式一致——如果你需要所有滑动窗口的结果,去掉这一步即可。
备选方案(针对固定时间点)
如果你的需求是仅在特定时间点(比如整10秒、20秒)计算前10秒的聚合,也可以用下面的方法,逻辑更直观,适合小数据集:
import pandas as pd # 生成目标时间点 target_times = pd.date_range(start='2018-03-09 12:00:10', end='2018-03-09 12:00:30', freq='10s') # 计算每个时间点前10秒的求和 result = pd.DataFrame( data=[df.loc[t - pd.Timedelta('10s'):t, 'data'].sum() for t in target_times], index=target_times, columns=['data'] )
不过这个方法在数据量极大时,效率不如rolling,因为它需要循环遍历每个时间点,而rolling是向量化运算。
内容的提问来源于stack exchange,提问作者user1554681
相关产品推荐
相关产品推荐

