Transformar lista de listas em tibble

Olá pessoas

Eu tenho uma lista de listas, e quero converter em tibble. Minha melhor tentativa até agora é a seguinte:

library(tibble)  
lista <- list(
  list(id = 1, 
       comp = list(id = 1, area = "A", name = "Comp1"),
       season = list(id = 1, start_year = 2023, end_year = 2024, name = "S1"),
       name = "Comp1 - S1"),
  list(id = 2, 
       comp = list(id = 1, area = "A", name = "Comp1"),
       season = list(id = 2, start_year = 2022, end_year = 2023, name = "S2"),
       name = "Comp1 - S2"),
  list(id = 3, 
       comp = list(id = 2, area = "A", name = "Comp2"),
       season = list(id = 1, start_year = 2023, end_year = 2024, name = "S1"),
       name = "Comp2 - S1")
)

lista %>% 
  purrr::map_depth(2, as_tibble) %>% 
  purrr::map_df(as_tibble) %>% 
  tidyr::unnest()
#> Warning: `cols` is now required when using `unnest()`.
#> ℹ Please use `cols = c(id, comp, season, name)`.
#> # A tibble: 3 × 9
#>   value    id area  name    id1 start_year end_year name1 value1    
#>   <dbl> <dbl> <chr> <chr> <dbl>      <dbl>    <dbl> <chr> <chr>     
#> 1     1     1 A     Comp1     1       2023     2024 S1    Comp1 - S1
#> 2     2     1 A     Comp1     2       2022     2023 S2    Comp1 - S2
#> 3     3     2 A     Comp2     1       2023     2024 S1    Comp2 - S1

tibble::tribble(
  ~id, ~comp_id, ~comp_area, ~comp_name, 
  ~season_id, ~season_start_year, ~season_end_year, ~season_name, ~name,
  1, 1, "A", "Comp1", 1, 2023, 2024, "S1", "Comp1 - S1",
  2, 1, "A", "Comp1", 2, 2022, 2023, "S2", "Comp1 - S2",
  3, 2, "A", "Comp2", 1, 2023, 2024, "S1", "Comp2 - S1"
)
#> # A tibble: 3 × 9
#>      id comp_id comp_area comp_name season_id season_start_year season_end_year
#>   <dbl>   <dbl> <chr>     <chr>         <dbl>             <dbl>           <dbl>
#> 1     1       1 A         Comp1             1              2023            2024
#> 2     2       1 A         Comp1             2              2022            2023
#> 3     3       2 A         Comp2             1              2023            2024
#> # ℹ 2 more variables: season_name <chr>, name <chr>

Created on 2023-12-13 with reprex v2.0.2

Minha melhor tentativa ainda não resolve o que eu quero, que é o último objeto escrito manualmente ali. O conteúdo está ok, o problema está apenas no nome das colunas. Alguma dica de como chegar no conjunto de nomes que indiquei na última tibble? Um mutate resolve para este caso, mas eu preciso de uma solução parametrizável para casos mais genéricos.

Rodrigo, acho que a função unnest_wider() pode te ajudar com esse desafio:

lista <- list(
  list(id = 1, 
       comp = list(id = 1, area = "A", name = "Comp1"),
       season = list(id = 1, start_year = 2023, end_year = 2024, name = "S1"),
       name = "Comp1 - S1"),
  list(id = 2, 
       comp = list(id = 1, area = "A", name = "Comp1"),
       season = list(id = 2, start_year = 2022, end_year = 2023, name = "S2"),
       name = "Comp1 - S2"),
  list(id = 3, 
       comp = list(id = 2, area = "A", name = "Comp2"),
       season = list(id = 1, start_year = 2023, end_year = 2024, name = "S1"),
       name = "Comp2 - S1")
)

lista |>
  purrr::map_depth(2, tibble::as_tibble) |>
  purrr::map(tibble::as_tibble) |>
  purrr::list_rbind() |>
  tidyr::unnest_wider(dplyr::everything(), names_sep = "_") |>
  dplyr::rename_with(\(x) stringr::str_remove(x, "_value$"))
#> # A tibble: 3 × 9
#>      id comp_id comp_area comp_name season_id season_start_year season_end_year
#>   <dbl>   <dbl> <chr>     <chr>         <dbl>             <dbl>           <dbl>
#> 1     1       1 A         Comp1             1              2023            2024
#> 2     2       1 A         Comp1             2              2022            2023
#> 3     3       2 A         Comp2             1              2023            2024
#> # ℹ 2 more variables: season_name <chr>, name <chr>

Created on 2023-12-13 with reprex v2.0.2

O maior problema da minha solução é que as colunas id e name precisam ser renomeadas no final, porque elas saem por padrão como id_value e name_value. Talvez você consiga achar um jeito de contornar isso, possivelmente não transformando esses elementos da lista inicial em tibbles.

Caio, muito obrigado! Funcionou perfeitamente! Eu implementei aqui exatamente como você sugeriu, removendo o “_value” no fim. A solução funciona bem por saber que o sufixo sempre vai estar presente (e mesmo que não esteja, continua funcionando). Por curiosidade, tentei filtrar apenas os elementos que são lista com tidyr::unnest_wider(dplyr::where(is.list), names_sep = "_"), mas no momento ali todas as colunas são listas, inclusive id e name que só têm um objeto, e acaba dando na mesma. Como fica muito mais trabalhoso filtrar os elementos que são listas com um único elemento igual a “value” e sua solução já é flexível o bastante, resolveu completamente minha questão. Muito obrigado novamente!