如何在Pandas中对两个DataFrame基于分组列与日期列执行asof merge?
如何使用Pandas的merge_asof实现按水果匹配最接近日期的合并?
需求说明
拥有两个DataFrame(df1和df2),需通过Pandas的merge_asof执行asof合并:
- 按
Frutas列分组,为对应水果匹配最接近的日期/时间 - 合并df1的
Data列与df2的Data/Hora列信息 - 最终保留
Transcricao和Pedido de venda列
DataFrame结构
DataFrame df1
from datetime import datetime import pandas as pd datas_df1 = [datetime(2023, 8, 1), datetime(2023, 8, 3), datetime(2023, 8, 2), datetime(2023, 8, 1), datetime(2023, 8, 1), datetime(2023, 8, 3), datetime(2023, 8, 4), datetime(2023, 8, 4), datetime(2023, 8, 2), datetime(2023, 8, 4)] df1_dict = { "Frutas": ["Maçã", "Banana", "Laranja", "Uva", "Morango", "Pera", "Abacaxi", "Melancia", "Cereja", "Kiwi"], "Data": datas_df1, "Transcricao": [f"Transcricao_{i}" for i in range(10)] } df1 = pd.DataFrame(df1_dict)
DataFrame df2
datas_df2 = [datetime(2023, 8, 1, 14, 37), datetime(2023, 8, 3, 8, 23), datetime(2023, 8, 1, 9, 56), datetime(2023, 8, 4, 12, 9), datetime(2023, 8, 3, 10, 50), datetime(2023, 8, 2, 17, 38), datetime(2023, 8, 4, 19, 22), datetime(2023, 8, 2, 7, 44), datetime(2023, 8, 1, 21, 33), datetime(2023, 8, 2, 23, 6)] df2_dict = { "Frutas": ["Maçã", "Banana", "Laranja", "Uva", "Morango", "Pera", "Abacaxi", "Melancia", "Cereja", "Kiwi"], "Data/Hora": datas_df2, "Pedido de venda": [f"Pedido_{i}" for i in range(10)] } df2 = pd.DataFrame(df2_dict)
错误代码及问题
尝试执行以下代码时出现TypeError: Function call with ambiguous argument types:
df_merge = pd.merge_asof(df1.sort_values('data'), df2.sort_values('Data/Hora'), left_on='data', right_on='Data/Hora', by='Frutas')
错误原因
- 列名大小写错误:df1的时间列是
Data(首字母大写),但代码中写成了小写的data,导致无法找到对应列 - 排序不完整:
merge_asof要求两个DataFrame必须同时按by列(Frutas)和时间列排序,仅排序时间列会导致分组匹配逻辑失效 - 时间类型兼容问题:df1的
Data是日期类型,df2的Data/Hora是带时分秒的datetime类型,虽可比较,但统一类型能避免潜在问题
正确实现代码
# 1. 统一时间列类型(将df1的Data转为datetime类型) df1['Data'] = pd.to_datetime(df1['Data']) # 2. 按分组列+时间列排序(merge_asof强制要求) df1_sorted = df1.sort_values(by=['Frutas', 'Data']) df2_sorted = df2.sort_values(by=['Frutas', 'Data/Hora']) # 3. 执行merge_asof,使用direction='nearest'匹配最接近的时间 df_merge = pd.merge_asof( df1_sorted, df2_sorted, left_on='Data', right_on='Data/Hora', by='Frutas', direction='nearest' ) # 4. 筛选需要的列 df_merge_final = df_merge[['Frutas', 'Data', 'Transcricao', 'Data/Hora', 'Pedido de venda']] print(df_merge_final)
代码说明
- 类型统一:将df1的
Data转为datetime类型,确保与df2的Data/Hora类型完全兼容 - 正确排序:按
Frutas(分组依据)和时间列排序,保证merge_asof能按分组匹配时间 - direction参数:
direction='nearest'会为每个df1的记录,找到同水果分组下时间差最小的df2记录,完全符合“匹配最接近日期/时间”的需求(默认direction='backward'仅匹配不大于左边时间的最近记录) - 列筛选:最终保留业务需要的列,剔除冗余数据
内容的提问来源于stack exchange,提问作者Guilherme Henrique Favaro
相关产品推荐
相关产品推荐

