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

基于时间区间条件高效实现将df2的Info列数据匹配到df1的方法

基于时间区间条件高效实现将df2的Info列数据匹配到df1的方法

嗨,针对你提出的这个时间区间匹配需求——把df2里的Info列数据匹配到df1,要求df1的Time落在df2的Start_Time和End_Time之间,我来给你分享几个高效的实现方法,尤其是适合大数据量的场景:

首先先明确你提供的原始数据:

df1

TimeIDPlace_Holder
13:10:00#1g
13:10:00#2g
14:10:00#1g
14:10:00#2g
15:50:00#1g

df2

Start_TimeEnd_TimeInfo
13:00:0013:55:00abc
14:00:0014:30:00xyz
15:00:0015:20:00tuv

方法一:使用merge_asof(推荐,高效适配大数据)

merge_asof是pandas专门为有序键的合并场景设计的工具,非常适合这种时间区间匹配,性能比循环或逐行判断好太多,时间复杂度为O(n log n)(主要来自排序步骤)。

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

首先得把所有时间字符串转成datetime格式,这样才能正确进行区间比较:

import pandas as pd

# 转换df1的Time列
df1['Time'] = pd.to_datetime(df1['Time'], format='%H:%M:%S')
# 转换df2的Start_Time和End_Time列
df2['Start_Time'] = pd.to_datetime(df2['Start_Time'], format='%H:%M:%S')
df2['End_Time'] = pd.to_datetime(df2['End_Time'], format='%H:%M:%S')

步骤2:对df2按Start_Time排序

merge_asof要求右表(这里是df2)必须按匹配键(Start_Time)有序:

df2_sorted = df2.sort_values('Start_Time')

步骤3:合并并过滤区间

先通过merge_asof匹配到Start_Time <= Time的最近行,再过滤出Time <= End_Time的结果,确保Time落在完整区间内:

# 先对df1按Time排序(merge_asof要求左表也有序)
df1_sorted = df1.sort_values('Time')

# 执行合并,匹配最近的Start_Time不晚于Time的行
merged = pd.merge_asof(df1_sorted, df2_sorted, left_on='Time', right_on='Start_Time')

# 过滤出Time在[Start_Time, End_Time]区间内的记录
merged = merged[merged['Time'] <= merged['End_Time']]

# 如果需要保留df1中所有原始行(包括没匹配到区间的,Info显示NaN),可以这样处理:
merged_full = pd.merge_asof(df1_sorted, df2_sorted, left_on='Time', right_on='Start_Time', direction='backward')
merged_full['Info'] = merged_full.apply(
    lambda row: row['Info'] if row['Time'] <= row['End_Time'] else pd.NA,
    axis=1
)

# 恢复df1原来的行顺序(如果需要)
merged_full = merged_full.sort_index()

方法二:区间索引匹配(适合小数据量)

如果你的数据量不大,也可以用区间索引的方式实现,代码更直观,但性能不如merge_asof:

# 为df2创建时间区间索引
df2['Time_Interval'] = pd.IntervalIndex.from_arrays(
    df2['Start_Time'], df2['End_Time'], closed='both'
)

# 逐行匹配区间
df1['Info'] = df1['Time'].apply(
    lambda t: df2[df2['Time_Interval'].contains(t)]['Info'].values[0] 
    if any(df2['Time_Interval'].contains(t)) 
    else pd.NA
)

预期输出

处理后你会得到类似这样的结果(以保留所有df1行的情况为例):

TimeIDPlace_HolderInfo
2023-01-01 13:10:00#1gabc
2023-01-01 13:10:00#2gabc
2023-01-01 14:10:00#1gxyz
2023-01-01 14:10:00#2gxyz
2023-01-01 15:50:00#1g

(注:日期部分是pandas默认补充的,不影响时间区间的判断,你可以用.dt.time提取时间部分)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.15 15:42:59