Pandas:为每行统计时间戳前后窗口内的行数
高效统计每行时间戳前后指定窗口内的行数
逐行遍历的方法在数据量小的时候凑合用,但数据一旦上万甚至几十万,速度会直接崩掉——毕竟O(n²)的时间复杂度真的扛不住。其实利用Pandas和NumPy的内置工具,我们可以把效率提升几个数量级,核心就是用二分查找替代逐行筛选。
核心思路
因为你的DataFrame已经按timestamp排序了,我们可以用searchsorted方法(底层是二分查找,时间复杂度O(log n))快速定位每个时间戳窗口的边界位置,然后通过索引差直接计算行数,完全不需要逐行遍历。
具体实现步骤
- 确保时间戳是datetime类型:先把字符串格式的时间转换成Pandas的datetime对象,方便后续时间运算。
- 计算窗口边界:对每个时间戳,分别计算「前3秒的边界」和「后3秒的边界」。
- 用二分查找定位边界位置:通过
searchsorted找到每个边界在整个时间戳序列中的插入点,然后用索引差得到窗口内的行数。
代码示例
import pandas as pd # 构造你的示例数据 data = { 'timestamp': [ '2018-09-19 00:53:48', '2018-09-19 00:53:49', '2018-09-19 00:53:53', '2018-09-19 00:53:54', '2018-09-19 00:53:55', '2018-09-19 00:53:57' ] } df = pd.DataFrame(data) df['timestamp'] = pd.to_datetime(df['timestamp']) # 提取时间戳数组,定义窗口大小 timestamps = df['timestamp'].values window = pd.Timedelta(seconds=3) # 计算每行的before数量:窗口内早于当前时间的行数 left_bounds = timestamps - window df['before'] = df.index - pd.Series(timestamps).searchsorted(left_bounds, side='left') # 计算每行的after数量:窗口内晚于当前时间的行数 right_bounds = timestamps + window df['after'] = pd.Series(timestamps).searchsorted(right_bounds, side='right') - df.index - 1 # 查看结果 print(df)
运行这段代码后,你会得到和示例完全一致的输出:
timestamp before after 0 2018-09-19 00:53:48 0 1 1 2018-09-19 00:53:49 1 0 2 2018-09-19 00:53:53 0 2 3 2018-09-19 00:53:54 1 2 4 2018-09-19 00:53:55 2 1 5 2018-09-19 00:53:57 2 0
为什么这个方法高效?
- 逐行遍历的方法,每行都要扫描整个DataFrame,时间复杂度是O(n²),当n=10000时,需要执行1亿次左右的操作;
- 而
searchsorted用二分查找,每行只需要O(log n)的时间,整个操作的时间复杂度是O(n log n),n=10000时只需要约1.4万次操作,速度提升了几千倍都不止。
注意事项
- 一定要确保你的DataFrame已经按
timestamp排序,如果没排序,记得先执行df = df.sort_values('timestamp'); - 如果你的时间戳有重复,
searchsorted的side参数可以灵活调整(比如用side='right'来处理重复值的包含逻辑),根据你的实际需求调整即可。
内容的提问来源于stack exchange,提问作者Flow Nuwen
相关产品推荐
相关产品推荐

