如何有条件地在列对上加入数据框?

时间:2017-07-11 09:27:19

标签: r dplyr

我有两个df

d1 <- data_frame(name=c('Mike','Carl','Joe', 'Mike'), 
           id=c(1,2,NA,1), 
           id2=c('a',NA,'c','a'),
           dateT=as.Date('2017-05-01','2017-05-01','2017-05-01','2016-05-01'))


   # A tibble: 4 x 4
   name    id   id2      dateT
  <chr> <dbl> <chr>     <date>
1  Mike     1     a 2017-05-01
2  Carl     2  <NA> 2017-05-01
3   Joe    NA     c 2017-05-01
4  Mike     1     a 2016-05-01

d2 <- data_frame(value=c(T, T, F, T,F), 
                 id=c(1,2,3,1,4), 
                 id2=c('a','b','c','a','d'),
                 dateT=as.Date('2017-05-01','2017-05-01','2017-05-01', '2016-05-01','2016-05-01'))
# A tibble: 5 x 4
  value    id   id2      dateT
  <lgl> <dbl> <chr>     <date>
1  TRUE     1     a 2017-05-01
2  TRUE     2     b 2017-05-01
3 FALSE     3     c 2017-05-01
4  TRUE     1     a 2016-05-01
5 FALSE     4     d 2016-05-01

我正在尝试加入d2 d1 dateTiddate id2和{{ 1}}取决于哪一个可用。 最后,我希望得到d2的所有记录(它们是否匹配),并附上d1中与d2匹配的所有列。

到目前为止我所拥有的是

d2 %>% 
  inner_join(d1, by=c('id'='id', 'dateT'='dateT'))



 # A tibble: 5 x 6
  value    id id2.x      dateT  name id2.y
  <lgl> <dbl> <chr>     <date> <chr> <chr>
1  TRUE     1     a 2017-05-01  Mike     a
2  TRUE     2     b 2017-05-01  Carl  <NA>
3 FALSE     3     c 2017-05-01  <NA>  <NA>
4  TRUE     1     a 2016-05-01  Mike     a
5 FALSE     4     d 2016-05-01  <NA>  <NA>

有两个问题:

  1. 我只想从name附加d1,因为在我的情况下,id2.y始终会成为id2.x的一部分(我只想保留) id2.x因为它总是最完整的。我知道我可以稍后删除列,但我想知道dplyr是否有任何功能只能保留第一个数据帧中存在重复列名的列

  2. id2

  3. 时,我不知道如何有条不紊地查看is.na(id)==T

    预期输出如下:

    # A tibble: 5 x 6
      value    id   id2      dateT  name 
      <lgl> <dbl> <chr>     <date> <chr> 
    1  TRUE     1     a 2017-05-01  Mike 
    2  TRUE     2     b 2017-05-01  Carl 
    3 FALSE     3     c 2017-05-01   Joe 
    4  TRUE     1     a 2016-05-01  Mike 
    5 FALSE     4     d 2016-05-01  <NA> 
    

2 个答案:

答案 0 :(得分:1)

尝试:

library(dplyr)

d1 <- data_frame(name=c('Mike','Carl','Joe', 'Mike'), 
                 id=c(1,2,NA,1), 
                 id2=c('a',NA,'c','a'),
                 dateT=as.Date(c('2017-05-01','2017-05-01','2017-05-01','2016-05-01')))
# add combine-"c" !!

d2 <- data_frame(value=c(T, T, F, T,F), 
                 id=c(1,2,3,1,4), 
                 id2=c('a','b','c','a','d'),
                 dateT=as.Date(c('2017-05-01','2017-05-01','2017-05-01', '2016-05-01','2016-05-01')))
# add combine-"c" !!

left_join(d2,
          d1 %>%
            select(name, id, dateT) %>%
            rename(name1=name),
          by=c("id", "dateT")) %>%
  left_join(d1 %>%
              select(name, id2, dateT) %>%
              rename(name2=name),
            by=c("id2", "dateT")) %>%
  transmute(value, id, id2, dateT, 
            name=ifelse(is.na(name1),name2,name1))

答案 1 :(得分:1)

这个怎么样?

# first join by id, dropping id2
join1 = select(d1, -id2) %>%
    inner_join(d2, ., by=c("dateT", "id"))
# now take what couldn't be joined with id,
# drop id, join by id2, + left join to keep the remainder
join2 = d2 %>%
    anti_join(d1, by=c("dateT", "id")) %>%
    left_join(select(d1, -id), by=c("dateT", "id2"))

bind_rows(join1, join2)

# A tibble: 5 x 5
  value    id   id2      dateT  name
  <lgl> <dbl> <chr>     <date> <chr>
1  TRUE     1     a 2017-05-01  Mike
2  TRUE     2     b 2017-05-01  Carl
3  TRUE     1     a 2016-05-01  Mike
4 FALSE     4     d 2016-05-01  <NA>
5 FALSE     3     c 2017-05-01   Joe

请注意,只有当id2id时,此代码才会在id加入失败时尝试使用NA。 坦率地说,我的方法需要三个连接,所以在一个庞大的数据集上,重新编码id变量可能会更快 - 但如果不知道它在数据中意味着什么,这很难做到。