Pandas中按ID匹配两个DataFrame获取不重复的最小符合条件other_date
解法思路
我们可以按以下步骤实现需求:
- 首先将两个表的日期字段统一转换为
datetime格式,方便后续大小比较 - 按
ID对两个表分别分组,每个ID单独处理匹配逻辑,避免跨ID匹配 - 对每个ID下的
updated_date按升序排序,other_date也按升序排序,用双指针贪心匹配:每次给当前updated_date找第一个大于等于它的未使用other_date,匹配成功后该other_date就标记为已使用不再参与后续匹配 - 没有匹配到的填充为
NONE,最后按df1的原始顺序还原结果
完整实现代码
import pandas as pd # 构造示例数据 df1 = pd.DataFrame( { "ID" : ["11", "11", "11", "11" , "55"] , "updated_date" : ["2019/04/03", "2019/05/02", "2019/05/20", "2019/07/01", "2019/03/03"] } ) df2 = pd.DataFrame( { "ID" : ["11", "11", "11", "11" , "55"] , "other_date" : ["2019/04/09", "2019/05/14", "2019/06/05", "2019/06/05", "2019/03/03"] } ) # 转换日期格式 df1['updated_date'] = pd.to_datetime(df1['updated_date']) df2['other_date'] = pd.to_datetime(df2['other_date']) # 定义匹配函数 def match_dates(group_df1, group_df2): # 保存df1的原始索引,后续还原顺序用 group_df1 = group_df1.reset_index().sort_values('updated_date') others = sorted(group_df2['other_date'].tolist()) res = [] ptr = 0 # other_date的指针 for ud in group_df1['updated_date']: matched = 'NONE' while ptr < len(others): if others[ptr] >= ud: matched = others[ptr] ptr += 1 break ptr += 1 res.append(matched) group_df1['other_date'] = res # 还原原始顺序 return group_df1.set_index('index').sort_index() # 按ID分组应用匹配函数 result = df1.groupby('ID', group_keys=False).apply(lambda x: match_dates(x, df2[df2['ID'] == x.name])) # 日期转成字符串格式,和示例输出一致 result['updated_date'] = result['updated_date'].dt.strftime('%Y-%m-%d') result['other_date'] = result['other_date'].apply(lambda x: x.strftime('%Y-%m-%d') if x != 'NONE' else x) # 重置索引得到最终结果 result = result.reset_index(drop=True) print(result)
输出结果
运行后得到的结果和期望完全一致:
ID updated_date other_date 0 11 2019-04-03 2019-04-09 1 11 2019-05-02 2019-05-14 2 11 2019-05-20 2019-06-05 3 11 2019-07-01 NONE 4 55 2019-03-03 2019-03-03
内容的提问来源于stack exchange,提问作者big_soapy
相关产品推荐
相关产品推荐

