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

如何高效合并无共享列的单日期DataFrame与日期范围DataFrame?

如何高效合并无共享列的单日期DataFrame与日期范围DataFrame?

嘿,你的思路其实没问题,但循环在数据量比较大的时候确实会拖慢速度,毕竟pandas的强项就是向量化操作嘛。这里给你几个更高效的方案:

方案一:使用 merge_asof(推荐,速度快)

merge_asof 本来就是为这类按时间范围匹配的场景设计的,不过需要先把两个DataFrame按日期排序,再设置好匹配规则:

import pandas as pd

# 先统一转换日期格式
df1['date'] = pd.to_datetime(df1['date'])
df2['start'] = pd.to_datetime(df2['start'])
df2['end'] = pd.to_datetime(df2['end'])

# 给df2创建用于匹配的临时列,对应我们需要的「start < date <= end」规则
df2['match_date'] = df2['start']
# merge_asof要求左右DataFrame都按匹配键排序
df1_sorted = df1.sort_values('date')
df2_sorted = df2.sort_values('match_date')

# 执行asof合并,指定forward方向匹配最近的后续区间
merged = pd.merge_asof(
    df1_sorted,
    df2_sorted,
    left_on='date',
    right_on='match_date',
    direction='forward'
)

# 过滤掉date超出对应区间end的行,给符合条件的行赋值id,其余设为空
merged['id'] = merged.apply(
    lambda x: x['id'] if x['date'] <= x['end'] else pd.NA,
    axis=1
)

# 恢复原DataFrame的顺序,整理成目标格式
result = merged[['date', 'price', 'id']].sort_index()
print(result)

这个方法完全是向量化操作,比循环快很多,数据量越大优势越明显。

方案二:使用区间索引(IntervalIndex)

另一种简洁的思路是把df2的日期范围转成区间,再用索引匹配:

import pandas as pd

df1['date'] = pd.to_datetime(df1['date'])
df2['start'] = pd.to_datetime(df2['start'])
df2['end'] = pd.to_datetime(df2['end'])

# 创建左开右闭的区间(对应start排他、end包含的规则)
intervals = pd.IntervalIndex.from_arrays(df2['start'], df2['end'], closed='right')
# 找到每个date对应的区间索引,未匹配到的会返回-1
idx = intervals.get_indexer(df1['date'])
# 给匹配成功的行赋值id,未匹配的设为空
df1['id'] = df2['id'].iloc[idx].where(idx != -1, pd.NA)

print(df1)

这个方法逻辑直观,区间索引的匹配效率也很高,代码量也更少。

关于你的原方法

你的循环逻辑很清晰,适合小数据量的场景,但当df1和df2的行数较多时,逐行循环的操作会比上面的向量化方法慢几十甚至上百倍。另外注意下,id是Python的内置函数名,最好改成id_val这类变量名,避免冲突哦。

备注:内容来源于stack exchange,提问作者AmirX

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.17 12:49:30