【问题标题】:R conditional joinR 条件连接
【发布时间】:2018-07-05 11:08:46
【问题描述】:

有没有办法在 R 中加入和更新列?示例:

tbl1 <- tibble(ID = LETTERS[1:3],
       VAL = rep(NA, 3),
       tbl1_df = list(tibble(A = rnorm(3),
                             B = rnorm(3))))

tbl2 <- tibble(ID = LETTERS[1:3],
               VAL = c(1, 2, 3),
               tbl2_df = list(tibble(A = rnorm(3),
                                     B = rnorm(3))))

tbl3 <- tibble(ID = LETTERS[1:3],
               VAL = c(1, 2, 3),
               tbl3_df = list(tibble(A = rnorm(3),
                                     B = rnorm(3))))

我想将这些 tibbles 连接在一起并使用具有值的表之一更新 VAL。表在 VAL 中始终具有相同的值,但我并不总是知道它们在哪个表中。是否可以强制 VAL 列在一起或将 VAL 列从存在值的小标题之一中保留?

答案应该是这样的,如前所述,VAL 列来自哪个表无关紧要,表具有相同的 VAL 或 NA。

tibble(ID = LETTERS[1:3],
                 VAL = c(1, 2, 3),
                 tbl1_df = list(tibble(A = rnorm(3),
                                       B = rnorm(3))),
                 tbl2_df = list(tibble(A = rnorm(3),
                                       B = rnorm(3))),
                 tbl3_df = list(tibble(A = rnorm(3),
                                       B = rnorm(3))))

# A tibble: 3 x 5
  ID      VAL tbl1_df          tbl2_df          tbl3_df         
  <chr> <dbl> <list>           <list>           <list>          
1 A        1. <tibble [3 x 2]> <tibble [3 x 2]> <tibble [3 x 2]>
2 B        2. <tibble [3 x 2]> <tibble [3 x 2]> <tibble [3 x 2]>
3 C        3. <tibble [3 x 2]> <tibble [3 x 2]> <tibble [3 x 2]>

【问题讨论】:

  • reduce(list(tbl1, tbl2, tbl3), full_join, by = "ID") %&gt;% select(ID, VAL, tbl1_df, tbl2_df, tbl3_df)
  • 我喜欢这个,但选择 VAL 恰好在示例中起作用。如前所述,我不知道哪些表填充了 VAL 列。也许我必须从那里争吵,如果没有别的。因为完全连接返回 VAL.x、VAL.y 和 VAL。

标签: r join conditional tibble


【解决方案1】:

这个怎么样?

library(purrr)

list(tbl1, tbl2, tbl3) %>% 
  reduce(full_join, by = "ID") %>%   #merge all tables
  select_if(~!all(is.na(.))) %>%     #drop columns having all NA value
  select(-starts_with("VAL."))       #keep only one 'VAL' column and drop remaining repetitive columns

给了

# A tibble: 3 x 5
  ID    tbl1_df          tbl2_df            VAL tbl3_df         
  <chr> <list>           <list>           <dbl> <list>          
1 A     <tibble [3 x 2]> <tibble [3 x 2]>  1.00 <tibble [3 x 2]>
2 B     <tibble [3 x 2]> <tibble [3 x 2]>  2.00 <tibble [3 x 2]>
3 C     <tibble [3 x 2]> <tibble [3 x 2]>  3.00 <tibble [3 x 2]>

【讨论】:

  • 谢谢,我想这样就可以了。我有 mutate(VAL= rowMeans(select(., starts_with("VAL")), na.rm = TRUE) 然后选择,但这很好。
【解决方案2】:

在 Jaap 的 cmets 的基础上,您可以使用 purrr 的 reduce 命令和 dplyr 的 full_join 将 tibbles 组合成一个 tibble。 那么问题是如何获取存在的 VAL,而不是为 VAL 提供 3 列,但并非所有列都有数据。一个简单的方法是使用 dplyr 中的 coalesce 命令,它采用第一个非缺失值。此步骤中引入的一个问题是,如果数据类型均为 NA,则数据类型为 BOOLEAN,因此通过使用 as.numeric 来解决此问题。最后,删除后面添加字母的附加 VAL 列。

library(dplyr)
library(purrr)

reduce(list(tbl1, tbl2, tbl3), full_join, by = "ID") %>% # Combine the tibbles into a single tibble
  mutate(VAL= coalesce(as.numeric(VAL.x), as.numeric(VAL.y), as.numeric(VAL))) %>% # Create a variable for VAL which takes the first non missing using the coalesce function
  select(-starts_with("Val.")) # Delete the columns for VAL which were created when joining and have a name of VAL. and then a letter

【讨论】:

  • 虽然这个答案可能是正确且有用的,但最好在其中附上一些解释来解释它如何帮助解决问题。如果有更改(可能不相关)导致它停止工作并且用户需要了解它曾经是如何工作的,这在未来变得特别有用。
猜你喜欢
  • 2015-04-29
  • 2019-03-14
  • 2016-11-12
  • 2021-04-01
  • 2013-10-03
  • 2015-09-19
  • 2019-08-03
  • 2020-03-03
  • 1970-01-01
相关资源
最近更新 更多