【问题标题】:R: Wrapping t.test in a functionR:将 t.test 包装在一个函数中
【发布时间】:2019-03-23 18:54:21
【问题描述】:

为什么这个函数执行失败?

my_ttest <- function(df, variable, by){
    variable <- enquo(variable)
    by <- enquo(by)

    t.test(!!variable ~ !!by, df)
}

my_ttest(mtcars, mpg, am) is_quosure(e2) 中的错误:缺少参数“e2”,没有默认值

但是这个有效

my_mean <- function(df, variable, by){
        variable <- enquo(variable)
        by <- enquo(by)

        df %>% group_by(!!by) %>% summarize(mean(!!variable))
}



my_mean(mtcars, mpg, am)
# A tibble: 2 x 2
     am `mean(mpg)`
  <dbl>       <dbl>
1     0        17.1
2     1        24.4

(dplyr_0.8.0.1)

【问题讨论】:

  • t.test 是一个基础 R 函数,不知道如何处理带引号的变量。你可以使用t.test(formula(substitute(variable ~ by)), df) 而不使用enquo

标签: r dplyr tidyeval


【解决方案1】:

如果我们想在 'my_ttest' 中分别传递参数并在函数内部构造公式,请将 'variable'、'by' 的 quosure (enquo) 转换为符号 (sym),然后构造表达式 ('expr1') 和 evaluate` 它

my_ttest <- function(df, variable, by, env = parent.frame()){
    variable <- rlang::sym(rlang::as_label(rlang::enquo(variable)))
    by <- rlang::sym(rlang::as_label(rlang::enquo(by)))

    exp1 <- rlang::expr(!! variable ~ !! by)



    t.test(formula = eval(exp1), data = df)

}


my_ttest(mtcars, mpg, am)
#Welch Two Sample t-test

#data:  mpg by am
#t = -3.7671, df = 18.332, p-value = 0.001374
#alternative hypothesis: true difference in means is not equal to 0
#95 percent confidence interval:
# -11.280194  -3.209684
#sample estimates:
#mean in group 0 mean in group 1 
#       17.14737        24.39231 

或者如cmets中提到的@lionel,直接用ensym就可以了

my_ttest <- function(df, variable, by, env = parent.frame()){  

  exp1 <- expr(!!ensym(variable) ~ !!ensym(by))

    t.test(formula = eval(exp1), data = df)

  }


my_ttest(mtcars, mpg, am)

编辑:基于@lionel 的 cmets

【讨论】:

  • 嗨阿克伦。我看到您定期使用quo_name() 发布解决方案。请注意quo_name() 将在某个时候被弃用(至少在未来一年)。请看一下来自 rlang 0.3.1 的?as_name / ?as_label
  • 将quosures转换为symbol没有什么意义,最好直接用ensym()取symbol。另请注意,quosures 可以包含任意对象。如果您希望它包含符号,请使用as_name() 将其转换为字符串,否则使用as_label()
  • @lionel 感谢 cmets。 as_label 方式有效。你能用ensym 发布答案吗?目前我使用的是variable &lt;- rlang::sym(rlang::as_label(rlang::enquo(variable))); by &lt;- rlang::sym(rlang::as_label(rlang::enquo(by))),然后其余的和函数中的一样
  • 对于ensym(),这只是exp1 &lt;- expr(!!ensym(variable) ~ !!ensym(by))。谢谢你的更新。我会更改内联代码,所以它根本不会提到quo_name()。这也是我们的错,因为我们更新自己的文档很慢:(
【解决方案2】:

并非每个函数(和包)都适用于整洁的评估。 t.test 将数字向量 x,y 作为参数或公式。在您的示例中,您可以提供公式和数据框,尽管它实际上似乎并不比直接调用 t.test 更有效。


my_ttest <- function(df, frma) {
  t.test(frma, df)
}

my_ttest(mtcars, mpg ~ am)
#> 
#>  Welch Two Sample t-test
#> 
#> data:  mpg by am
#> t = -3.7671, df = 18.332, p-value = 0.001374
#> alternative hypothesis: true difference in means is not equal to 0
#> 95 percent confidence interval:
#>  -11.280194  -3.209684
#> sample estimates:
#> mean in group 0 mean in group 1 
#>        17.14737        24.39231

reprex package (v0.2.1) 于 2019 年 3 月 23 日创建

【讨论】:

    猜你喜欢
    • 2013-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-02
    • 1970-01-01
    • 2021-07-10
    • 1970-01-01
    • 2013-05-23
    相关资源
    最近更新 更多