r - r rlang:在 tidyselect 助手上使用 is_quosure
问题描述
假设您在 R 函数中有一个参数,它可以是:
- 一个原始的 tidyselect 助手,例如
contains("a")
,starts_with("a")
等等, - 带有助手的 quosures 列表,带有
vars(contains("a"))
.
如果您在情况(1)或(2)中,您如何检查功能?
问题是它is_quosures(vars(contains("a")))
有效,但is_quosures(contains("a"))
不起作用,因为它首先尝试评估函数contains("a")
,当单独评估时返回错误!?
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 包(v0.3.0)于 2019 年 12 月 3 日创建
用例
您想使用诸如 , 之类的函数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 包(v0.3.0)于 2019 年 12 月 3 日创建
解决方案
我之前这样做的方法是捕获表达式并检查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"))
只需确保使用enexpr
for is_call
,请参阅此 GitHub 问题。
推荐阅读
- react-native - 处理错误尝试设置不可变和冻结对象的键
- java - 比较 java.utilDate 和 java 中的 LocalDate
- r - R 在 M1 mac 中找不到“stats”和“utils”包
- android - 在 MPAndroidChart 中,如何将 X 轴标签分成两条线?对使用任何修改后的库不感兴趣
- c# - 如何设置第一人称角色控制器的动作
- java - 将VO作为json返回时,如何返回不包括空值?
- ios - 如何shareDialog Facebook无法在swiftUI中工作
- javascript - 如何在不连接的情况下进行调度
- python - Beautiful Soup 只使用soup.select() 返回前10 个列表,这可能是什么问题?
- c# - 鼠标拖动操作失败。使用方法“mysql_native_password”向用户“root”验证主机“serverN”失败并显示消息:访问被拒绝