无主键时基于最近前置日期合并两个Pandas DataFrame
解决Pandas按学生匹配最近早于正式考试的模考记录问题
首先得把日期转换成可比较的datetime类型,不然字符串日期的比较逻辑会出错:
import pandas as pd # 转换df1的日期列,dayfirst=True适配日/月/年格式 df1['Mock_Date'] = pd.to_datetime(df1['Mock_Date'], dayfirst=True) # 转换df2的日期列 df2['Date'] = pd.to_datetime(df2['Date'], dayfirst=True)
接下来,对df1按学生分组并按模考日期排序——merge_asof要求用于匹配的左侧数据集(这里是df1)必须按匹配的日期列排序:
# 按Student_ID分组后排序,确保每个学生的模考记录按时间顺序排列 df1_sorted = df1.sort_values(['Student_ID', 'Mock_Date'])
然后用merge_asof完成匹配,这个函数会为df2的每一行,在df1中找到同Student_ID、且Mock_Date <= Date的最近一条记录:
# 执行合并,direction='backward'表示找小于等于当前日期的最近记录 result = pd.merge_asof( df2.sort_values('Date'), # merge_asof要求右侧数据集也按日期列排序 df1_sorted[['Student_ID', 'Mock_Date', 'Mock_score']], by='Student_ID', left_on='Date', right_on='Mock_Date', direction='backward' ) # 恢复原df2的顺序,调整列顺序到期望格式 result = result.loc[df2.index].reindex(columns=['Student_ID', 'Date', 'Score', 'Mock_Date', 'Mock_score']) # 把日期转回原字符串格式(按需选择) result['Date'] = result['Date'].dt.strftime('%d/%m/%Y') result['Mock_Date'] = result['Mock_Date'].dt.strftime('%d/%m/%Y').where(pd.notna(result['Mock_Date']))
这样得到的结果就和你期望的输出一致:
- 无符合条件模考记录的行,
Mock_Date和Mock_score自动填充NaN - 每个正式考试记录都会匹配到同学生最近的、日期更早的模考记录
关键说明
merge_asof是处理这类时间序列匹配的高效工具,比手动循环或分组筛选性能优异,尤其适合大数据量场景- 必须确保两个数据集都按匹配的日期列排序,否则会导致匹配结果错误
direction='backward'是核心参数,指定查找小于等于当前日期的最近记录;若需找大于等于的最近记录可改用forward
内容的提问来源于stack exchange,提问作者Apook
相关产品推荐
相关产品推荐

