【问题标题】:R: How do I merge data frames based on one exact match and one nearest (date) match?R:如何根据一个完全匹配和一个最近(日期)匹配合并数据帧?
【发布时间】:2018-07-27 12:49:17
【问题描述】:

现实生活中的问题:我有研究志愿者抽血的测试结果。我想将这些结果与志愿者的人口统计和调查数据合并,但其中许多人在不同日期(跨年)进行了多项研究。因此,调查数据行必须与测试结果对象 ID 完全匹配,并尽可能接近抽血日期(可能准确或相差几天或几周)。此外,一些受试者有来自不同抽血日期的多个验血结果。

玩具示例:

set.seed(905)  

#The "test result" data frame:
df.1 <- tibble(id = c('A1', 'A1', 'A2', 'A3', 'A3'),
           draw.date = as.Date(c("2013-01-19", "2015-03-22", "2013-01-19",
                               "2014-04-23", "2016-05-07")),
           result1 = rnorm(5))  

#The "survey results" data frame:
df.2 <- tibble(id = c('A1', 'A1', 'B1', 'A2', 'A3'),
           test.date = as.Date(c("2013-02-01", "2015-02-28", "2017-01-26",
                               "2014-04-23", "2016-05-06")),
           survey1 = 101:105,
           survey2 = letters[1:5])  

#The desired final data frame:
desired <- tibble(id = df.1$id,
              draw.date = df.1$draw.date,
              result1 = df.1$result1,
              test.date = as.Date(c("2013-02-01", "2015-02-28", "2014-04-23",
                                  "2016-05-06", "2016-05-06")),
              survey1 = c(101, 102, 104, 105, 105),
              survey2 = c('a', 'b', 'd', 'e', 'e'))  

评论:
我无法让 R 仅在具有匹配 ID 的人中找到最接近的日期。换句话说,阻止它针对所有 test.dates 检查 draw.date 并将其限制为仅具有匹配 ID 的 test.dates。

我已经搜索过之前的问题,但在两个具有不同日期的数据框中(次要匹配变量),它们都没有重复的 ID(主要匹配变量)。我找不到任何适合我的东西。

我更喜欢 dplyr 解决方案,但我愿意接受任何可行的方法。我不熟悉 data.table 包,所以如果这是我唯一的选择,请慢慢引导我:)

注意:我现实生活中的 df.1 是 1524 obs x 22 vars,而 df.2 是 26802 obs x 7317 vars。

【问题讨论】:

    标签: r merge match


    【解决方案1】:

    dplyr 方法可以是

    library(dplyr)
    
    df.1 %>%
      left_join(df.2, by = "id") %>%
      mutate(date_diff = abs(difftime(draw.date, test.date, units = "days"))) %>%
      group_by(id, draw.date) %>%
      filter(date_diff == min(date_diff)) %>%
      select(-date_diff)
    

    给了

      id    draw.date  result1 test.date  survey1 survey2
    1 A1    2013-01-19   2.92  2013-02-01     101 a      
    2 A1    2015-03-22  -0.349 2015-02-28     102 b      
    3 A2    2013-01-19   0.382 2014-04-23     104 d      
    4 A3    2014-04-23   0.308 2016-05-06     105 e      
    5 A3    2016-05-07  -0.843 2016-05-06     105 e   
    

    【讨论】:

      【解决方案2】:

      这可以使用 滚动连接 到“最近”来解决,data.table

      library(data.table)   # version 1.11.4 used
      setDT(df.2)[, draw.date := test.date][setDT(df.1), on = .(id, draw.date), roll = "nearest"]
      
         id  test.date survey1 survey2  draw.date    result1
      1: A1 2013-02-01     101       a 2013-01-19  2.9201353
      2: A1 2015-02-28     102       b 2015-03-22 -0.3485295
      3: A2 2014-04-23     104       d 2013-01-19  0.3824341
      4: A3 2016-05-06     105       e 2014-04-23  0.3077772
      5: A3 2016-05-06     105       e 2016-05-07 -0.8427319
      

      为了比较,这里是 OP 的预期结果:

      desired
      
         id  draw.date    result1  test.date survey1 survey2
      1: A1 2013-01-19  2.9201353 2013-02-01     101       a
      2: A1 2015-03-22 -0.3485295 2015-02-28     102       b
      3: A2 2013-01-19  0.3824341 2014-04-23     104       d
      4: A3 2014-04-23  0.3077772 2016-05-06     105       e
      5: A3 2016-05-07 -0.8427319 2016-05-06     105       e
      

      【讨论】:

        猜你喜欢
        • 2019-02-28
        • 2018-11-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-09-20
        • 1970-01-01
        • 1970-01-01
        • 2014-09-20
        相关资源
        最近更新 更多