【问题标题】:making loop-friendly formula interface in tidyeval functions在 tidyeval 函数中制作循环友好的公式界面
【发布时间】:2020-11-25 09:45:01
【问题描述】:

我正在使用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

【问题讨论】:

  • {{ 仅在由 tidyeval 提供支持的 NSE 参数中执行某些操作。 new_formula() 不是 NSE 函数,所以 {{ 就像用括号括起来一样,什么都不做。你能从你的例子中删除这些{{ 以避免混淆吗?
  • 你试过as.name(col.name[i])吗?

标签: r tidyeval


【解决方案1】:

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

真的有两种选择:

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

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

没有办法解决这个问题,除非您要创建一个非标准接口,通过尝试太神奇而工作不一致且不可预测。

【讨论】:

  • 感谢 Lionel 简洁地总结了我编写 tidyeval 函数的选项。我肯定想走第二条路,并相应地做一些元编程来解决这个问题。 :)
【解决方案2】:

如果您可以将字符串值作为变量传递,我们可以使用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

【讨论】:

  • 不幸的是,我不想这样做,因为我希望有一个类似tidyverse 的函数,我想传递符号而不是字符串。
猜你喜欢
  • 2020-02-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-16
  • 1970-01-01
  • 2020-02-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多