替换plyr::cbind.填写dplyr?
Replacement of plyr::cbind.fill in dplyr?
如果这个问题很初级,我深表歉意,但我一直在网上搜索,似乎找不到简单的解决方案。
我目前有一个 R 对象列表(命名向量或 1 个变量的数据帧,我可以使用其中任何一个),我想将它们加入 1 个大数据帧,每个唯一行有 1 行 name/rowname , 以及原始列表中每个元素的 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")))
我希望输出如下所示:
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
我不介意填充值是 NA 还是 0(最终我想要 0,但这很容易解决)。
我几乎肯定 plyr::cbind.fill
确实做到了这一点,但我一直在脚本的其余部分使用 dplyr,我认为同时使用两者不是一个好主意。 dplyr::bind_cols
似乎不适用于不同长度的向量。我知道这里有人问过一个非常相似的问题:
但正如我所提到的,这个解决方案实际上似乎并不奏效。 dplyr::full_join
也没有,甚至包裹在 do.call
中。对此是否有直接的解决方案,或者是编写自定义函数的唯一解决方案?
我们可以将行名转换为具有 rownames_to_column
的列,然后 rename
第二列,将 list
元素与 bind_rows
绑定,并重塑为 'wide' 和 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')
下面是一些 purrr
和 dplyr
函数的方法。创建列名来表示每个数据框——因为每个数据框只有一列,所以使用 setNames
很容易,但是如果有更多列,您可以使用 dplyr::rename
。根据原始行名对整个列表进行全连接,并用 0.
填充 NA
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
另一个 purrr
和 dplyr
选项可以是:
l1 %>%
map2_dfr(.x = ., .y = names(.), ~ setNames(.x, .y) %>%
rownames_to_column()) %>%
group_by(rowname) %>%
summarise_all(~ ifelse(all(is.na(.)), NA, first(na.omit(.))))
rowname df1 df2 df3 df4
<chr> <dbl> <dbl> <dbl> <dbl>
1 A 1 NA 9 4
2 B 2 2 NA NA
3 C 3 NA 3 NA
4 D NA 6 6 NA
5 E NA NA NA 12
如果这个问题很初级,我深表歉意,但我一直在网上搜索,似乎找不到简单的解决方案。
我目前有一个 R 对象列表(命名向量或 1 个变量的数据帧,我可以使用其中任何一个),我想将它们加入 1 个大数据帧,每个唯一行有 1 行 name/rowname , 以及原始列表中每个元素的 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")))
我希望输出如下所示:
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
我不介意填充值是 NA 还是 0(最终我想要 0,但这很容易解决)。
我几乎肯定 plyr::cbind.fill
确实做到了这一点,但我一直在脚本的其余部分使用 dplyr,我认为同时使用两者不是一个好主意。 dplyr::bind_cols
似乎不适用于不同长度的向量。我知道这里有人问过一个非常相似的问题:dplyr::full_join
也没有,甚至包裹在 do.call
中。对此是否有直接的解决方案,或者是编写自定义函数的唯一解决方案?
我们可以将行名转换为具有 rownames_to_column
的列,然后 rename
第二列,将 list
元素与 bind_rows
绑定,并重塑为 'wide' 和 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')
下面是一些 purrr
和 dplyr
函数的方法。创建列名来表示每个数据框——因为每个数据框只有一列,所以使用 setNames
很容易,但是如果有更多列,您可以使用 dplyr::rename
。根据原始行名对整个列表进行全连接,并用 0.
NA
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
另一个 purrr
和 dplyr
选项可以是:
l1 %>%
map2_dfr(.x = ., .y = names(.), ~ setNames(.x, .y) %>%
rownames_to_column()) %>%
group_by(rowname) %>%
summarise_all(~ ifelse(all(is.na(.)), NA, first(na.omit(.))))
rowname df1 df2 df3 df4
<chr> <dbl> <dbl> <dbl> <dbl>
1 A 1 NA 9 4
2 B 2 2 NA NA
3 C 3 NA 3 NA
4 D NA 6 6 NA
5 E NA NA NA 12