R:使用数据框A中的值从填充数据框B中的行之前的日期开始

时间:2014-11-26 15:19:22

标签: r join dataframe

这可能非常复杂,我怀疑需要先进的知识。我现在有两种不同类型的data.frames需要合并:

数据:

Dataframe A:

按患者ID列出所有输血日期。每次输血都由一个单独的行代表,患者可以进行多次输血。不同的患者可以在同一天进行输血。

Patient ID Transfusion.Date
1          01/01/2000
1          01/30/2000
2          04/01/2003
3          04/01/2003

B类数据框包含其他日期的测试结果,也包括患者ID:

Patient ID  Test.Date   Test.Value
1           11/30/1999   negative
1           01/15/2000   700 copies/uL
1           01/27/2000   900 copies/uL
2           03/30/2003   negative

我想要的是具有相同行数的Dataframe A(每次输入为1),并将最新的Test.Value作为单独的列。每个输血日期应该具有与输血最密切(之前)进行的测试的测试结果。

期望的输出:

- >

Patient ID Transfusion.Date Pre.Transfusion.Test
1          01/01/2000       negative
1          01/30/2000       900 copies/ul
2          04/01/2003       negative
3          04/01/2003       NA

我认为一般策略是按患者ID对data.frames进行子集化。然后获取患者1的所有输血日期,检查哪个结果最接近每个元素的所有可用test_dates,然后返回最接近的值。

如何解释R来做到这一点?

编辑1 :以下是这些示例的R代码

df_A <- data.frame(MRN = c(1,1,2,3), 
                   Transfusion.Date = as.Date(c('01/01/2000', '01/30/2000', 
                   '04/01/2003','04/01/2003'),'%m/%d/%Y')) 

df_B <- data.frame(MRN = c(1,1,1,2), 
                   Test.Date = as.Date(c('11/30/1999', '01/15/2000', '01/27/2000', 
                   '03/30/2003'),'%m/%d/%Y'), Test.Result = c('negative', 
                   '700 copies/ul','900 copies/ul','negative'))

编辑2:

为了澄清,结果数据应为:患者A在第X天和第Y天接受输血(对于df_A)。在第X天输血之前,他最近的测试结果是X(最接近第一次输血的测试日期,在df_B中)。在第Y天输血之前,他最近的测试结果是Y(第二次输血之前,也是df_B。df_B还包含一堆其他测试日期,最终输出不需要。

3 个答案:

答案 0 :(得分:5)

在这里使用data.table的滚动连接:

require(data.table)
setkey(setDT(df_A), MRN, Transfusion.Date)
setkey(setDT(df_B), MRN, Test.Date)

df_B[df_A, roll=TRUE]
#    MRN  Test.Date   Test.Result
# 1:   1 2000-01-01      negative
# 2:   1 2000-01-30 900 copies/ul
# 3:   2 2003-04-01      negative
# 4:   3 2003-04-01            NA
  • setDT通过引用将data.frame转换为data.table(无需任何额外复制)。这会导致df_Adf_B现在成为data.tables。

  • setkey按我们提供的列对data.table进行排序,并将标记这些列作为关键列,这样我们就可以使用二进制搜索< / em>基于联接。

  • 我们在关键列上执行x[i]表单的连接,i的每一行,x的匹配行(如果有的话,其他NA)与i的行一起返回。这就是我们所说的 equi-join 。通过添加roll = TRUE,如果不匹配,最后一次观察将继续进行(LOCF)。这就是我们所说的滚动连接。按升序排序(由于setkey())确保最后一次观察是最近的日期。

HTH

答案 1 :(得分:0)

 dfLast <- df_B[ df_B$Test.Date %in% 
  as.Date( tapply(df_B$Test.Date, df_B$MRN, tail,1),"1970-01-01"), ]
 merge(df_A, dfLast, by=c(1:2,1:2) ,all.y=TRUE)
  MRN Transfusion.Date   Test.Result
1   1       2000-01-27 900 copies/ul
2   2       2003-03-30      negative

编辑。有一些逻辑错误和一些sytactic错误。 tapply返回日期的整数值,正如您所指出的那样,我在数据缩减步骤中使用了错误的列名。

答案 2 :(得分:0)

好的,谢谢大家的帮助。我花了很多辛劳,血,汗和眼泪,但这是我提出的解决方案:

  1. 合并两个数据框:
  2.   

    df_AB&lt; - merge(df_A,df_B,all.x = T)

    df_AB:

      MRN Transfusion.Date  Test.Date   Test.Result
    1   1       2000-01-01 1999-11-30      negative
    2   1       2000-01-01 2000-01-15 700 copies/ul
    3   1       2000-01-01 2000-01-27 900 copies/ul
    4   1       2000-01-30 1999-11-30      negative
    5   1       2000-01-30 2000-01-15 700 copies/ul
    6   1       2000-01-30 2000-01-27 900 copies/ul
    7   2       2003-04-01 2003-03-30      negative
    8   3       2003-04-01       <NA>          <NA>
    

    使用dplyr

    df_tests <- df_AB %>% 
      group_by(MRN, Transfusion.Date) %>%
      mutate(Time.Difference = Transfusion.Date - Test.Date) %>%
      filter(Time.Difference > 0) %>%
      arrange(Time.Difference) %>%
      summarize(Test.Date = Test.Date[1], Test.Result = Test.Result[1])
    

    df_tests:

      MRN Transfusion.Date  Test.Date Test.Result
    1   1       2000-01-01 1999-11-30    negative
    2   1       2000-01-30 1999-11-30    negative
    3   2       2003-04-01 2003-03-30    negative
    

    using merge again for MRN3:

    df_desired <- merge(df_A, df_tests, all.x = T)
    
      MRN Transfusion.Date  Test.Date   Test.Result
    1   1       2000-01-01 1999-11-30      negative
    2   1       2000-01-30 2000-01-27 900 copies/ul
    3   2       2003-04-01 2003-03-30      negative
    4   3       2003-04-01       <NA>          <NA>