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

如何在R中基于日期范围匹配获取药物数据(双场景规则)

没问题,我来帮你用 pandas 实现这个药物匹配需求,完全符合你说的两个场景逻辑。咱们一步步来:

1. 准备样本数据并转换日期格式

首先得把字符串格式的日期转成 datetime 类型,不然没法做时间范围的计算和匹配:

import pandas as pd

# 构建你的样本df1
df1 = pd.DataFrame({
    'PID': [123, 234, 345, 456],
    'Record_Date_1': ['22-04-1996', '16-06-1994', '18-09-2000', '20-02-2001'],
    'D1': [5.3, 6.8, 7.5, 8.5],
    'Record_Date_2': ['30-10-1996', '13-12-1994', '24-02-2001', '20-08-2001'],
    'D2': [5.4, 7.2, 8.9, 9.4]
})

# 构建你的样本df2
df2 = pd.DataFrame({
    'PID': [123, 123, 123, 234, 234, 345, 345, 456, 456],
    'Drug_Date': ['23-04-1996', '28-04-1996', '31-10-1996', '15-06-1994', '14-12-1994', '18-09-2000', '24-02-2001', '21-02-2001', '26-08-2001'],
    'Drugs': ['Biguanides', 'Sulphynureas', 'SGLT2', 'Insulin', 'Biguanides', 'DPP4-inhibitor', 'Incretin', 'Biguanides', 'Sulphynureas']
})

# 转换日期列为datetime类型,注意格式是dd-mm-yyyy
df1['Record_Date_1'] = pd.to_datetime(df1['Record_Date_1'], format='%d-%m-%Y')
df1['Record_Date_2'] = pd.to_datetime(df1['Record_Date_2'], format='%d-%m-%Y')
df2['Drug_Date'] = pd.to_datetime(df2['Drug_Date'], format='%d-%m-%Y')

2. 编写核心匹配函数

这个函数封装了你要求的两个场景逻辑:先尝试精确匹配,匹配失败就找目标日期前后指定范围内的最小药物日期:

def match_drugs(pid, target_date, df_drugs):
    # 筛选当前PID的所有药物记录
    pid_drugs = df_drugs[df_drugs['PID'] == pid].copy()
    
    # 场景1:精确匹配日期
    exact_match = pid_drugs[pid_drugs['Drug_Date'] == target_date]
    if not exact_match.empty:
        return (exact_match['Drug_Date'].iloc[0], exact_match['Drugs'].iloc[0])
    
    # 场景2:计算目标日期的范围(前7天到后45天)
    lower_bound = target_date - pd.Timedelta(days=7)
    upper_bound = target_date + pd.Timedelta(days=45)
    range_match = pid_drugs[(pid_drugs['Drug_Date'] >= lower_bound) & (pid_drugs['Drug_Date'] <= upper_bound)]
    
    # 找到范围内最早的药物日期
    if not range_match.empty:
        min_date_row = range_match.loc[range_match['Drug_Date'].idxmin()]
        return (min_date_row['Drug_Date'], min_date_row['Drugs'])
    
    # 兜底:如果没有匹配到任何记录(你的样本数据里没这种情况)
    return (pd.NaT, None)

3. 应用函数并整理结果

把函数应用到df1的每个随访日期,然后调整格式和列顺序,得到你要的输出:

# 处理Record_Date_1的药物匹配
df1[['Drug_Date1', 'D1_Drugs']] = df1.apply(
    lambda row: match_drugs(row['PID'], row['Record_Date_1'], df2),
    axis=1,
    result_type='expand'
)

# 处理Record_Date_2的药物匹配
df1[['Drug_Date2', 'D2_Drugs']] = df1.apply(
    lambda row: match_drugs(row['PID'], row['Record_Date_2'], df2),
    axis=1,
    result_type='expand'
)

# 把日期转回原来的字符串格式(dd-mm-yyyy)
date_cols = ['Record_Date_1', 'Record_Date_2', 'Drug_Date1', 'Drug_Date2']
df1[date_cols] = df1[date_cols].apply(lambda x: x.dt.strftime('%d-%m-%Y'))

# 调整列顺序和预期输出一致
output_cols = ['PID', 'Record_Date_1', 'D1', 'Record_Date_2', 'D2', 'Drug_Date1', 'D1_Drugs', 'Drug_Date2', 'D2_Drugs']
df1 = df1[output_cols]

# 打印最终结果
print(df1)

运行结果

执行后得到的结果和你给出的预期输出完全一致(注:预期里的sulphynureas是小写,原数据是大写,代码会保留原数据的大写格式,你可以根据需要调整大小写):

PIDRecord_Date_1D1Record_Date_2D2Drug_Date1D1_DrugsDrug_Date2D2_Drugs
12322-04-19965.330-10-19965.423-04-1996Biguanides31-10-1996SGLT2
23416-06-19946.813-12-19947.215-06-1994Insulin14-12-1994Biguanides
34518-09-20007.524-02-20018.918-09-2000DPP4-inhibitor24-02-2001Incretin
45620-02-20018.520-08-20019.421-02-2001Biguanides26-08-2001Sulphynureas

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 17:32:29