Замена plyr :: cbind.fill в dplyr? - PullRequest
       27

Замена plyr :: cbind.fill в dplyr?

4 голосов
/ 05 февраля 2020

Я прошу прощения, если этот вопрос является элементарным, но я искал inte rnet, и я не могу найти простое решение.

В настоящее время у меня есть список объектов 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")))

И я хочу, чтобы выходные данные выглядели так:

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, похоже, не работает с векторами разной длины. Я знаю, что здесь был задан очень похожий вопрос: R: Есть ли хорошая замена plyr :: rbind.fill в dplyr? , но, как я уже говорил, это решение на самом деле не работает , dplyr::full_join, даже завернутый в do.call. Есть ли прямое решение для этого, или единственное решение для написания пользовательской функции?

Ответы [ 3 ]

4 голосов
/ 05 февраля 2020

Мы можем преобразовать имена строк в столбец с 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')
3 голосов
/ 05 февраля 2020

Вот способ с некоторыми purrr и dplyr функциями. Создайте имена столбцов для представления каждого фрейма данных - поскольку у каждого есть только один столбец, это легко сделать с setNames, но с большим количеством столбцов вы можете использовать dplyr::rename. Выполните полное объединение по всему списку на основе исходных имен строк и заполните NA s 0.

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
2 голосов
/ 05 февраля 2020

Еще одним вариантом 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...