Преобразовать список списков в единую вложенную строку data.frame или tibble (R)

#r #list #tibble

#r #Список #tibble

Вопрос:

У меня есть вложенный список списков:

 data = list(a = list(1, 2, 3), b = list("foo"), c = list("toast", "onions"))
  

Как я могу преобразовать это в одну строку data.frame или tibble? Я бы хотел, чтобы списки с более чем одним элементом ( a и c здесь ) сохранялись как списки, а одноэлементный ( b ) был обычным значением.

Ожидаемый результат:

 # A tibble: 1 x 3
  a          b     c         
  <list>     <chr> <list>    
1 <list [3]> foo   <list [2]>
  

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

1. tibble::enframe(data) %>% tidyr::pivot_wider() ?

2. Да, это работает для меня, Ронак. Спасибо за вашу помощь. Каков наилучший способ затем преобразовать столбец b в обычный символьный столбец? Я пробовал ... %>% mutate(b = map(b, unlist)) , но это не меняет фактический тип столбца.

3. [Ronak] %>% tidyr::unnest(b) %>% tidyr::unnest(b)

4. Спасибо Ronak. Также работает, если я изменяю map map_chr , т.е. `… %>% mutate(b = map_chr(b, unlist))’.

Ответ №1:

Как насчет этого?

 > as_tibble_row(Map(function(x) ifelse(length(x)==1,unlist(x),list(x)),data))
# A tibble: 1 x 3
  a          b     c
  <list>     <chr> <list>
1 <list [3]> foo   <list [2]>
  

Ответ №2:

Вы можете использовать enframe pivot_wider

 tibble::enframe(data) %>% tidyr::pivot_wider() 
#      a          b          c         
#  <list>     <list>     <list>    
#1 <list [3]> <list [1]> <list [2]>
  

Чтобы получить длину одного столбца в виде вектора, мы можем добавить :

 library(dplyr)

tibble::enframe(data) %>% 
  tidyr::pivot_wider() %>%
  summarise(across(.fns = ~if(length(unlist(.)) == 1) unlist(.) else .))

#      a          b     c         
#  <list>     <chr> <list>    
#1 <list [3]> foo   <list [2]>
  

Ответ №3:

 data[] <- lapply(data, function(x) if (length(x) == 1) x[[1]] else list(x))
data.table::setDF(data)

# > str(data)
# 'data.frame': 1 obs. of  3 variables:
#  $ a:List of 1
#   ..$ :List of 3
#   .. ..$ : num 1
#   .. ..$ : num 2
#   .. ..$ : num 3
#  $ b: chr "foo"
#  $ c:List of 1
#   ..$ :List of 2
#   .. ..$ : chr "toast"
#   .. ..$ : chr "onions"
  

Ответ №4:

Одним из вариантов является создание набора данных из двух столбцов с aggregate помощью from base R

 aggregate(values ~ ind, stack(data), list)