将分组的 tibble 转换为命名列表

Jef*_*ker 9 r purrr tidyverse

我觉得可能有tidyversefor-loop. 从标准 tibble/dataframe 开始,创建一个列表,其中列表元素的名称是一列的唯一值 ( group_by?),列表元素是另一列的所有值。

\n
  my_data <- tibble(list_names = c("Ford", "Chevy", "Ford", "Dodge", "Dodge", "Ford"),\n                    list_values = c("Ranger", "Equinox", "F150", "Caravan", "Ram", "Explorer"))\n  \n# A tibble: 6 \xc3\x97 2\n  list_names list_values\n  <chr>      <chr>      \n1 Ford       Ranger     \n2 Chevy      Equinox    \n3 Ford       F150       \n4 Dodge      Caravan    \n5 Dodge      Ram        \n6 Ford       Explorer\n
Run Code Online (Sandbox Code Playgroud)\n

这是所需的输出:

\n
  desired_output <- list(Ford = c("Ranger", "F150", "Explorer"),\n       Chevy = c("Equinox"),\n       Dodge = c("Caravan", "Ram"))\n\n$Ford\n[1] "Ranger"   "F150"     "Explorer"\n\n$Chevy\n[1] "Equinox"\n\n$Dodge\n[1] "Caravan" "Ram" \n
Run Code Online (Sandbox Code Playgroud)\n

它可以用 a 来完成,for-loop但我敢打赌有一个tidyverse函数可以使它更简单/更快,等等。

\n
  desired_output <- list()\n  for(i in seq_along(my_data$list_names)) {\n    entry <- my_data %>%\n      filter(list_names == my_data$list_names[i]) %>%\n      pull(list_values)\n    desired_output[[my_data$list_names[i]]] <- entry\n  }\n
Run Code Online (Sandbox Code Playgroud)\n

And*_*own 7

group_modify这是使用and deframefrom的另一个选项(尽管更详细)tidyverse

library(tidyverse)

my_data |>
  group_by(list_names)  |>
  group_modify(\(x, ...) tibble(res = list(deframe(x)))) |>
  deframe()
Run Code Online (Sandbox Code Playgroud)

或者另一种选择可能是使用summarise然后再次使用deframe

my_data %>%
  group_by(list_names) %>%
  summarise(named_vec = list(list_values)) %>%
  deframe()
Run Code Online (Sandbox Code Playgroud)

输出

$Chevy
[1] "Equinox"

$Dodge
[1] "Caravan" "Ram"    

$Ford
[1] "Ranger"   "F150"     "Explorer"
Run Code Online (Sandbox Code Playgroud)

基准

我很想知道这里的答案中最快的是什么,并且split@akrun 看起来肯定是迄今为止最快的,其次是unstack.

在此输入图像描述

bm <- microbenchmark::microbenchmark(
  akrun_split = with(my_data, split(list_values,
                                    factor(list_names, levels = unique(list_names)))),
  akrun_unstack = unstack(my_data, list_values ~ list_names),
  andrew_deframe1 = my_data |>
    group_by(list_names)  |>
    group_modify(\(x, ...) tibble(res = list(deframe(x)))) |>
    deframe(),
  andrew_deframe2 = my_data %>%
    group_by(list_names) %>%
    summarise(named_vec = list(list_values)) %>%
    deframe(),
  paulsmith = my_data %>% 
    group_by(list_names) %>% 
    summarise(list_values = list(list_values)) %>% 
    {set_names(.$list_values, .$list_names)}, 
  times=1000L
)
Run Code Online (Sandbox Code Playgroud)


akr*_*run 6

我们可以用split

with(my_data, split(list_values,
     factor(list_names, levels = unique(list_names))))
$Ford
[1] "Ranger"   "F150"     "Explorer"

$Chevy
[1] "Equinox"

$Dodge
[1] "Caravan" "Ram"   
Run Code Online (Sandbox Code Playgroud)

或者与unstack

unstack(my_data, list_values ~ list_names)
$Chevy
[1] "Equinox"

$Dodge
[1] "Caravan" "Ram"    

$Ford
[1] "Ranger"   "F150"     "Explorer"
Run Code Online (Sandbox Code Playgroud)