r - 将参数列表传递给具有 quasiquotation 的函数
问题描述
我正在尝试在 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
like 作为汇总变量,然后用 替换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 包(v0.2.1.9000)于 2018 年 10 月 9 日创建
推荐阅读
- python - 继承抽象模型“mail.activity.mixin”父模型“crm.lead”后无法保存数据
- kubernetes - Kubernetes Secrets 自动删除
- c++ - C++ 14 GCC 更喜欢带有 std::initializer_list 的构造函数而不是 move-constructor
- java - 试图计算时间差来比较两种排序算法
- node.js - 我的数组不为空,但 array.length 返回 0
- vim - ST & VIM——没有颜色
- rust - 如何确定可以格式化的类型的打印宽度?
- c# - 如何允许覆盖我的 ASP.NET Core 应用程序中的 blob?
- r - 如何在r中分配一半的向量
- python - html中的可点击参数使用flask转到python函数