如何从 tibble 列表列构建命名列表?

How to build a named list from tibble list columns?

是否有直接的 pipe-friendly 方法从包含 list-columns 的 tibble 生成 list object?

考虑下面的例子。如果 my_starwars 是给定的 tibble,我怎样才能实现 named 列表,如 desired_output?

library(dplyr, warn.conflicts = FALSE)
library(purrr)

my_starwars <-
  starwars %>%
  slice(1)

films <- my_starwars %>% pull(films) %>% set_names("films")
vehicles <- my_starwars %>% pull(vehicles) %>% set_names("vehicles")

desired_output <- c(films, vehicles)

desired_output
#> $films
#> [1] "The Empire Strikes Back" "Revenge of the Sith"    
#> [3] "Return of the Jedi"      "A New Hope"             
#> [5] "The Force Awakens"      
#> 
#> $vehicles
#> [1] "Snowspeeder"           "Imperial Speeder Bike"

虽然上面的代码完成了工作,但我想要一些可以从管道中获取的更少的手册,例如:

my_starwars %>%
  build_list(films, vehicles, foo, bar) # this is a demo

## $films
## [1] "The Empire Strikes Back" "Revenge of the Sith"     "Return of the Jedi"      "A New Hope"              ## "The Force Awakens"      

## $vehicles
## [1] "Snowspeeder"           "Imperial Speeder Bike"

## $foo
## [1] "foo" "foo" "foo"

## $bar
## [1] "bar" "bar"

是否有使用 tidyverse 工具的直接方法?


编辑


虽然@GuedesBF 的解决方案非常适合初始 my_starwars 示例,但它因不同类型的小标题而失败。所以我原来的例子太小了,不能代表我的问题。请考虑以下示例,其中 trb 是一个包含 2 list-columns 的小标题,每个小标题中都有一个 recipe object。

library(recipes)

car_rec_1 <- 
  recipe(mpg ~ ., data = mtcars) %>% 
  step_ns(disp, deg_free = 5)

car_rec_2 <- 
  recipe(mpg ~ ., data = mtcars) %>% 
  step_dummy(am)

trb <-
  tribble(~car_rec_1, ~car_rec_2,
           car_rec_1,  car_rec_2)

undesired_output_trb <- 
  trb %>%
  lapply(unlist)

car_rec_1 <- trb %>% pull(car_rec_1) %>% setNames("car_rec_1")
car_rec_2 <- trb %>% pull(car_rec_2) %>% setNames("car_rec_2")
desired_output_trb <- c(car_rec_1, car_rec_2)

当我们使用@GuedesBF 的解决方案时,我们得到 undesired_output_trb,而我想要的是 desired_output_trb。如何实现?

我们可以将函数循环应用到 unlist() select 列。

my_starwars %>%
        select(c(films, vehicles)) %>%
        lapply(unlist)

#Or if tidyverse is a must, we can replace `lapply` with `purrr::map`

my_starwars %>%
        select(c(films, vehicles)) %>%
        map(unlist)

$films
[1] "The Empire Strikes Back" "Revenge of the Sith"     "Return of the Jedi"      "A New Hope"              "The Force Awakens"      

$vehicles
[1] "Snowspeeder"           "Imperial Speeder Bike"

更新

OP 给出的第二个示例包含嵌套列表,列表列中包含列表元素。更简单的 lapply(unlist)unclass() 解决方案在这里不起作用。我们需要一个提供额外控制的取消列表功能,为此我建议 purrr::pluckmap(my_starwars, pluck, 1) 也适用于原始问题。

library(purrr)

trb %>%
        map(pluck, 1)

identical(desired_output_trb, trb %>% map(pluck, 1))
[1] TRUE

基于,另一个解决方案是 tidyr::pivot_longer()tibble::deframe():

library(dplyr, warn.conflicts = FALSE)
library(tibble)
library(tidyr)

my_starwars <-
  starwars %>%
  slice(1)

my_starwars %>%
  select(films, vehicles) %>%
  pivot_longer(everything()) %>%
  deframe()
#> $films
#> [1] "The Empire Strikes Back" "Revenge of the Sith"    
#> [3] "Return of the Jedi"      "A New Hope"             
#> [5] "The Force Awakens"      
#> 
#> $vehicles
#> [1] "Snowspeeder"           "Imperial Speeder Bike"

library(recipes)

car_rec_1 <- 
  recipe(mpg ~ ., data = mtcars) %>% 
  step_ns(disp, deg_free = 5)

car_rec_2 <- 
  recipe(mpg ~ ., data = mtcars) %>% 
  step_dummy(am)

trb <-
  tribble(~car_rec_1, ~car_rec_2,
          car_rec_1,  car_rec_2)

trb %>%
  pivot_longer(everything()) %>%
  deframe()
#> $car_rec_1
#> Recipe
#> 
#> Inputs:
#> 
#>       role #variables
#>    outcome          1
#>  predictor         10
#> 
#> Operations:
#> 
#> Natural Splines on disp
#> 
#> $car_rec_2
#> Recipe
#> 
#> Inputs:
#> 
#>       role #variables
#>    outcome          1
#>  predictor         10
#> 
#> Operations:
#> 
#> Dummy variables from am