在 dplyr 中替换 plyr::cbind.fill?

Tom*_*Tom 5 r plyr cbind dplyr

如果这个问题很初级,我深表歉意,但我一直在网上搜索,似乎找不到简单的解决方案。

我目前有一个 R 对象列表(命名为向量或 1 个变量的数据框,我可以使用任何一个),我想将它们加入 1 个大数据框,每个唯一名称/行名有 1 行,每个元素有 1 列在原始列表中。

我的起始列表如下所示:

l1 <- list(df1 = data.frame(c(1,2,3), row.names = c("A", "B", "C")), 
       df2 = data.frame(c(2,6), row.names = c("B", "D")),
       df3 = data.frame(c(3,6,9), row.names = c("C", "D", "A")),
       df4 = data.frame(c(4,12), row.names = c("A", "E")))
Run Code Online (Sandbox Code Playgroud)

我希望输出看起来像:

data.frame("df1" = c(1,2,3,NA,NA),
+            "df2" = c(NA,2,NA,6,NA),
+            "df3" = c(9,NA,3,6,NA),
+            "df4" = c(4,NA,NA,NA,12), row.names = c("A", "B", "C", "D", "E"))
  df1 df2 df3 df4
A   1  NA   9   4
B   2   2  NA  NA
C   3  NA   3  NA
D  NA   6   6  NA
E  NA  NA  NA  12
Run Code Online (Sandbox Code Playgroud)

我不介意填充值是 NA 还是 0(最终我想要 0 但这是一个简单的修复)。

我几乎肯定plyr::cbind.fill会这样做,但我一直在脚本的其余部分使用 dplyr,我认为同时使用两者并不是一个好主意。dplyr::bind_cols似乎不适用于不同长度的向量。我知道这里有人问了一个非常相似的问题:R:dplyr 中的 plyr::rbind.fill 是否有很好的替代品? 但正如我所提到的,这个解决方案实际上似乎不起作用。也没有dplyr::full_join,甚至包裹在do.call. 是否有一个简单的解决方案,或者是编写自定义函数的唯一解决方案?

akr*_*run 6

我们可以将行名转换为一列rownames_to_column,然后rename是第二列,用 绑定list元素bind_rows,然后用pivot_wider

library(dplyr)
library(tidyr)
library(purrr)
library(tibble)
map_dfr(l1, ~ rownames_to_column(.x, 'rn') %>% 
              rename_at(2, ~'v1'), .id = 'grp') %>%        
   pivot_wider(names_from = grp, values_from = v1) %>% 
   column_to_rownames('rn')
Run Code Online (Sandbox Code Playgroud)


cam*_*lle 6

这是一种具有一些purrrdplyr功能的方法。创建列名来表示每个数据框——因为每个数据框只有一列,这很容易使用setNames,但如果有更多列,您可以使用dplyr::rename。根据原始行名称对整个列表进行全连接,并NA用 0填充s。

library(dplyr)
library(purrr)

l1 %>%
  imap(~setNames(.x, .y)) %>%
  map(tibble::rownames_to_column) %>%
  reduce(full_join, by = "rowname") %>%
  mutate_all(tidyr::replace_na, 0)
#>   rowname df1 df2 df3 df4
#> 1       A   1   0   9   4
#> 2       B   2   2   0   0
#> 3       C   3   0   3   0
#> 4       D   0   6   6   0
#> 5       E   0   0   0  12
Run Code Online (Sandbox Code Playgroud)