在 tidyeval 函数中制作循环友好的公式界面

making loop-friendly formula interface in tidyeval functions

我正在使用 tidyeval 编写一个简单的函数,我需要将参数传递给公式接口。虽然我已经设法构建了该函数的工作版本,但它似乎不适用于 for 循环。

函数

foo <- function(data, x, y) {
  BayesFactor::ttestBF(
    paired = FALSE,
    data = data,
    formula = rlang::new_formula(rlang::enexpr(y), rlang::enexpr(x))
  )
}

foo(mtcars, am, wt)
#> Bayes factor analysis
#> --------------
#> [1] Alt., r=0.707 : 1383.367 ±0%
#> 
#> Against denominator:
#>   Null, mu1-mu2 = 0 
#> ---
#> Bayes factor type: BFindepSample, JZS

使用循环

我这里也试过了!!col.name[i]

df <- dplyr::select(mtcars, am, wt, mpg)
col.name <- colnames(df)

for (i in 2:length(col.name)) {
  foo(
    data = mtcars,
    x = am,
    y = col.name[i]
  )
}
#> Error in `[.data.frame`(data, , dv): undefined columns selected

如果您可以将字符串值作为变量传递,我们可以使用 reformulate 来构建公式。

foo <- function(data, x, y) {
  BayesFactor::ttestBF(
    paired = FALSE,
    data = data,
    formula = reformulate(x, y)
  )
}

foo(mtcars, "am", "wt")

#Bayes factor analysis
#--------------
#[1] Alt., r=0.707 : 1383.367294 ±0%

#Against denominator:
#  Null, mu1-mu2 = 0 
#---
#Bayes factor type: BFindepSample, JZS

循环传递/lapply :

col.name <- c('wt', 'mpg')
result <- lapply(col.name, foo, data = mtcars, x = 'am')
result

#[[1]]
#Bayes factor analysis
#--------------
#[1] Alt., r=0.707 : 1383.367294 ±0%

#Against denominator:
#  Null, mu1-mu2 = 0 
#---
#Bayes factor type: BFindepSample, JZS


#[[2]]
#Bayes factor analysis
#--------------
#[1] Alt., r=0.707 : 86.58972736 ±0%

#Against denominator:
#  Null, mu1-mu2 = 0 
#---
#Bayes factor type: BFindepSample, JZS

如果你想让数据屏蔽函数在列上循环工作,你必须在某些时候进行元编程。

真的有两种选择:

  • 要么让你的函数接受带有标准评估的字符串。然后在内部将该字符串转换为符号。元编程是内部的。

  • 或者让它采用非标准评估的表达式。然后你的调用者必须将字符串转换为符号并取消引用它们。元编程是外部的。

没有办法解决这个问题,除非您要创建一个非标准界面,该界面会因过于神奇而工作不一致且不可预测。