【问题标题】:How to extract date based on condition over two different variables in R如何根据R中两个不同变量的条件提取日期
【发布时间】:2015-08-07 18:16:42
【问题描述】:

我有一个包含 100 个观察结果的数据集,其中包含患者 ID、药物代码、处方日期。我想创建一个新列“索引日期”,这是患者第三次换药的日期。

PatientID   DrugCode    Prescriptiondate   
A1  3   07-08-2014   
A1  3   08-09-2014   
A1  7   19-09-2014   
A1  5   30-09-2014  
A2  4   11-07-2014  
A2  4   21-07-2014  
A2  3   13-08-2014  
A2  5   26-08-2014  
A2  5   30-09-2014  
A3  2   16-08-2014  
A3  3   17-09-2014  
A4  5   08-06-2014  
A4  5   29-06-2014  
A4  6   20-08-2014  
A4  6   24-09-2014  
A4  4   22-10-2014  
A4  4   25-10-2014   

数据集应如下所示:

PatientID   DrugCode    Prescriptiondate    IndexDate  
A1  3   07-08-2014  30-09-2014  
A1  3   08-09-2014  30-09-2014  
A1  7   19-09-2014  30-09-2014  
A1  5   30-09-2014  30-09-2014  
A2  4   11-07-2014  26-08-2014  
A2  4   21-07-2014  26-08-2014  
A2  3   13-08-2014  26-08-2014  
A2  5   26-08-2014  26-08-2014  
A2  5   30-09-2014  26-08-2014  
A3  2   16-08-2014  NA  
A3  3   17-09-2014  NA  
A4  5   08-06-2014  22-10-2014  
A4  5   29-06-2014  22-10-2014  
A4  6   20-08-2014  22-10-2014  
A4  6   24-09-2014  22-10-2014  
A4  4   22-10-2014  22-10-2014  
A4  4   25-10-2014  22-10-2014 

在上述病例中,患者A1和A2分别于2014年9月30日和2014年8月26日第三次换药为药物5;A3未第三次换药,A4已于22日换药4 -10-2014,因此索引日期应分别为 30-09-2014、26-08-2014、NA、22-10-2014。

请如果有人可以协助编写此类问题的代码。

【问题讨论】:

    标签: r date group-by conditional-statements


    【解决方案1】:

    这是一个可能的dplyr 解决方案:

    df %>% group_by(PatientID) %>% mutate(IndexDate = Prescriptiondate[match(unique(DrugCode)[3], DrugCode)])
    # Source: local data frame [17 x 4]
    # Groups: PatientID
    # 
    #    PatientID DrugCode Prescriptiondate  IndexDate
    # 1         A1        3       07-08-2014 30-09-2014
    # 2         A1        3       08-09-2014 30-09-2014
    # 3         A1        7       19-09-2014 30-09-2014
    # 4         A1        5       30-09-2014 30-09-2014
    # 5         A2        4       11-07-2014 26-08-2014
    # 6         A2        4       21-07-2014 26-08-2014
    # 7         A2        3       13-08-2014 26-08-2014
    # 8         A2        5       26-08-2014 26-08-2014
    # 9         A2        5       30-09-2014 26-08-2014
    # 10        A3        2       16-08-2014         NA
    # 11        A3        3       17-09-2014         NA
    # 12        A4        5       08-06-2014 22-10-2014
    # 13        A4        5       29-06-2014 22-10-2014
    # 14        A4        6       20-08-2014 22-10-2014
    # 15        A4        6       24-09-2014 22-10-2014
    # 16        A4        4       22-10-2014 22-10-2014
    # 17        A4        4       25-10-2014 22-10-2014
    

    我想这和data.table是一样的想法

    dt[, IndexDate := Prescriptiondate[match(unique(DrugCode)[3], DrugCode)], PatientID]
    #    PatientID DrugCode Prescriptiondate  IndexDate
    #  1:        A1        3       07-08-2014 30-09-2014
    #  2:        A1        3       08-09-2014 30-09-2014
    #  3:        A1        7       19-09-2014 30-09-2014
    #  4:        A1        5       30-09-2014 30-09-2014
    #  5:        A2        4       11-07-2014 26-08-2014
    #  6:        A2        4       21-07-2014 26-08-2014
    #  7:        A2        3       13-08-2014 26-08-2014
    #  8:        A2        5       26-08-2014 26-08-2014
    #  9:        A2        5       30-09-2014 26-08-2014
    # 10:        A3        2       16-08-2014         NA
    # 11:        A3        3       17-09-2014         NA
    # 12:        A4        5       08-06-2014 22-10-2014
    # 13:        A4        5       29-06-2014 22-10-2014
    # 14:        A4        6       20-08-2014 22-10-2014
    # 15:        A4        6       24-09-2014 22-10-2014
    # 16:        A4        4       22-10-2014 22-10-2014
    # 17:        A4        4       25-10-2014 22-10-2014
    

    match 之所以有效,是因为它一旦找到匹配项就会停止。因此,如果一种药物使用多天或多天,它不会改变结果。我们寻找第三次更改 DrugCode 的第一个实例。 unique 有效,因为它按照它们出现的顺序排列它的值。所以unique(x)[3] 将给出该值的第三个变化。

    【讨论】:

    • 感谢您的帮助..我能够得到想要的结果。
    【解决方案2】:

    这是一个基本的 R 解决方案,无耻地窃取了 Pierre Lafortune 的绝妙匹配独特想法:

    df <- data.frame(PatientID=c('A1','A1','A1','A1','A2','A2','A2','A2','A2','A3','A3','A4','A4','A4','A4','A4','A4'),DrugCode=c(3,3,7,5,4,4,3,5,5,2,3,5,5,6,6,4,4),Prescriptiondate=as.Date(c('07-08-2014','08-09-2014','19-09-2014','30-09-2014','11-07-2014','21-07-2014','13-08-2014','26-08-2014','30-09-2014','16-08-2014','17-09-2014','08-06-2014','29-06-2014','20-08-2014','24-09-2014','22-10-2014','25-10-2014'),'%d-%m-%Y'));
    df$IndexDate <- do.call('c',by(df,df$PatientID,function(g) rep(g$Prescriptiondate[match(unique(g$DrugCode)[3],g$DrugCode)],nrow(g))));
    df;
    ##    PatientID DrugCode Prescriptiondate  IndexDate
    ## 1         A1        3       2014-08-07 2014-09-30
    ## 2         A1        3       2014-09-08 2014-09-30
    ## 3         A1        7       2014-09-19 2014-09-30
    ## 4         A1        5       2014-09-30 2014-09-30
    ## 5         A2        4       2014-07-11 2014-08-26
    ## 6         A2        4       2014-07-21 2014-08-26
    ## 7         A2        3       2014-08-13 2014-08-26
    ## 8         A2        5       2014-08-26 2014-08-26
    ## 9         A2        5       2014-09-30 2014-08-26
    ## 10        A3        2       2014-08-16       <NA>
    ## 11        A3        3       2014-09-17       <NA>
    ## 12        A4        5       2014-06-08 2014-10-22
    ## 13        A4        5       2014-06-29 2014-10-22
    ## 14        A4        6       2014-08-20 2014-10-22
    ## 15        A4        6       2014-09-24 2014-10-22
    ## 16        A4        4       2014-10-22 2014-10-22
    ## 17        A4        4       2014-10-25 2014-10-22
    

    【讨论】:

    • 我在运行代码时收到错误消息“do.call(c, by(df, df$PatientID, function(g) rep(g$Prescriptiondate[match(unique(g)) $DrugCode)[3], : 'what' 必须是字符串或函数"
    • @Mayur 您可能在某个时候分配了c,这掩盖了base::c() 功能。幸运的是,do.call() 也接受一个字符串作为函数参数,所以'c' 应该可以工作。请尝试我编辑的代码,让我知道它是否有效。 (另一种方法是对其进行限定,即do.call(base::c,...)。)
    • 感谢您的帮助..我能够得到想要的结果。
    最近更新 更多