r rlang:在 tidyselect 助手上使用 is_quosure
r rlang: using is_quosure on tidyselect helper
假设您在 R 函数中有一个参数可以是:
- 原始的 tidyselect 助手,例如
contains("a")
、starts_with("a")
等,
- 与助手的关系列表,
vars(contains("a"))
。
如果你是情况(1)或(2),你如何在函数内检查?
问题是 is_quosures(vars(contains("a")))
有效,但 is_quosures(contains("a"))
无效,因为它首先尝试计算函数 contains("a")
,returns 在计算时出错一个人!?
library(rlang)
library(dplyr)
is_quosures(vars(contains("a")))
#> [1] TRUE
is_quosures(contains("a"))
#> Error: No tidyselect variables were registered
fo <- function(var) {
is_quosures(var)
}
fo(vars(contains("a")))
#> [1] TRUE
fo(contains("a"))
#> Error: No tidyselect variables were registered
由 reprex package (v0.3.0)
于 2019-12-03 创建
用例
您想使用 summarise_at(data, var)
之类的函数,并希望它对指定 var
作为直接 tidyselect
帮助程序或包含在 vars()
呼叫。我想出解决这个问题的唯一方法是逐个检查 if/then 是否为 quosure(如果不是,则包装到 vars 中),但这在上述情况下恰恰会失败。
library(rlang)
library(dplyr)
#>
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#>
#> filter, lag
#> The following objects are masked from 'package:base':
#>
#> intersect, setdiff, setequal, union
fo <- function(var) {
is_var_closure <- rlang::is_quosures(var)
if(is_var_closure) {
dplyr::summarise_at(iris, var, mean)
} else {
dplyr::summarise_at(iris, quos(var), mean)
}
}
fo(vars(starts_with("Sepal")))
#> Sepal.Length Sepal.Width
#> 1 5.843333 3.057333
fo(starts_with("Sepal"))
#> Error: No tidyselect variables were registered
由 reprex package (v0.3.0)
于 2019-12-03 创建
我之前这样做的方法是捕获表达式并使用 is_call
:
检查
f <- function(var) {
if (rlang::is_call(rlang::enexpr(var), names(tidyselect::vars_select_helpers))) {
rlang::enquos(var)
}
else {
stopifnot(rlang::is_quosures(var)) # or something more specific with a useful message
var
}
}
# both work
f(vars(starts_with("Sepal")))
f(starts_with("Sepal"))
只需确保对 is_call
使用 enexpr
,
参见 this GitHub issue。
假设您在 R 函数中有一个参数可以是:
- 原始的 tidyselect 助手,例如
contains("a")
、starts_with("a")
等, - 与助手的关系列表,
vars(contains("a"))
。
如果你是情况(1)或(2),你如何在函数内检查?
问题是 is_quosures(vars(contains("a")))
有效,但 is_quosures(contains("a"))
无效,因为它首先尝试计算函数 contains("a")
,returns 在计算时出错一个人!?
library(rlang)
library(dplyr)
is_quosures(vars(contains("a")))
#> [1] TRUE
is_quosures(contains("a"))
#> Error: No tidyselect variables were registered
fo <- function(var) {
is_quosures(var)
}
fo(vars(contains("a")))
#> [1] TRUE
fo(contains("a"))
#> Error: No tidyselect variables were registered
由 reprex package (v0.3.0)
于 2019-12-03 创建用例
您想使用 summarise_at(data, var)
之类的函数,并希望它对指定 var
作为直接 tidyselect
帮助程序或包含在 vars()
呼叫。我想出解决这个问题的唯一方法是逐个检查 if/then 是否为 quosure(如果不是,则包装到 vars 中),但这在上述情况下恰恰会失败。
library(rlang)
library(dplyr)
#>
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#>
#> filter, lag
#> The following objects are masked from 'package:base':
#>
#> intersect, setdiff, setequal, union
fo <- function(var) {
is_var_closure <- rlang::is_quosures(var)
if(is_var_closure) {
dplyr::summarise_at(iris, var, mean)
} else {
dplyr::summarise_at(iris, quos(var), mean)
}
}
fo(vars(starts_with("Sepal")))
#> Sepal.Length Sepal.Width
#> 1 5.843333 3.057333
fo(starts_with("Sepal"))
#> Error: No tidyselect variables were registered
由 reprex package (v0.3.0)
于 2019-12-03 创建我之前这样做的方法是捕获表达式并使用 is_call
:
f <- function(var) {
if (rlang::is_call(rlang::enexpr(var), names(tidyselect::vars_select_helpers))) {
rlang::enquos(var)
}
else {
stopifnot(rlang::is_quosures(var)) # or something more specific with a useful message
var
}
}
# both work
f(vars(starts_with("Sepal")))
f(starts_with("Sepal"))
只需确保对 is_call
使用 enexpr
,
参见 this GitHub issue。