如何高效地基于时间范围匹配两个 DataFrame 并添加新列

梦杰同学_1406

梦杰同学_1406

2026-02-08

820人浏览

原创

如何高效地基于时间范围匹配两个 DataFrame 并添加新列

本文介绍使用 `pandas.merge_asof()` 高效实现跨 dataframe 的时间区间匹配,避免低效的嵌套循环,在百万级数据下仍保持秒级响应。

在数据分析中,常需将一个事件表(如设备操作日志)与一个时段表(如工单生效区间)按主键+时间范围关联,并将时段表中的字段(如 VALUE)作为新列注入事件表。若采用双重 for 循环逐行比对(如 df1['EVENT_TIME'] 是否落在 df2['IN_TIME'] 与 df2['OUT_TIME'] 之间),时间复杂度为 O(n×m),面对 10 万+ 行数据时极易超时(如原问题中耗时 >10 分钟)。幸运的是,Pandas 提供了专为此类场景优化的 merge_asof() 方法——它基于排序后的一对多最近匹配机制,配合后续逻辑过滤,可将性能提升数十倍。

✅ 正确做法:merge_asof + 时间范围校验

核心思路分三步:

  1. 统一时间类型:确保 EVENT_TIME、IN_TIME、OUT_TIME 均为 datetime64 类型;
  2. merge_asof 初步关联:按 LOT 分组,以 EVENT_TIME(左)和 IN_TIME(右)为键进行“向后最近匹配”(默认策略),快速找到每个事件最接近且不晚于其发生时刻的 IN_TIME 所在记录;
  3. 二次过滤:用 .assign() 和布尔掩码保留满足 EVENT_TIME ≤ OUT_TIME 的匹配结果,剔除超出时段上限的误匹配。
import pandas as pd

# 示例数据构造
data1 = {
    'LOT': ['A', 'A', 'A', 'A', 'A', 'A'],
    'SLOT': [1, 2, 3, 4, 5, 6],
    'EVENT_TIME': ['2024-01-20 13:30', '2024-01-20 13:36',
                    '2024-01-21 14:28', '2024-01-21 14:30',
                    '2024-01-21 14:32', '2024-01-21 14:34']
}
data2 = {
    'LOT': ['A', 'A'],
    'IN_TIME': ['2024-01-20 13:20', '2024-01-21 14:25'],
    'OUT_TIME': ['2024-01-20 13:40', '2024-01-21 14:50'],
    'VALUE': [13, 15]
}
df1 = pd.DataFrame(data1)
df2 = pd.DataFrame(data2)

# 步骤1:转为 datetime
df1['EVENT_TIME'] = pd.to_datetime(df1['EVENT_TIME'])
df2['IN_TIME'] = pd.to_datetime(df2['IN_TIME'])
df2['OUT_TIME'] = pd.to_datetime(df2['OUT_TIME'])

# 步骤2+3:merge_asof + 范围校验
result = (
    pd.merge_asof(
        df1.sort_values('EVENT_TIME'), 
        df2.sort_values('IN_TIME'), 
        by='LOT', 
        left_on='EVENT_TIME', 
        right_on='IN_TIME',
        allow_exact_matches=True,  # 允许 EVENT_TIME == IN_TIME
        direction='backward'       # 取 IN_TIME ≤ EVENT_TIME 的最大值(最接近的起始点)
    )
    .assign(VALUE=lambda x: x['VALUE'].where(x['EVENT_TIME'] <p>输出结果与预期完全一致:</p><div class="aritcle_card flexRow artxards">
											<div class="artcardd flexRow">
												<a class="aritcle_card_img" rel="nofollow" href="/xiazai/js/1451" title="jQuery+CSS3 3D立体图片排列布局代码"><img
														src="https://img.php.cn/upload/jscode/000/000/001/59ba1e7f4e893977.jpg" alt="jQuery+CSS3 3D立体图片排列布局代码" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
												<div class="aritcle_card_info flexColumn">
													<a rel="nofollow" href="/xiazai/js/1451" title="jQuery+CSS3 3D立体图片排列布局代码" class="overflowclass">jQuery+CSS3 3D立体图片排列布局代码</a>
													<p class="overflowclass">jQuery+CSS3 3D立体图片排列布局代码</p>
												</div>
												<a rel="nofollow" href="/xiazai/js/1451" title="jQuery+CSS3 3D立体图片排列布局代码" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
												</a>
											</div>
										</div><pre class="brush:php;toolbar:false;">  LOT  SLOT         EVENT_TIME  DATA
0   A     1 2024-01-20 13:30:00  13.0
1   A     2 2024-01-20 13:36:00  13.0
2   A     3 2024-01-21 14:28:00  15.0
3   A     4 2024-01-21 14:30:00  15.0
4   A     5 2024-01-21 14:32:00  15.0
5   A     6 2024-01-21 14:34:00  15.0

⚠️ 注意事项与最佳实践

  • 必须排序:merge_asof 要求左右 DataFrame 均按关联时间列升序排列(sort_values 不可省略);
  • direction 参数选择:本例用 'backward'(找 ≤ EVENT_TIME 的最大 IN_TIME),若需找 ≥ EVENT_TIME 的最小 IN_TIME,则用 'forward';'nearest' 则取绝对距离最近者(但需额外验证是否在 [IN, OUT] 内);
  • 处理缺失匹配:未匹配到任何时段的行,DATA 将为 NaN,可根据业务需要 .fillna() 或 .dropna();
  • 扩展性提示:当 df2 中存在重叠时段或同一 LOT 多个非重叠区间时,该方法依然稳健;若需支持更复杂的多维范围匹配(如地理围栏),建议转向 dask 或数据库 JOIN ... ON a.time BETWEEN b.start AND b.end。

通过 merge_asof 替代暴力循环,不仅代码更简洁、可读性更强,更能将 10 万行数据的匹配耗时从分钟级降至毫秒级,是 Pandas 时间序列关联任务的首选方案。

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

排列

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
Python 时间序列分析与预测
Python 时间序列分析与预测

本专题专注讲解 Python 在时间序列数据处理与预测建模中的实战技巧,涵盖时间索引处理、周期性与趋势分解、平稳性检测、ARIMA/SARIMA 模型构建、预测误差评估,以及基于实际业务场景的时间序列项目实操,帮助学习者掌握从数据预处理到模型预测的完整时序分析能力。

2025.12.04

340

15

Python 数据清洗与预处理实战
Python 数据清洗与预处理实战

本专题系统讲解 Python 在数据清洗与预处理中的核心技术,包括使用 Pandas 进行缺失值处理、异常值检测、数据格式化、特征工程与数据转换,结合 NumPy 高效处理大规模数据。通过实战案例,帮助学习者掌握 如何处理混乱、不完整数据,为后续数据分析与机器学习模型训练打下坚实基础。

2026.01.31

272

21

Python数据分析与Pandas高级实战
Python数据分析与Pandas高级实战

本专题围绕 Python 数据分析展开,系统讲解 Pandas 的高级用法,包括数据清洗、透视表、时间序列分析以及多表合并与分组操作。通过实战案例,帮助开发者掌握高效处理与分析数据的方法,提高数据处理效率与分析能力。

2026.04.13

771

25

数据库三范式
数据库三范式

数据库三范式是一种设计规范,用于规范化关系型数据库中的数据结构,它通过消除冗余数据、提高数据库性能和数据一致性,提供了一种有效的数据库设计方法。本专题提供数据库三范式相关的文章、下载和课程。

2023.06.29

2985

3

如何删除数据库
如何删除数据库

删除数据库是指在MySQL中完全移除一个数据库及其所包含的所有数据和结构,作用包括:1、释放存储空间;2、确保数据的安全性;3、提高数据库的整体性能,加速查询和操作的执行速度。尽管删除数据库具有一些好处,但在执行任何删除操作之前,务必谨慎操作,并备份重要的数据。删除数据库将永久性地删除所有相关数据和结构,无法回滚。

2023.08.14

4121

10

vb怎么连接数据库
vb怎么连接数据库

在VB中,连接数据库通常使用ADO(ActiveX 数据对象)或 DAO(Data Access Objects)这两个技术来实现:1、引入ADO库;2、创建ADO连接对象;3、配置连接字符串;4、打开连接;5、执行SQL语句;6、处理查询结果;7、关闭连接即可。

2023.08.31

3351

3

MySQL恢复数据库
MySQL恢复数据库

MySQL恢复数据库的方法有使用物理备份恢复、使用逻辑备份恢复、使用二进制日志恢复和使用数据库复制进行恢复等。本专题为大家提供MySQL数据库相关的文章、下载、课程内容,供大家免费下载体验。

2023.09.05

1047

5

vb中怎么连接access数据库
vb中怎么连接access数据库

vb中连接access数据库的步骤包括引用必要的命名空间、创建连接字符串、创建连接对象、打开连接、执行SQL语句和关闭连接。本专题为大家提供连接access数据库相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.09

2927

5

数据库对象名无效怎么解决
数据库对象名无效怎么解决

数据库对象名无效解决办法:1、检查使用的对象名是否正确,确保没有拼写错误;2、检查数据库中是否已存在具有相同名称的对象,如果是,请更改对象名为一个不同的名称,然后重新创建;3、确保在连接数据库时使用了正确的用户名、密码和数据库名称;4、尝试重启数据库服务,然后再次尝试创建或使用对象;5、尝试更新驱动程序,然后再次尝试创建或使用对象。

2023.10.16

2907

4

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
热门推荐
/
最新课程
phpStudy极速入门视频教程
phpStudy极速入门视频教程

共6课时 | 54.7万人学习

独孤九贱(4)_PHP视频教程
独孤九贱(4)_PHP视频教程

共89课时 | 134.1万人学习