Creating a new formula of type `~ x + y` using `rlang`

Ind*_*til 2 r rlang quosure

I am trying to write a custom function where I want to use the cor.test function but I am having trouble unquoting the needed arguments to create a working formula.

Here is what I currently have that doesn't work-

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
Run Code Online (Sandbox Code Playgroud)

I tried this way because it seems to work if I don't have to unquote the formula in the function environment.

# without unquoting inside another function
print(rlang::new_formula(NULL, quote(x + y)))
#> ~x + y
Run Code Online (Sandbox Code Playgroud)

Any ideas on how to implement this?

Ale*_*xis 5

请记住,这rlang::quo与并不相同base::quote。实际上,后者最终基本上等于rlang::expr。插值法{{会在其对应的环境中创建目标,因此它是类似以下情况的快捷方式:

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
Run Code Online (Sandbox Code Playgroud)

另一方面,enexpr行为类似于,quote但对于用户键入的内容:

with_enexpr <- function(foo) {
  x <- 1
  rlang::eval_tidy(rlang::enexpr(foo))
}

with_enexpr(x)
# 1
Run Code Online (Sandbox Code Playgroud)

以我的经验,在不显式支持它们的函数中,quores不能很好地发挥作用(或根本不起作用),并且许多R函数期望“ raw”表达式。即使在打印过程中,您也可以看到它们没有得到相同的处理:

foo <- function(foo) {
  rlang::qq_show({{ foo }})
  rlang::qq_show(!!rlang::enexpr(foo))
  invisible()
}

foo(x)
# ^x
# x
Run Code Online (Sandbox Code Playgroud)

这意味着,至少到目前为止,创建简单表达式没有捷径,您将需要做很长的路要走:

编辑:并不完全正确。简单表达式没有捷径,但是您仍然可以创建带有等式的公式。请参阅穆迪的答案和下面的评论。


有时也应该退后一步,并记住您并不需要到处都进行非标准评估:

tryfn <- function(data, x, y) {
  stats::cor.test(
    formula = as.formula(glue::glue("~ {x} + {y}")),
    data = data,
    method = "pearson"
  )
}

tryfn(mtcars, "wt", "mpg")
Run Code Online (Sandbox Code Playgroud)