Преобразование списка с элементами разного размера в фрейм данных в R

#r

#r

Вопрос:

Я уже некоторое время борюсь с этой ошибкой, поэтому мне было интересно, знает ли кто-нибудь, как я могу это сделать?

У меня есть список в R, содержащий ~ 10 подсписков (прошу прощения, если я использую неправильную терминологию). В целом, мой объект выглядит так:

 head(list)

[[1]]
[[1]]$`LISTNAME1`
[1] "item1"     "item2"       "item3"       "item4"   

[[2]]
[[2]]$`LISTNAME2`
[1] "item2"   "item3"     "item2109"   

[...]
    
[[10]]
[[10]]$`LISTNAME10`
[1] "item3"   "item213199"     "item291212"   
 

Другими словами, каждый подсписок в списке содержит разные длины и может содержать или не содержать разные элементы. Что я хочу сделать, так это преобразовать это во фрейм данных, где один столбец содержит имя списка в предыдущем объекте, а второй столбец содержит элементы, разделенные одним пробелом. Пример:

 LISTNAME1        item1 item2 item3 item4
LISTNAME2        item2 item3 item2109 
...
LISTNAME10       item3 item213199 item291212 
 

Ранее это работало с использованием чего-то вроде:

 everything_df <- plyr::ldply(everything, rbind)
 

Плюс некоторый последующий код для удаления значений NA. Но по какой-то причине сейчас я получаю эту ошибку:

 Error in output[rng, lcols[[i]]] <- matrices[[i]] : 
  incorrect number of subscripts on matrix
 

Есть идеи о том, как я могу это исправить, или если есть лучшие способы сделать это?

Большое спасибо!

Комментарии:

1. Вы просто хотите paste объединить значения «item ##»?

2. У вас несколько столбцов или один столбец

3. Да, элементы каждого «подсписка» будут вставлены вместе в одну ячейку в конечном выходном фрейме данных.

4. stack(rapply(lst1, paste, collapse = " ")) или stack(rapply(lst1, toString)) , если вы хотите, чтобы они были разделены запятыми.

Ответ №1:

Мы можем использовать map with enframe для возврата tibble с первым столбцом name list элемента и вторым столбцом a list

 library(dplyr)
library(tibble)
library(purrr)
library(stringr)
map_dfr(lst1, enframe)
 

Если нам нужно, чтобы paste list элементы вместе

 map_dfr(lst1, ~ enframe(.x) %>%
                  mutate(value = map_chr(value, str_c, collapse=", ")))
 

-вывод

 # A tibble: 2 x 2
#  name      value                     
#   <chr>     <chr>                     
#1 LISTNAME1 item1, item2, item3, item4
#2 LISTNAME2 item2, item3, item32109   
 

данные

 lst1 <- list(list(LISTNAME1 = c("item1", "item2", "item3", "item4")), 
     list(LISTNAME2 = c("item2", "item3", "item32109")))
 

Комментарии:

1. Привет @akrun, большое спасибо за это! Первая часть кода работает очень хорошо для моих данных! map_dfr(lst1, enframe) , но второй бит, который форматирует мои результаты, чтобы не показывать строки, похожие на векторы (например c("item1", "item2", "item3") ), не работает. Он показывает: Error in as_mapper(.f, ...) : object 'str_c' not found . Я все еще изучаю это! Но большое спасибо, это помогает!!

2. @RodrigoDuarte забыл добавить library(stringr) now, он должен работать для вас

3. Оооо, это было оно! Спасибо, это сработало! Это тоже можно было исправить, используя предложение @A5C1D2H2I1M1N2O1R2T1: stack(rapply(lst1, paste, collapse = " "))

4. Вы также можете использовать library(tidyverse) . Он загружает purrr, magritirr, dplyr, string, ggplot, ….

Ответ №2:

Вы можете unlist объединить данные на одном уровне и объединить их в одну строку, разделенную запятыми.

 result <- stack(sapply(unlist(lst1, recursive = FALSE), toString))[2:1]