Pandas基于最近时间戳合并两DataFrame并保留重复行问题
pd.merge_asof默认仅会为左表每行匹配右表的第一个符合条件的行,无法拿到右表同一匹配时间戳下的全部数据。我们可以拆分两步实现需求:先为df2每行匹配到df1中最近的时间戳值,再用该值做等值左连接获取df1同时间下的所有行,全程保留df2全量数据。
步骤1:预处理数据(必须)
merge_asof要求参与合并的表按时间戳排序,且时间列需要为datetime类型:
import pandas as pd # 构造示例数据 df1 = pd.DataFrame({'tstamp': ['12-11-2021 00:00:00','12-11-2021 00:00:00','12-11-2021 01:00:00','12-11-2021 01:00:00'],'band_name': ['A','B','A','B'],'band_values' : [1,2,3,4]}) df2 = pd.DataFrame({'tstamp': ['12-11-2021 00:10:00','12-11-2021 00:20:00','12-11-2021 01:10:00','12-11-2021 01:20:00','12-11-2021 01:30:00'],'mgr_name': ['John','Nick','Jack','Jayce','Mark'],'mgr_surname': ['Hanks','Lad','Ors','Lancelot','Larks']}) # 转换时间列格式 df1['tstamp'] = pd.to_datetime(df1['tstamp'], format='%d-%m-%Y %H:%M:%S') df2['tstamp'] = pd.to_datetime(df2['tstamp'], format='%d-%m-%Y %H:%M:%S') # 按时间戳排序 df1 = df1.sort_values('tstamp').reset_index(drop=True) df2 = df2.sort_values('tstamp').reset_index(drop=True)
步骤2:为df2每行匹配最近的df1时间戳
# 仅用df1的唯一时间戳做匹配,避免冗余计算 df2_matched = pd.merge_asof( df2, df1[['tstamp']].drop_duplicates(), on='tstamp', direction='nearest', suffixes=('', '_df1') ).rename(columns={'tstamp_df1': 'matched_df1_tstamp'})
如果需要限制最大匹配时间差,可以增加tolerance参数,比如设置30分钟内才匹配:pd.merge_asof(..., tolerance=pd.Timedelta(minutes=30))
步骤3:等值关联获取df1全部匹配行
用左连接保证df2全量数据被保留:
final_df = pd.merge( df2_matched, df1, left_on='matched_df1_tstamp', right_on='tstamp', how='left', suffixes=('', '_df1') ) # 可选:删除冗余的重复时间列 final_df = final_df.drop(columns=['tstamp_df1', 'matched_df1_tstamp'])
结果说明
最终输出共10行,df2的5行数据全部保留,每行都关联了df1对应最近时间戳下的2条(A、B频段)数据,符合需求。
内容的提问来源于stack exchange,提问作者jvario1
相关产品推荐
相关产品推荐

