R:如何根据一项完全匹配和一项最接近(日期)匹配来合并数据帧?

时间:2018-07-27 12:49:18

标签: r merge match

现实生活中的问题:我有研究志愿者抽血的测试结果。我想将这些结果与志愿者的人口统计和调查数据合并,但是其中许多是在不同的日期(跨年)进行多次研究的。因此,调查数据行必须与测试结果的受试者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。

2 个答案:

答案 0 :(得分:3)

可以使用滚动连接到“最近”来解决此问题,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

答案 1 :(得分:2)

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