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

如何高效在另一DataFrame中查找固定时间范围内的所有邻近记录

高效查找DataFrame固定时间范围内邻近记录的方法

问题描述

现有两个DataFrame:order_df(包含订单ID和订单时间)和trade_df(包含交易ID和交易时间),需要为order_df的每一行,找出trade_df中交易时间处于订单时间前后指定分钟数(示例为3分钟)范围内的所有交易ID,最终将符合条件的交易ID合并为字符串列。

示例数据:

import datetime
import pandas as pd

order_dict = {
    'Order ID': ['Order 1', 'Order 2', 'Order 3', 'Order 4'],
    'Order Time': [datetime.datetime(2023, 3, 8, 7, 5, 0), datetime.datetime(2023, 3, 8, 7, 10, 0), datetime.datetime(2023, 3, 8, 7, 15, 0), datetime.datetime(2023, 3, 8, 7, 20, 0)]
}
trade_dict = {
    'Trade ID': ['Trade 1001', 'Trade 1002', 'Trade 1003', 'Trade 1004', 'Trade 1005'],
    'Trade Time': [datetime.datetime(2023, 3, 8, 7, 8, 0), datetime.datetime(2023, 3, 8, 7, 9, 0), datetime.datetime(2023, 3, 8, 7, 17, 0), datetime.datetime(2023, 3, 8, 7, 18, 0), datetime.datetime(2023, 3, 8, 7, 30, 0)]
}

order_df = pd.DataFrame(order_dict)
trade_df = pd.DataFrame(trade_dict)

预期输出(3分钟时间范围):

Order ID           Order Time Nearest Trade ID
0   Order 1 2023-03-08 07:05:00        Trade 1001
1   Order 2 2023-03-08 07:10:00  Trade 1001, Trade 1002
2   Order 3 2023-03-08 07:15:00  Trade 1003, Trade 1004
3   Order 4 2023-03-08 07:20:00  Trade 1003, Trade 1004

原始低效实现

最初使用apply逐行遍历订单时间,筛选交易时间在范围内的记录,这种方法在数据量达10万条时耗时约3.5分钟,效率极低:

def fixed_distance_nearest_neighbors(x, fixed_distance, lookup_df, lookup_field, return_field):
    return ', '.join(lookup_df[lookup_df[lookup_field].between(x - datetime.timedelta(minutes=fixed_distance), x + datetime.timedelta(minutes=fixed_distance))][return_field])

order_df['Nearest Trade ID'] = order_df['Order Time'].apply(lambda x: fixed_distance_nearest_neighbors(x, 3, trade_df, 'Trade Time', 'Trade ID'))

高效实现方案

方法1:排序+二分查找(最优性能)

核心思路:先对交易数据按时间排序,利用numpy.searchsorted对每个订单的时间范围进行二分查找,快速定位符合条件的交易起止索引,最后批量聚合结果。这种方法将逐行O(n)的查找转为O(log n)的二分查找,性能提升显著。

代码实现:

import numpy as np

# 预处理:对交易数据按时间排序,提取时间和ID的数组
trade_sorted = trade_df.sort_values('Trade Time').reset_index(drop=True)
trade_times = trade_sorted['Trade Time'].values
trade_ids = trade_sorted['Trade ID'].values

# 定义时间范围(此处为3分钟)
time_delta = datetime.timedelta(minutes=3)
order_times = order_df['Order Time'].values
lower_bounds = order_times - time_delta
upper_bounds = order_times + time_delta

# 用二分查找定位每个时间范围在交易数据中的起止位置
left_idx = np.searchsorted(trade_times, lower_bounds, side='left')
right_idx = np.searchsorted(trade_times, upper_bounds, side='right')

# 生成每个订单对应的交易ID字符串
order_df['Nearest Trade ID'] = [', '.join(trade_ids[left:right]) for left, right in zip(left_idx, right_idx)]

方法2:IntervalIndex匹配(简洁向量化)

核心思路:为每个订单时间创建时间区间,利用pandas的IntervalIndex快速匹配交易时间所属的订单区间,再通过分组聚合得到结果,代码更简洁易读。

代码实现:

# 为每个订单时间创建包含前后3分钟的区间
time_delta = datetime.timedelta(minutes=3)
order_intervals = pd.IntervalIndex.from_arrays(
    order_df['Order Time'] - time_delta,
    order_df['Order Time'] + time_delta,
    closed='both'
)

# 对交易数据按时间排序,匹配每个交易所属的订单索引
trade_sorted = trade_df.sort_values('Trade Time')
matches = trade_sorted['Trade Time'].apply(lambda t: order_intervals.get_loc(t)).explode()

# 分组聚合交易ID,合并到原订单DataFrame
trade_groups = trade_sorted.loc[matches.index, 'Trade ID'].groupby(matches).agg(', '.join)
order_df['Nearest Trade ID'] = order_df.index.map(trade_groups).fillna('')

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 10:35:06