You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pandas合并日期范围匹配DataFrame:保留不匹配行并填充Null

解决Pandas匹配费率时保留无匹配行并设为Null的问题

这是某日期区间匹配问题的后续需求:当交易DataFrame中存在费率DataFrame里无匹配Agentname的行,或交易日期不在对应Agentname+ProductType的费率日期区间内时,需保留这些行并将Agentname_rates列设为Null/NA值。

输入数据

费率表(Rates table)

Agentname ProductType  OldRate  NewRate StartDate   EndDate
0    VSFAAL       SPORTS      0.0     10.0 2020-11-05 2021-01-18
1    VSFAAL      APPAREL      0.0     35.0 2020-11-05 2022-05-03
2    VSFAAL       SPORTS     10.0     15.0 2021-01-18 2022-05-03
3  VSFAALJS       SPORTS      0.0     10.0 2020-11-07 2022-05-03
4  VSFAALJS      APPAREL      0.0     15.0 2020-11-07 2021-11-09
5  VSFAALJS      APPAREL     15.0      5.0 2021-11-09 2022-05-03

交易表(Transactions table)

Date  Sales Agentname ProductType
0 2020-12-01 08:00:02  100.0    VSFAAL       SPORTS
1 2022-03-01 08:00:09   99.0    VSFAAL      APPAREL
2 2022-03-01 08:00:14   75.0    VSFAAL       SPORTS
3 2021-05-01 08:00:39   67.0  VSFAALJS       SPORTS
4 2020-05-01 08:00:56  160.0  VSFAALJS      APPAREL
5 2021-05-01 08:00:56   65.0  VSFAALJS      APPAREL
6 2021-06-03 09:07:33   55.0  VSRANDOM       SPORTS

原代码问题

你提供的代码在合并后直接筛选符合日期条件的行,导致不符合条件(无匹配Agent、日期不在区间内)的行被丢弃,而非保留并设为Null。

解决方案

方法1:高效合并筛选法(适合大数据量)

先统一日期类型,通过左连接保留所有交易行,再筛选日期匹配的费率并映射回原表:

import pandas as pd

# 1. 加载并转换日期格式
# 费率表
rates_data = {
    'Agentname': ['VSFAAL', 'VSFAAL', 'VSFAAL', 'VSFAALJS', 'VSFAALJS', 'VSFAALJS'],
    'ProductType': ['SPORTS', 'APPAREL', 'SPORTS', 'SPORTS', 'APPAREL', 'APPAREL'],
    'OldRate': [0.0, 0.0, 10.0, 0.0, 0.0, 15.0],
    'NewRate': [10.0, 35.0, 15.0, 10.0, 15.0, 5.0],
    'StartDate': ['2020-11-05', '2020-11-05', '2021-01-18', '2020-11-07', '2020-11-07', '2021-11-09'],
    'EndDate': ['2021-01-18', '2022-05-03', '2022-05-03', '2022-05-03', '2021-11-09', '2022-05-03']
}
df_rates = pd.DataFrame(rates_data)
df_rates['StartDate'] = pd.to_datetime(df_rates['StartDate'])
df_rates['EndDate'] = pd.to_datetime(df_rates['EndDate'])

# 交易表
trans_data = {
    'Date': ['2020-12-01 08:00:02', '2022-03-01 08:00:09', '2022-03-01 08:00:14', '2021-05-01 08:00:39', '2020-05-01 08:00:56', '2021-05-01 08:00:56', '2021-06-03 09:07:33'],
    'Sales': [100.0, 99.0, 75.0, 67.0, 160.0, 65.0, 55.0],
    'Agentname': ['VSFAAL', 'VSFAAL', 'VSFAAL', 'VSFAALJS', 'VSFAALJS', 'VSFAALJS', 'VSRANDOM'],
    'ProductType': ['SPORTS', 'APPAREL', 'SPORTS', 'SPORTS', 'APPAREL', 'APPAREL', 'SPORTS']
}
df_trans = pd.DataFrame(trans_data)
df_trans['Date'] = pd.to_datetime(df_trans['Date'])

# 2. 左连接合并,保留所有交易行
merged = df_trans.merge(df_rates, on=['Agentname', 'ProductType'], how='left')

# 3. 筛选交易日期在费率区间内的行
mask = (merged['Date'] >= merged['StartDate']) & (merged['Date'] <= merged['EndDate'])

# 4. 将匹配的费率映射回原交易表,无匹配则为NaN
df_trans['Agentname_rates'] = merged[mask].groupby(merged[mask].index)['NewRate'].first()

# 查看结果
print(df_trans)

方法2:逐行匹配法(适合小数据量,逻辑直观)

使用apply逐行查找对应Agent和Product的匹配费率:

import pandas as pd

# (省略数据加载和日期转换步骤,同上)

def get_matching_rate(row):
    # 筛选当前行对应的Agent和Product的费率记录
    filtered_rates = df_rates[(df_rates['Agentname'] == row['Agentname']) & 
                              (df_rates['ProductType'] == row['ProductType'])]
    # 找到日期在区间内的费率
    match = filtered_rates[(filtered_rates['StartDate'] <= row['Date']) & 
                           (filtered_rates['EndDate'] >= row['Date'])]
    # 返回匹配的NewRate,无匹配则返回None(自动转为NaN)
    return match['NewRate'].iloc[0] if not match.empty else None

# 生成Agentname_rates列
df_trans['Agentname_rates'] = df_trans.apply(get_matching_rate, axis=1)

# 查看结果
print(df_trans)

期望输出

执行后将得到符合要求的结果:

Date  Sales Agentname ProductType  Agentname_rates
0 2020-12-01 08:00:02  100.0    VSFAAL       SPORTS             10.0
1 2022-03-01 08:00:09   99.0    VSFAAL      APPAREL             35.0
2 2022-03-01 08:00:14   75.0    VSFAAL       SPORTS             15.0
3 2021-05-01 08:00:39   67.0  VSFAALJS       SPORTS             10.0
4 2020-05-01 08:00:56  160.0  VSFAALJS      APPAREL              NaN
5 2021-05-01 08:00:56   65.0  VSFAALJS      APPAREL             15.0
6 2021-06-03 09:07:33   55.0  VSRANDOM       SPORTS              NaN

内容的提问来源于stack exchange,提问作者jagabee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 05:54:58