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

基于多条件高效合并两个DataFrame的技术实现咨询

问题描述

我有两个规模适中的DataFrame,结构如下:

df_B

id     start_time                   end_time                     side      cost 
1234   2021-01-01 16:00:00.100000   2021-01-01 16:02:00.100000   BUY       100
1564   2021-01-01 16:05:00.100000   2021-01-01 16:10:00.100000   BUY       111
7535   2021-01-01 16:40:00.100000   2021-01-01 16:55:00.100000   BUY       124
9999   2021-01-01 16:44:00.100000   2021-01-01 16:45:00.100000   BUY       128

df_S

id     start_time                   end_time                     side      cost 
5366   2021-01-01 16:00:00.100000   2021-01-01 16:02:00.100000   SELL       100
4533   2021-01-01 16:05:00.100000   2021-01-01 16:08:00.100000   SELL       105
4532   2021-01-01 16:20:00.100000   2021-01-01 16:50:00.100000   SELL       122
5827   2021-01-01 16:30:00.100000   2021-01-01 16:35:00.100000   SELL       123

我需要创建一个新的DataFrame,规则是:遍历df_B的每条记录,当df_S.cost <= df_B.cost且df_S.start_time <= df_B.end_time时,将匹配的df_S记录合并到对应df_B记录后。

期望输出示例:

id     start_time                   end_time                     side      cost  id_S   start_time_S             end_time_S             side_S      cost_S 
1234   2021-01-01 16:00:00.100000   2021-01-01 16:02:00.100000   BUY       100   5366   2021-01-01 16:00:00.100000   2021-01-01 16:02:00.100000   SELL       100
1564   2021-01-01 16:05:00.100000   2021-01-01 16:10:00.100000   BUY       111   4533   2021-01-01 16:05:00.100000   2021-01-01 16:08:00.100000   SELL       105
7535   2021-01-01 16:40:00.100000   2021-01-01 16:55:00.100000   BUY       124
9999   2021-01-01 16:44:00.100000   2021-01-01 16:45:00.100000   BUY       128

针对大型DataFrame,如何高效实现这一需求?


高效实现方案

针对大型DataFrame,绝对要避免逐行遍历——这种方法时间复杂度为O(n*m),数据量大时会直接导致性能瓶颈。推荐以下两种基于矢量化操作或索引优化的方案:

方法1:条件交叉合并 + 筛选去重

通过merge生成笛卡尔积后,过滤符合条件的行,再处理多匹配场景。适合数据规模中等的情况:

import pandas as pd

# 先转换时间列为datetime类型(必须步骤)
df_B['start_time'] = pd.to_datetime(df_B['start_time'])
df_B['end_time'] = pd.to_datetime(df_B['end_time'])
df_S['start_time'] = pd.to_datetime(df_S['start_time'])
df_S['end_time'] = pd.to_datetime(df_S['end_time'])

# 给df_S列名加后缀,避免合并后重名冲突
df_S = df_S.add_suffix('_S')

# 交叉合并两个DataFrame
merged = df_B.merge(df_S, how='left')

# 过滤满足条件的记录
filtered = merged[(merged['cost_S'] <= merged['cost']) & (merged['start_time_S'] <= merged['end_time'])]

# 处理多匹配:若一个df_B行对应多个df_S,取第一个匹配(可按需调整为取最大cost_S等)
result = filtered.groupby(df_B.columns.tolist()).first().reset_index()

# 补全无匹配的df_B记录
result = df_B.merge(result, how='left')

方法2:IntervalIndex时间匹配 + 成本过滤

利用IntervalIndex实现时间范围的快速匹配,避免全量笛卡尔积,适合超大型DataFrame场景:

import pandas as pd

# 转换时间列为datetime类型
df_B['start_time'] = pd.to_datetime(df_B['start_time'])
df_B['end_time'] = pd.to_datetime(df_B['end_time'])
df_S['start_time'] = pd.to_datetime(df_S['start_time'])
df_S['end_time'] = pd.to_datetime(df_S['end_time'])

# 基于df_B的时间范围构建IntervalIndex
intervals = pd.IntervalIndex.from_arrays(df_B['start_time'], df_B['end_time'], closed='both')

# 找到每个df_S记录对应的df_B行索引(无匹配则返回-1)
df_S['b_idx'] = intervals.get_indexer(df_S['start_time'])

# 过滤出匹配成功且成本符合条件的df_S记录
matched_S = df_S[(df_S['b_idx'] != -1) & (df_S['cost'] <= df_B.loc[df_S['b_idx'], 'cost'].values)]

# 重命名df_S列并合并到df_B
matched_S = matched_S.add_suffix('_S').rename(columns={'b_idx_S': 'b_idx'})
result = df_B.reset_index().rename(columns={'index': 'b_idx'}).merge(matched_S, on='b_idx', how='left').drop('b_idx', axis=1)

关键注意事项

  • 时间列类型转换:必须将时间列转为datetime类型,否则字符串比较会出错。
  • 多匹配处理:若存在一个df_B对应多个df_S的情况,需明确需求(保留全部、取第一个、取最优),调整代码中的筛选/分组逻辑。
  • 超大规模数据:如果数据量达到千万级,可考虑使用Dask进行分布式处理,避免内存溢出。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 03:55:14