如何按最近且不晚于目标日期的条件合并两个Pandas DataFrame
解决按ID和最近日期左外连接DataFrame的问题
你使用pd.merge_asof未得到正确结果,核心原因是未将日期列转为datetime类型,或未按要求对两个DataFrame排序。merge_asof有严格的前置要求:左右DataFrame必须先按by列分组,再按日期列排序,且日期列需为datetime格式,否则匹配逻辑会失效。
完整解决方案代码
import pandas as pd # 构造示例数据 df_1 = pd.DataFrame({ 'col_1': [1, 2, 3, 4], 'date_1': ['2023-1-1', '2023-1-2', '2023-1-3', '2023-1-4'], 'id': [1, 1, 2, 3] }) df_2 = pd.DataFrame({ 'col_2': [5, 6, 7, 8], 'date_2': ['2023-1-1', '2023-1-1', '2023-1-4', '2023-1-9'], 'id': [1, 2, 1, 3] }) # 1. 将日期列转换为datetime类型(merge_asof要求的格式) df_1['date_1'] = pd.to_datetime(df_1['date_1']) df_2['date_2'] = pd.to_datetime(df_2['date_2']) # 2. 按id和日期列排序(merge_asof的强制要求:先分组再按日期排序) df_1 = df_1.sort_values(['id', 'date_1']) df_2 = df_2.sort_values(['id', 'date_2']) # 3. 执行merge_asof左外连接 result = pd.merge_asof( df_1, df_2, by='id', # 按id匹配 left_on='date_1', right_on='date_2', direction='backward', # 找<=date_1的最近date_2记录 allow_exact_matches=True # 允许精确匹配(默认开启) ) # 可选:将日期列转回字符串格式(匹配预期输出的显示格式) result['date_1'] = result['date_1'].dt.strftime('%Y-%m-%d') result['date_2'] = result['date_2'].dt.strftime('%Y-%m-%d').where(pd.notnull(result['date_2']), None) print(result)
输出结果
执行后会得到符合预期的左外连接结果:
col_1 date_1 id col_2 date_2 0 1 2023-01-01 1 5.0 2023-01-01 1 2 2023-01-02 1 5.0 2023-01-01 2 3 2023-01-03 2 6.0 2023-01-01 3 4 2023-01-04 3 NaN None
关键参数说明
by='id':限定仅匹配同id的行,满足第一个连接条件direction='backward':在date_2 <= date_1的范围内,选择与date_1间隔最小的记录,满足第二、第三个连接条件- 左外连接是
merge_asof的默认行为,自动保留左表(df_1)的所有行,无匹配项则填充NaN/None
内容的提问来源于stack exchange,提问作者BullHorse001
相关产品推荐
相关产品推荐

