【发布时间】:2021-11-19 15:51:31
【问题描述】:
拥有一个数据框,我想生成一个包含命名向量(每行一个向量)的新列表列。每个向量都从其他 2 个数据框列派生其名称和值。但我被困住了,因为我想做:
- 按组
- 尽可能提高计算效率
示例
让我们以{ggplot2} 中的mpg 数据集来说明按组 原则。我想将成对的 cty 和 hwy 值集中在一起,按 manufacturer 和 year 的不同组合分组。所以我们可以这样做:
library(ggplot2)
library(dplyr, warn.conflicts = FALSE)
library(tidyr)
my_mpg <-
mpg %>%
select(manufacturer, year, cty, hwy)
via_tidyr_nest <-
my_mpg %>%
group_by(manufacturer, year) %>%
nest()
via_tidyr_nest
#> # A tibble: 30 x 3
#> # Groups: manufacturer, year [30]
#> manufacturer year data
#> <chr> <int> <list>
#> 1 audi 1999 <tibble [9 x 2]>
#> 2 audi 2008 <tibble [9 x 2]>
#> 3 chevrolet 2008 <tibble [12 x 2]>
#> 4 chevrolet 1999 <tibble [7 x 2]>
#> 5 dodge 1999 <tibble [16 x 2]>
#> 6 dodge 2008 <tibble [21 x 2]>
#> 7 ford 1999 <tibble [15 x 2]>
#> 8 ford 2008 <tibble [10 x 2]>
#> 9 honda 1999 <tibble [5 x 2]>
#> 10 honda 2008 <tibble [4 x 2]>
#> # ... with 20 more rows
由reprex package (v0.3.0) 于 2021 年 9 月 27 日创建
这是完美的,除了我不想要一个嵌套的 tibble 而是一个嵌套的命名向量。 (原因:一旦我们将输出作为对象存储在环境中,命名向量版本的大小会比嵌套的 tibble 版本更轻)。
可行但不受欢迎的解决方案将采用 via_tidyr_nest 并将嵌套的 tibble 转换为命名向量。
expected_output <-
via_tidyr_nest %>%
mutate(desired_named_vec = map(.x = data, .f = ~pull(.x, cty, hwy))) %>%
select(-data)
expected_output
#> # A tibble: 30 x 3
#> # Groups: manufacturer, year [30]
#> manufacturer year desired_named_vec
#> <chr> <int> <list>
#> 1 audi 1999 <int [9]>
#> 2 audi 2008 <int [9]>
#> 3 chevrolet 2008 <int [12]>
#> 4 chevrolet 1999 <int [7]>
#> 5 dodge 1999 <int [16]>
#> 6 dodge 2008 <int [21]>
#> 7 ford 1999 <int [15]>
#> 8 ford 2008 <int [10]>
#> 9 honda 1999 <int [5]>
#> 10 honda 2008 <int [4]>
#> # ... with 20 more rows
这是不希望的,因为它通过绕道实现所需的输出。首先它创建一个 tibble,然后它转换为一个命名向量。虽然在此示例中处理时间可以忽略不计,但实际上我有一个大型数据集(1000 万行)。因此,增加任何额外的步骤都是昂贵的。相反,我希望以尽可能少的步骤到达expected_output。
一次失败的尝试:
library(purrr)
via_summarise_map2_setnames <-
my_mpg %>%
group_by(manufacturer, year) %>%
summarise(named_vec = map2(.x = cty, .y = hwy, .f = ~setNames(.x, .y)))
#> `summarise()` has grouped output by 'manufacturer', 'year'. You can override using the `.groups` argument.
via_summarise_map2_setnames
#> # A tibble: 234 x 3
#> # Groups: manufacturer, year [30]
#> manufacturer year named_vec
#> <chr> <int> <list>
#> 1 audi 1999 <int [1]>
#> 2 audi 1999 <int [1]>
#> 3 audi 1999 <int [1]>
#> 4 audi 1999 <int [1]>
#> 5 audi 1999 <int [1]>
#> 6 audi 1999 <int [1]>
#> 7 audi 1999 <int [1]>
#> 8 audi 1999 <int [1]>
#> 9 audi 1999 <int [1]>
#> 10 audi 2008 <int [1]>
#> # ... with 224 more rows
知道如何直接从my_mpg 转到expected_output,而不在中间创建一个小标题吗?
编辑
只是在这个问题的背景下的一般想法。我知道tidyr::nest() 的默认行为是返回一个嵌套的小标题。但我没有找到任何关于这个决定的讨论。换句话说,如果我们想自己选择嵌套数据的类怎么办?它可以是默认的tibble,也可以是data.frame、data.table、named vector 等。无论用户选择什么作为输出类。
【问题讨论】:
-
as.list+ 设置名称是否能满足您在 tibble 上应用它的期望? -
@anymous.asker,您能否提供一些代码来说明您的意思?不完全确定我理解。
-
什么是“嵌套命名向量”?你的意思是一个(命名的)向量列表吗?
-
@Till,参见示例中
expected_output对象中的desired_named_vec。desired_named_veclist-column 下的每个向量都是一个“嵌套命名向量”。 -
“嵌套命名向量”不是您所描述的准确术语,它是“向量列表”或“向量列表列”。
标签: r performance dplyr tidyr tibble