Pandas带条件合并匹配:获取符合日期间隔要求的最大special_date
Pandas实现区间匹配取最大符合值的方案
核心思路
使用pandas.merge_asof实现高效的区间匹配,该方法针对有序的时间/数值列做关联性能远好于逐行遍历,适合大数据量场景,操作步骤如下:
- 先将所有日期列转换为
datetime类型,避免字符串比较逻辑错误 - 对两个DataFrame的日期匹配列做升序排序(merge_asof的强制要求)
- 按ID分组,匹配小于等于
second_date的最大special_date - 过滤掉小于
first_date的不符合结果,置为NaN
完整代码
import pandas as pd # 构造示例数据 df_special = pd.DataFrame({ 'ID': [11,11,11,11], 'special_date': ['2019-04-06', '2019-04-09', '2019-06-03', '2019-03-11'] }) df_range = pd.DataFrame({ 'ID': [11,11,11,11], 'first_date': ['2019-04-03', '2019-05-02', '2019-05-20', '2019-03-03'], 'second_date': ['2019-04-09', '2019-05-14', '2019-06-05', '2019-03-07'] }) # 日期列转datetime类型,必须操作 df_special['special_date'] = pd.to_datetime(df_special['special_date']) df_range[['first_date', 'second_date']] = df_range[['first_date', 'second_date']].apply(pd.to_datetime) # 排序:merge_asof要求连接键列是升序排列 df_special = df_special.sort_values('special_date').reset_index(drop=True) df_range = df_range.sort_values('second_date').reset_index(drop=True) # 关联匹配 res = pd.merge_asof( left=df_range, right=df_special, by='ID', left_on='second_date', right_on='special_date', direction='backward' ) # 过滤不符合区间的结果 res.loc[res['special_date'] < res['first_date'], 'special_date'] = pd.NA # 调整列顺序和排序,和期望输出一致 res = res[['ID', 'first_date', 'special_date', 'second_date']].sort_values('first_date').reset_index(drop=True) print(res)
小数据量简化写法
如果你的数据集很小,也可以用逐行匹配的写法,逻辑更直观但性能较差:
def match_max_date(row): filter_mask = ( (df_special['ID'] == row['ID']) & (df_special['special_date'].between(row['first_date'], row['second_date'])) ) valid_dates = df_special.loc[filter_mask, 'special_date'] return valid_dates.max() if len(valid_dates) > 0 else pd.NA res = df_range.copy() res['special_date'] = res.apply(match_max_date, axis=1)
内容的提问来源于stack exchange,提问作者big_soapy
相关产品推荐
相关产品推荐

