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

如何优化Pandas中时间区间转换次数计算的运行时长

高效实现同Base分组下时间区间内记录计数需求

需求说明

统计同一Base分组下,Time_of_Fetch处于当前行Time_of_Fetch至Time_Completed区间内的记录数量,并将该计数作为新列Check_value添加至DataFrame。

样本数据

Time_Completed   Time_of_Fetch   Base    Number of event
        03-06-2022 14:56    03-06-2022 14:14    Q112    12
        03-06-2022 14:54    03-06-2022 14:14    Q112    11
        03-06-2022 14:51    03-06-2022 14:18    Q112    9
        03-06-2022 14:52    03-06-2022 14:21    Q112    8
        03-06-2022 15:07    03-06-2022 14:25    Q112    8
        03-06-2022 14:54    03-06-2022 14:25    Q112    7
        03-06-2022 14:50    03-06-2022 14:25    Q112    5
        03-06-2022 15:11    03-06-2022 14:27    Q112    5
        03-06-2022 15:17    03-06-2022 14:29    Q112    4
        03-06-2022 15:19    03-06-2022 14:47    Q112    3
        03-06-2022 15:18    03-06-2022 14:49    Q112    2
        03-06-2022 15:21    03-06-2022 14:54    Q112    1
        03-06-2022 15:20    03-06-2022 14:58    Q106    2
        03-06-2022 15:23    03-06-2022 14:59    Q106    1

现有低效实现

循环方式

result = []
for i in range(0, len(df)):
   result.append(df[(df['Time_of_Fetch'] >= df.iloc[i]['Time_of_Fetch']) & (df['Time_of_Fetch'] < df.iloc[i]['Time_Completed']) & (df['Base'] == df.iloc[i]['Base'])].count()['Base'])

df['Check_value'] = result

尝试的apply方法

df_108.assign = df_108.apply((lambda row :df_108[(df_108['Time_of_Fetch'] >= df_108['Time_of_Fetch'])
& (df_108['Time_of_Fetch'] < df_108['Time_Completed'])& (df_108['Base'] == df_108['Base'])].count()['Base']),axis = 1)

以上两种方法时间复杂度均为O(n²),在大数据集下会因重复遍历数据导致耗时激增。

优化方案

核心思路

通过Base分组后,对每组的Time_of_Fetch排序,利用二分查找快速统计区间内的记录数,将时间复杂度降至O(N log N),大幅提升处理效率。

具体实现代码

步骤1:转换时间列为datetime类型

首先确保时间列是可比较的datetime格式:

import pandas as pd
import bisect

# 转换时间格式
df['Time_Completed'] = pd.to_datetime(df['Time_Completed'], format='%d-%m-%Y %H:%M')
df['Time_of_Fetch'] = pd.to_datetime(df['Time_of_Fetch'], format='%d-%m-%Y %H:%M')

步骤2:分组+二分查找统计

使用向量化的二分查找实现,避免逐行遍历:

def count_in_range(group):
    # 对当前分组的Time_of_Fetch排序
    sorted_times = group['Time_of_Fetch'].sort_values().values
    # 用二分查找计算每个区间的左右边界位置
    left_positions = [bisect.bisect_right(sorted_times, t) for t in group['Time_of_Fetch']]
    right_positions = [bisect.bisect_left(sorted_times, t) for t in group['Time_Completed']]
    # 计算区间内的记录数
    group['Check_value'] = [right - left + 1 for left, right in zip(left_positions, right_positions)]
    return group

# 按Base分组处理,保留原索引顺序
df = df.groupby('Base', group_keys=False).apply(count_in_range)

方案优势

  • 分组排序后,每组仅需一次排序(O(n log n)),后续二分查找为O(log n)每行
  • 避免了原方法中对全数据集的重复过滤操作,大数据集下速度提升可达数十倍甚至上百倍

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 21:50:39