使用 rlang 创建类型为 ~ x + y 的新公式
Creating a new formula of type `~ x + y` using `rlang`
我正在尝试编写一个自定义函数,我想在其中使用 cor.test
函数,但我无法取消引用所需的参数来创建一个有效的公式。
这是我目前无法使用的方法-
library(rlang)
# custom function
tryfn <- function(data, x, y) {
stats::cor.test(
formula = rlang::new_formula(NULL, {{ x }} + {{ y }}),
data = data,
method = "pearson"
)
}
# using the function
tryfn(mtcars, wt, mpg)
#> Error in rlang::new_formula(NULL, {: object 'wt' not found
我试过这种方法,因为如果我不必在函数环境中取消对公式的引用,它似乎可以工作。
# without unquoting inside another function
print(rlang::new_formula(NULL, quote(x + y)))
#> ~x + y
关于如何实现这个的任何想法?
请务必记住 rlang::quo
与 base::quote
不同。
实际上,后者最终基本上等同于 rlang::expr
。
使用 {{
进行插值会创建具有相应环境的 quosures,
所以它是以下情况的快捷方式:
x <- 0
with_curly <- function(foo) {
x <- 1
rlang::eval_tidy({{ foo }})
}
with_curly(x)
# 0
with_enquo <- function(foo) {
x <- 1
rlang::eval_tidy(rlang::enquo(foo))
}
with_enquo(x)
# 0
另一方面,enexpr
的行为类似于 quote
,但对于用户键入的内容:
with_enexpr <- function(foo) {
x <- 1
rlang::eval_tidy(rlang::enexpr(foo))
}
with_enexpr(x)
# 1
根据我的经验,quosures 不能很好地(或根本)不支持任何不明确支持它们的函数,
许多 R 函数需要 "raw" 表达式。
即使在打印过程中,您也可以看到它们的处理方式不同:
foo <- function(foo) {
rlang::qq_show({{ foo }})
rlang::qq_show(!!rlang::enexpr(foo))
invisible()
}
foo(x)
# ^x
# x
这意味着,至少目前,创建简单表达式没有捷径可走,
而且你必须做很长的路要走:
编辑:不完全正确。
简单的表达没有捷径,
但您仍然可以创建带有等式的公式。
请参阅穆迪的回答和下面的评论。
时不时地退后一步并记住,您不需要到处都进行非标准评估也是值得的:
tryfn <- function(data, x, y) {
stats::cor.test(
formula = as.formula(glue::glue("~ {x} + {y}")),
data = data,
method = "pearson"
)
}
tryfn(mtcars, "wt", "mpg")
您的问题来自以下事实:
new_formula()
需要调用或命名对象作为输入,并且您希望它使用 NSE :
rlang::new_formula(NULL, wt + mpg)
#> Error in rlang::new_formula(NULL, wt + mpg): objet 'wt' introuvable
rlang::new_formula(NULL, quote(wt + mpg))
#> ~wt + mpg
new_formula()
不支持准引用:
quoted_expr <- quote(wt + mpg)
rlang::new_formula(NULL, !!quote(quoted_expr))
#> Error in !quote(quoted_expr): type de l'argument incorrect
(看看!!
是如何不被识别的)
解决这两个问题的一种方法是从支持准引用的函数创建引用表达式。这个函数是 expr()
:
tryfn <- function(data, x, y) {
stats::cor.test(
formula = rlang::new_formula(NULL, rlang::expr({{x}} + {{y}})),
data = data,
method = "pearson"
)
}
tryfn(mtcars, wt, mpg)
#>
#> Pearson's product-moment correlation
#>
#> data: wt and mpg
#> t = -9.559, df = 30, p-value = 1.294e-10
#> alternative hypothesis: true correlation is not equal to 0
#> 95 percent confidence interval:
#> -0.9338264 -0.7440872
#> sample estimates:
#> cor
#> -0.8676594
我正在尝试编写一个自定义函数,我想在其中使用 cor.test
函数,但我无法取消引用所需的参数来创建一个有效的公式。
这是我目前无法使用的方法-
library(rlang)
# custom function
tryfn <- function(data, x, y) {
stats::cor.test(
formula = rlang::new_formula(NULL, {{ x }} + {{ y }}),
data = data,
method = "pearson"
)
}
# using the function
tryfn(mtcars, wt, mpg)
#> Error in rlang::new_formula(NULL, {: object 'wt' not found
我试过这种方法,因为如果我不必在函数环境中取消对公式的引用,它似乎可以工作。
# without unquoting inside another function
print(rlang::new_formula(NULL, quote(x + y)))
#> ~x + y
关于如何实现这个的任何想法?
请务必记住 rlang::quo
与 base::quote
不同。
实际上,后者最终基本上等同于 rlang::expr
。
使用 {{
进行插值会创建具有相应环境的 quosures,
所以它是以下情况的快捷方式:
x <- 0
with_curly <- function(foo) {
x <- 1
rlang::eval_tidy({{ foo }})
}
with_curly(x)
# 0
with_enquo <- function(foo) {
x <- 1
rlang::eval_tidy(rlang::enquo(foo))
}
with_enquo(x)
# 0
另一方面,enexpr
的行为类似于 quote
,但对于用户键入的内容:
with_enexpr <- function(foo) {
x <- 1
rlang::eval_tidy(rlang::enexpr(foo))
}
with_enexpr(x)
# 1
根据我的经验,quosures 不能很好地(或根本)不支持任何不明确支持它们的函数, 许多 R 函数需要 "raw" 表达式。 即使在打印过程中,您也可以看到它们的处理方式不同:
foo <- function(foo) {
rlang::qq_show({{ foo }})
rlang::qq_show(!!rlang::enexpr(foo))
invisible()
}
foo(x)
# ^x
# x
这意味着,至少目前,创建简单表达式没有捷径可走, 而且你必须做很长的路要走:
编辑:不完全正确。 简单的表达没有捷径, 但您仍然可以创建带有等式的公式。 请参阅穆迪的回答和下面的评论。
时不时地退后一步并记住,您不需要到处都进行非标准评估也是值得的:
tryfn <- function(data, x, y) {
stats::cor.test(
formula = as.formula(glue::glue("~ {x} + {y}")),
data = data,
method = "pearson"
)
}
tryfn(mtcars, "wt", "mpg")
您的问题来自以下事实:
new_formula()
需要调用或命名对象作为输入,并且您希望它使用 NSE :
rlang::new_formula(NULL, wt + mpg)
#> Error in rlang::new_formula(NULL, wt + mpg): objet 'wt' introuvable
rlang::new_formula(NULL, quote(wt + mpg))
#> ~wt + mpg
new_formula()
不支持准引用:
quoted_expr <- quote(wt + mpg)
rlang::new_formula(NULL, !!quote(quoted_expr))
#> Error in !quote(quoted_expr): type de l'argument incorrect
(看看!!
是如何不被识别的)
解决这两个问题的一种方法是从支持准引用的函数创建引用表达式。这个函数是 expr()
:
tryfn <- function(data, x, y) {
stats::cor.test(
formula = rlang::new_formula(NULL, rlang::expr({{x}} + {{y}})),
data = data,
method = "pearson"
)
}
tryfn(mtcars, wt, mpg)
#>
#> Pearson's product-moment correlation
#>
#> data: wt and mpg
#> t = -9.559, df = 30, p-value = 1.294e-10
#> alternative hypothesis: true correlation is not equal to 0
#> 95 percent confidence interval:
#> -0.9338264 -0.7440872
#> sample estimates:
#> cor
#> -0.8676594