gpt4 book ai didi

r - 使用 quasiquotation 将参数列表传递给函数

转载 作者:行者123 更新时间:2023-12-04 11:24:19 26 4
gpt4 key购买 nike

我正在尝试在 R 中编写一个函数,根据分组变量汇总数据框。分组变量作为列表给出并传递给 group_by_at ,我想对它们进行参数化。

我现在正在做的是:

library(tidyverse)

d = tribble(
~foo, ~bar, ~baz,
1, 2, 3,
1, 3, 5
4, 5, 6,
4, 5, 1
)

sum_fun <- function(df, group_vars, sum_var) {
sum_var = enquo(sum_var)
return(
df %>%
group_by_at(.vars = group_vars) %>%
summarize(sum(!! sum_var))
)
}

d %>% sum_fun(group_vars = c("foo", "bar"), baz)

但是,我想像这样调用函数:
d %>% sum_fun(group_vars = c(foo, bar), baz)

这意味着不应在调用中评估分组变量,而应在函数中评估。我将如何重写函数以启用它?

我曾尝试使用 enquo 就像对摘要变量一样,然后将 group_vars 替换为 !! group_vars ,但导致此错误:
Error in !group_vars : invalid argument type

使用 group_by(!!!group_vars) 产生:
Column `c(foo, bar)` must be length 2 (the number of rows) or one, not 4 

重写函数的正确方法是什么?

最佳答案

我只是使用 vars 来做引用。这是使用 mtcars 数据集的示例

library(tidyverse)

sum_fun <- function(.data, .summary_var, .group_vars) {
summary_var <- enquo(.summary_var)

.data %>%
group_by_at(.group_vars) %>%
summarise(mean = mean(!!summary_var))
}

sum_fun(mtcars, disp, .group_vars = vars(cyl, am))
#> # A tibble: 6 x 3
#> # Groups: cyl [?]
#> cyl am mean
#> <dbl> <dbl> <dbl>
#> 1 4 0 136.
#> 2 4 1 93.6
#> 3 6 0 205.
#> 4 6 1 155
#> 5 8 0 358.
#> 6 8 1 326

你也可以用 .group_vars (dot-dot-dot) 替换 ...
sum_fun2 <- function(.data, .summary_var, ...) {
summary_var <- enquo(.summary_var)

.data %>%
group_by_at(...) %>% # Forward `...`
summarise(mean = mean(!!summary_var))
}

sum_fun2(mtcars, disp, vars(cyl, am))
#> # A tibble: 6 x 3
#> # Groups: cyl [?]
#> cyl am mean
#> <dbl> <dbl> <dbl>
#> 1 4 0 136.
#> 2 4 1 93.6
#> 3 6 0 205.
#> 4 6 1 155
#> 5 8 0 358.
#> 6 8 1 326

如果您更喜欢将输入作为列列表提供,则需要对 enquos 使用 ...
sum_fun3 <- function(.data, .summary_var, ...) {
summary_var <- enquo(.summary_var)

group_var <- enquos(...)
print(group_var)

.data %>%
group_by_at(group_var) %>%
summarise(mean = mean(!!summary_var))
}

sum_fun3(mtcars, disp, c(cyl, am))
#> [[1]]
#> <quosure>
#> expr: ^c(cyl, am)
#> env: global
#>
#> # A tibble: 6 x 3
#> # Groups: cyl [?]
#> cyl am mean
#> <dbl> <dbl> <dbl>
#> 1 4 0 136.
#> 2 4 1 93.6
#> 3 6 0 205.
#> 4 6 1 155
#> 5 8 0 358.
#> 6 8 1 326

编辑:将 .addi_var 附加到 .../ .group_var

sum_fun4 <- function(.data, .summary_var, .addi_var, .group_vars) {
summary_var <- enquo(.summary_var)

.data %>%
group_by_at(c(.group_vars, .addi_var)) %>%
summarise(mean = mean(!!summary_var))
}

sum_fun4(mtcars, disp, .addi_var = vars(gear), .group_vars = vars(cyl, am))
#> # A tibble: 10 x 4
#> # Groups: cyl, am [?]
#> cyl am gear mean
#> <dbl> <dbl> <dbl> <dbl>
#> 1 4 0 3 120.
#> 2 4 0 4 144.
#> 3 4 1 4 88.9
#> 4 4 1 5 108.
#> 5 6 0 3 242.
#> 6 6 0 4 168.
#> 7 6 1 4 160
#> 8 6 1 5 145
#> 9 8 0 3 358.
#> 10 8 1 5 326
group_by_at() 也可以将输入作为列名的字符向量

sum_fun5 <- function(.data, .summary_var, .addi_var, ...) {

summary_var <- enquo(.summary_var)
addi_var <- enquo(.addi_var)
group_var <- enquos(...)

### convert quosures to strings for `group_by_at`
all_group <- purrr::map_chr(c(addi_var, group_var), quo_name)

.data %>%
group_by_at(all_group) %>%
summarise(mean = mean(!!summary_var))
}

sum_fun5(mtcars, disp, gear, cyl, am)
#> # A tibble: 10 x 4
#> # Groups: gear, cyl [?]
#> gear cyl am mean
#> <dbl> <dbl> <dbl> <dbl>
#> 1 3 4 0 120.
#> 2 3 6 0 242.
#> 3 3 8 0 358.
#> 4 4 4 0 144.
#> 5 4 4 1 88.9
#> 6 4 6 0 168.
#> 7 4 6 1 160
#> 8 5 4 1 108.
#> 9 5 6 1 145
#> 10 5 8 1 326

reprex package (v0.2.1.9000) 于 2018-10-09 创建

关于r - 使用 quasiquotation 将参数列表传递给函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52718604/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com