Как работать со списками списков, когда первый индекс представляет строки?

Как я могу преобразовать список списков в DataFrame, где первым «слоем» списков должны быть строки?

myList = list(
    list(name="name1",num=20,dogs=list("dog1")),
    list(name="name2",num=13,dogs = list()),
    list(name="name3",num=5,dogs=list("dog2","dog4"))
)

Моя первая идея заключалась в том, чтобы исключить элементы в "третьем слое".

myUnList = sapply(myList,function(x){y=x;y$dogs = unlist(y$dogs);y})

Я могу приготовить блюдо

tibble(myUnList)
# A tibble: 3 x 1
    myUnList
      <list>
1 <list [3]>
2 <list [2]>
3 <list [3]>

Обратите внимание: если бы у меня было myList[[1]] для представления вектора name, это было бы просто, но у меня возникли проблемы с тем, как привести в порядок данные, представленные другим способом. Я думал об использовании purrr, чтобы «перевернуть» порядок.

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

# A tibble: 3 x 3
      names       num       dogs
     <list>    <list>     <list>
1 <chr [1]> <dbl [1]> <list [1]>
2 <chr [1]> <dbl [1]> <list [0]>
3 <chr [1]> <dbl [1]> <list [2]>

Существуют ли другие типы структур данных, поддерживающие записи различной длины?


person Freguglia    schedule 01.02.2018    source источник


Ответы (2)


Мы можем извлечь элемент списка, используя функцию map из пакета purrr, а затем создать новый тиббл, используя data_frame.

библиотека (тидиверс)

dat <- data_frame(name = map_chr(myList, "name"),
                  num = map_dbl(myList, "num"),
                  dogs = map(myList, "dogs"))
dat
# # A tibble: 3 x 3
#    name    num dogs      
#   <chr> <dbl> <list>    
# 1 name1 20.0  <list [1]>
# 2 name2 13.0  <NULL>    
# 3 name3  5.00 <list [2]>

А если вы предпочитаете, чтобы все было в столбце списка, замените map_chr и map_dbl на map.

dat <- data_frame(name = map(myList, "name"),
                  num = map(myList, "num"),
                  dogs = map(myList, "dogs"))
dat
#   name      num       dogs      
#   <list>    <list>    <list>    
# 1 <chr [1]> <dbl [1]> <list [1]>
# 2 <chr [1]> <dbl [1]> <NULL>    
# 3 <chr [1]> <dbl [1]> <list [2]>
person www    schedule 01.02.2018

После некоторого времени, поигравшего с purrr, я получил другое решение, которое не требует ввода имен (может быть проблематичным для действительно больших списков).

myList %>% transpose %>% simplify_all %>% tbl_df

Результаты в

# A tibble: 3 x 3
   name   num       dogs
  <chr> <dbl>     <list>
1 name1    20 <list [1]>
2 name2    13 <list [0]>
3 name3     5 <list [2]>

Функция transpose из purrr выполняет этот тип преобразования автоматически.

person Freguglia    schedule 22.02.2018