Как создать фрейм данных из списка, выбирая, на каком подсписке сосредоточиться

Скажите, что у меня есть этот список:

listexample = list(books = list(list(
                    title = "Book 1",
                    entry = "entry 1",
                    publisher = "Books Unlimited",
                    authors = list(
                                list(name = "bob", location = "north dakota"),
                                list(name = "susan", location = "california"),
                                list(name = "tim")),
                    isbn = "1358",
                    universities = list(
                                list(univ = "univ1"),
                                list(univ = "univ2"))
                    ),
                    list(
                        title = "Book 2",
                        entry = "entry 2",
                        publisher = "Books Unified",
                        authors = list(
                            list(name = "tom", location = "north dakota"),
                            list(name = "sally", location = "california"),
                            list(name = "erica", location = "berlin")),
                        isbn = "1258",
                        universities = list(
                            list(univ = "univ5"),
                            list(univ = "univ2"),
                            list(univ = "univ99"),
                            list(univ = "univ2"),
                            list(univ = "univ3"))
                    )   
                ),
     misc = list(name = "Jim Smith", location = "Alaska"))

Как я могу создать фрейм данных (или тиббл тоже подойдет), где каждая строка является автором? Я хочу полностью игнорировать второй элемент основного списка (misc). Я также хочу игнорировать universities, isbn и publisher. Я все еще хочу сохранить title, name, location, а также books (имя первого элемента основного списка).

Я знаю, что rrapply можно использовать для итеративного выполнения действий, но не уверен, уместно ли это в данном случае.

library(rrapply)
rrapply(listexample, how = "bind")

Это выглядит нормально, если список не большой? Возможно, сначала вам захочется пробежаться listexample[[2L]] = NULL. И тогда, я думаю, это просто вопрос переименования и удаления строк.

Friede 17.08.2024 01:01
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
1
88
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Вы можете использовать unnest_longer и unnest_wider от tidyr.

listexample |> 
  tibble::enframe() |> 
  dplyr::filter(name == "books") |> 
  tidyr::unnest_longer(value) |> 
  tidyr::unnest_wider(value) |> 
  dplyr::select(title, authors) |> 
  tidyr::unnest_longer(authors) |> 
  tidyr::unnest_wider(authors)

Вы можете запускать код, добавляя по одной строке, чтобы увидеть, что все делает. Короче говоря, мы превращаем список в двухстрочный тиббл (первая строка — books, вторая строка — misc), а затем расширяем вложенную информацию.

Прочтите tidyr«прямоугольную» виньетку для получения дополнительной информации. На самом деле, вы, вероятно, можете сократить код здесь, используя tidyr::hoist().

Спасибо, что отметили виньетку и за ответ.

bill999 18.08.2024 06:20

1) Используйте tibblify, чтобы создать тиббл, и выберите из него столбцы title и authors. Последний представляет собой столбец списка, так что unnest это так.

library(dplyr)
library(tidyr)
library(tibblify)

listexample %>%
  .$books %>%
  tibblify %>%
  select(title, authors) %>%
  unnest(authors)

предоставление

# A tibble: 6 × 3
  title  name  location    
  <chr>  <chr> <chr>       
1 Book 1 bob   north dakota
2 Book 1 susan california  
3 Book 1 tim   <NA>        
4 Book 2 tom   north dakota
5 Book 2 sally california  
6 Book 2 erica berlin      

2) Вариантом вышеизложенного является использование tibblify со спецификацией, как показано ниже. Спецификацию можно создать, запустив guess_tspec_df(listexample$books), а затем отредактировав ее до желаемого значения.

spec <- tspec_df(
  tib_chr("title"),
  tib_df(
    "authors",
    tib_chr("name"),
    tib_chr("location", required = FALSE),
  )
)
tibblify(listexample$books, spec) %>% unnest(authors)

В базе R, используя lapply и do.call, вы можете сделать

> lapply(listexample[[1L]], \(i) { 
+   tmp = i[names(i) %in% c("authors", "title")] 
+   tmp2 = do.call("rbind", lapply(l<-tmp[["authors"]], `length<-`, max(lengths(l))))
+   cbind.data.frame("title" = rep(tmp[["title"]], nrow(tmp2)), tmp2)
+   }) |> do.call(what = "rbind")

   title  name     location
1 Book 1   bob north dakota
2 Book 1 susan   california
3 Book 1   tim         NULL
4 Book 2   tom north dakota
5 Book 2 sally   california
6 Book 2 erica       berlin

Другие вопросы по теме