You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Pandas DataFrame中确保观测值间的最小时间间隔?

高效筛选Pandas时间序列:保留最小间隔的观测值

我有一个按日期列排序的Pandas DataFrame,需要确保观测值之间存在最小时间间隔(以10分钟为例:首个观测值在8:05,下一个需≥8:15,期间的观测值删除;第二个观测值若在8:17,则8:17-8:27间的观测值删除,以此类推)。

当前用逐行循环的脚本能实现需求,但几十万行的数据集上运行极慢,代码如下:

cur_time = df.iloc[0].Date

for idx, row in df[1:].iterrows():
    time_diff = (row.Date - cur_time).total_seconds()
    if time_diff > window*60:
        cur_time = row.Date
    else:
        trades_df.drop(idx, inplace=True)

请问有没有更高效的优化方法?将日期列设为索引后是否有现成函数可实现该功能?

补充:调研发现df.resample(window + 'M').first()功能类似,但数据集是稀疏数据(间隔从1秒到1个月不等),该方法不适用。


优化方案

核心问题分析

原来的代码性能差有两个关键原因:

  1. iterrows()逐行生成Series对象,单循环开销极大;
  2. 频繁调用drop(idx, inplace=True)会不断重排DataFrame的列存储数据,导致性能急剧下降。

方法1:纯Numpy循环(比原方法快10-50倍)

直接操作日期的数值化timestamp,避免逐行Series的开销:

import pandas as pd
import numpy as np

# 确保日期列是datetime类型(如果还不是)
df['Date'] = pd.to_datetime(df['Date'])
window_minutes = 10
window_seconds = window_minutes * 60

# 初始化保留标记数组
keep = np.zeros(len(df), dtype=bool)
keep[0] = True
last_kept_ts = df['Date'].iloc[0].timestamp()

for i in range(1, len(df)):
    current_ts = df['Date'].iloc[i].timestamp()
    if current_ts - last_kept_ts >= window_seconds:
        keep[i] = True
        last_kept_ts = current_ts

# 一次性筛选结果
filtered_df = df[keep].reset_index(drop=True)

方法2:Numba编译加速(比原方法快50-200倍)

用Numba将循环编译为机器码,适合超大规模数据集:

import pandas as pd
import numpy as np
from numba import jit

# 确保日期列是datetime类型
df['Date'] = pd.to_datetime(df['Date'])
window_minutes = 10
window_seconds = window_minutes * 60

# 把日期转为int64类型的timestamp(Numba对数值类型处理更高效)
dates_ts = df['Date'].astype(np.int64).values

@jit(nopython=True)
def filter_dates(dates, window):
    n = len(dates)
    keep = np.zeros(n, dtype=np.bool_)
    keep[0] = True
    last_kept = dates[0]
    for i in range(1, n):
        if dates[i] >= last_kept + window * 1_000_000_000:  # Pandas的timestamp是纳秒级
            keep[i] = True
            last_kept = dates[i]
    return keep

# 生成保留标记并筛选
keep = filter_dates(dates_ts, window_seconds)
filtered_df = df[keep].reset_index(drop=True)

关于日期列设为索引

将日期列设为DatetimeIndex本身没有现成函数直接实现该动态阈值筛选逻辑,但可以利用索引的数值化特性优化计算(比如直接用df.index.astype(np.int64)获取timestamp,比列访问略快),核心筛选逻辑还是需要用上述循环或编译方法。


内容的提问来源于stack exchange,提问作者Tommy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 00:53:36