高效合并更新频率不同的Pandas DataFrame:按ID匹配并关联最近日期
高效实现按ID匹配并关联最近日期的Pandas DataFrame合并
问题背景
你有两个Pandas DataFrame:a的更新频率低于b,需要按ID匹配,同时将b中的每条记录关联到对应ID在a中的最近不晚于当前日期的记录,日期配对规则如下:
b -> a
2021-01-03 -> 2021-01-03
2021-01-15 -> 2021-01-03
2021-01-23 -> 2021-01-03
2021-02-08 -> 2021-02-06
2021-02-17 -> 2021-02-06
示例数据代码:
import pandas as pd import numpy as np a = pd.DataFrame({'id': np.array([1, 3, 4, 9]*2), 'date': np.repeat(['2021-01-03', '2021-02-06'], 4), 'score': np.linspace(0, 1, 8)}) a['date'] = pd.to_datetime(a['date']) b = pd.DataFrame({'id': np.array([1, 3, 4, 9]*5), 'date': np.repeat(['2021-01-03', '2021-01-15', '2021-01-23', '2021-02-08', '2021-02-17'], 4), 'value': np.linspace(0, 1, 20)}) b['date'] = pd.to_datetime(b['date'])
当前用循环遍历区间的方法效率太低,想找更高效的实现方式。
高效解决方案:使用pd.merge_asof
这题必须用Pandas内置的merge_asof!它就是专门为这类「按最近日期合并」的场景设计的,是完全向量化的操作,彻底避免了循环,处理大数据量时性能提升不是一点半点。
步骤说明:
- 对两个DataFrame按
id和date排序:merge_asof要求输入的DataFrame必须按合并的日期列排序,同时按分组列(这里是id)排序能进一步提升匹配效率。 - 执行
merge_asof合并:设置by='id'按ID分组匹配,direction='backward'表示找不晚于b中日期的a里的最近日期,完美契合你的需求。
实现代码:
# 先对a和b按id、date排序 a_sorted = a.sort_values(by=['id', 'date']) b_sorted = b.sort_values(by=['id', 'date']) # 使用merge_asof完成合并 result = pd.merge_asof( b_sorted, a_sorted, by='id', # 按ID分组进行匹配 on='date', # 基于日期字段找最近匹配项 direction='backward' # 规则:找不晚于当前日期的最近记录 ) # 查看合并结果(可选) print(result)
结果说明:
合并后的结果会自动将b的每条记录,与对应ID下a中最近的不晚于该日期的记录关联,完全符合你给出的日期配对规则。而且整个过程是Pandas底层优化的向量操作,比循环遍历快几个数量级,数据量越大优势越明显。
补充提示
如果你的a中存在同一个ID对应多个重复日期的情况(比如示例里的结构),merge_asof也能正确处理,它会在每个ID分组内严格按日期匹配最近的记录。
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

