Pandas日期范围匹配:将日期映射至对应区间的bucket
问题描述
我们有两个DataFrame:
- df1:包含
start_date、end_date、bucket三列,共80行,每行对应一个日期区间 - df2:包含
Dates一列,共80行,每行是一个单独日期
需要把df2里的每个日期匹配到df1中对应的日期区间(也就是日期落在start_date和end_date之间),然后把匹配到的日期添加到df1的新列Dates里。
示例数据:
df1数据:
start_date end_date bucket 2017-06-01 2017-12-31 1 2018-06-01 2018-12-31 2 2019-06-01 2019-12-31 3 2020-06-01 2020-12-31 4
df2数据:
Dates 2019-08-28 2020-09-15 2017-09-13 2018-07-22
期望输出:
| start_date | end_date | bucket | Dates |
|---|---|---|---|
| 2017-06-01 | 2017-12-31 | 1 | 2017-09-13 |
| 2018-06-01 | 2018-12-31 | 2 | 2018-07-22 |
| 2019-06-01 | 2019-12-31 | 3 | 2019-08-28 |
| 2020-06-01 | 2020-12-31 | 4 | 2020-09-15 |
解决方案
第一步:统一日期格式
先把两个DataFrame里的日期列转成datetime类型,避免字符串匹配出问题:
import pandas as pd # 转换df1的日期列 df1['start_date'] = pd.to_datetime(df1['start_date']) df1['end_date'] = pd.to_datetime(df1['end_date']) # 转换df2的日期列 df2['Dates'] = pd.to_datetime(df2['Dates'])
第二步:匹配日期到对应区间
这里给两种实用方法,按需选择:
方法一:逐行匹配(简单直观)
用apply遍历df1的每一行,筛选出落在当前区间的df2日期:
def find_matching_date(row, df2_dates): # 筛选符合区间条件的日期 matched_dates = df2_dates[(df2_dates >= row['start_date']) & (df2_dates <= row['end_date'])] # 返回第一个匹配的日期,无匹配则返回None return matched_dates.iloc[0] if not matched_dates.empty else None # 给df1新增Dates列 df1['Dates'] = df1.apply(find_matching_date, df2_dates=df2['Dates'], axis=1)
方法二:交叉合并筛选(高效适配大数据)
如果数据量更大,交叉合并后筛选的方式效率更高:
# 用临时key交叉合并两个DataFrame merged_df = df1.assign(temp_key=1).merge(df2.assign(temp_key=1), on='temp_key').drop('temp_key', axis=1) # 筛选日期落在区间内的行 filtered_df = merged_df[(merged_df['Dates'] >= merged_df['start_date']) & (merged_df['Dates'] <= merged_df['end_date'])] # 把匹配结果合并回原df1 df1 = df1.merge(filtered_df[['bucket', 'Dates']], on='bucket', how='left')
补充说明
- 示例默认每个日期区间只对应一个df2日期,如果存在多个匹配,可以修改代码取第一个、最后一个,或者把所有匹配日期拼成列表
- 要是有日期找不到对应区间,结果会显示
NaN,可以根据需求填充默认值或者做其他处理
内容的提问来源于stack exchange,提问作者Somanshu
相关产品推荐
相关产品推荐

