在 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
如果你想让数据屏蔽函数在列上循环工作,你必须在某些时候进行元编程。
真的有两种选择:
要么让你的函数接受带有标准评估的字符串。然后在内部将该字符串转换为符号。元编程是内部的。
或者让它采用非标准评估的表达式。然后你的调用者必须将字符串转换为符号并取消引用它们。元编程是外部的。
没有办法解决这个问题,除非您要创建一个非标准界面,该界面会因过于神奇而工作不一致且不可预测。
我正在使用 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
如果你想让数据屏蔽函数在列上循环工作,你必须在某些时候进行元编程。
真的有两种选择:
要么让你的函数接受带有标准评估的字符串。然后在内部将该字符串转换为符号。元编程是内部的。
或者让它采用非标准评估的表达式。然后你的调用者必须将字符串转换为符号并取消引用它们。元编程是外部的。
没有办法解决这个问题,除非您要创建一个非标准界面,该界面会因过于神奇而工作不一致且不可预测。