【问题标题】:Function in R, passing in variablesR中的函数,传入变量
【发布时间】:2020-06-07 15:57:57
【问题描述】:

我希望在 R 中运行多个方差分析,所以我希望编写一个函数。

df = iris

run_anova <- function(var1,var2,df) {
  fit = aov(var1 ~ var1 , df)
  return(fit)
}

在鸢尾花数据集中,列名是“Sepal.Length”“Sepal.Width”“Petal.Length”“Petal.Width”“Species”

假设我想在方程中使用这些列,如何将它们传递给 run_anova 函数?我尝试将它们作为字符串传递

run_anova("Sepal.Width", "Petal.Length", df)

这不起作用,因为出现此错误: "在 storage.mode(v)

run_anova(Sepal.Width, Petal.Length, df)

当我不带引号将它们传入时,“未找到”。如何将 df 列的这些名称传递给函数?

非常感谢您的帮助。

【问题讨论】:

  • 将尝试从变量名称字符串构建公式:fit = aov(as.formula(paste(var1, "~", var2)) , df)
  • 或简称reformulate(var2, var1)

标签: r function


【解决方案1】:

1) 使用重新制定公式来创建公式。需要do.call 才能使输出中的 Call: 行看起来很好,但如果您不关心这一点,可以使用 (3) 中显示的较短版本。

run_anova <- function(var1, var2, df) {
  fo <- reformulate(var2, var1)
  do.call("aov", list(fo, substitute(df)))
}

run_anova("Sepal.Width", "Petal.Length", iris)

给予

Call:
   aov(formula = Sepal.Width ~ Petal.Length, data = iris)    

Terms:
                Petal.Length Residuals
Sum of Squares      5.196047 23.110887
Deg. of Freedom            1       148

Residual standard error: 0.3951641
Estimated effects may be unbalanced

2) 尽管不鼓励使用eval,但也可以提供良好输出的替代方法是:

run_anova2 <- function(var1, var2, df) {
  fo <- reformulate(var2, var1)
  eval.parent(substitute(aov(fo, df)))
}

run_anova2("Sepal.Width", "Petal.Length", iris)

3)如果您不关心输出中的 Call 行是否很好,则可以使用以下更简单的代码:

run_anova3 <- function(var1, var2, df) {
  fo <- reformulate(var2, var1)
  aov(fo, df)
}

run_anova3("Sepal.Width", "Petal.Length", iris)

给予:

Call:
   aov(formula = fo, data = df)
...etc...

【讨论】:

  • 这真的很有帮助,非常感谢您花时间回复
【解决方案2】:

另一种方法是使用rlang 的准引号语法

df = iris

library(rlang)
run_anova <- function(var1, var2, df) {
    var1 <- parse_expr(quo_name(enquo(var1)))
    var2 <- parse_expr(quo_name(enquo(var2)))
    eval_tidy(expr(aov(!!var1 ~ !!var2, data = df)))
}

这允许您对var1var2 使用字符串和不带引号的表达式:

run_anova("Sepal.Width", "Petal.Length", df)
run_anova(Sepal.Width, Petal.Length, df)

两个表达式返回相同的结果。

【讨论】:

  • @G.Grothendieck 真;但结果是一样的。这里的好处是我们可以使用带引号和不带引号的表达式。
  • @G.Grothendieck 是的,我理解您的评论。它在返回list 的调用元素中显示data = df,但它确实返回正确的aov 以及您为run_anovadf 参数提供的任何data.frame。答案之间的唯一区别是 call 元素不同。结果是一样的。
  • @G.Grothendieck PS。为了使事情与您的结果一致,我交换了var1var2;我原来有var2 ~ var1,你有var1 ~ var2(不幸的是,OP 有一个错字var1 ~ var1)。
  • @G.Grothendieck 这并不是 OP 真正要问的。 OP 尝试将列名作为字符串和不带引号的表达式传递。我的回答允许他两者都做(或者更确切地说:两者都做)。
猜你喜欢
  • 2012-12-12
  • 1970-01-01
  • 2011-02-26
  • 2013-10-08
  • 2021-12-07
  • 2019-01-15
  • 1970-01-01
  • 1970-01-01
  • 2021-07-18
相关资源
最近更新 更多