【问题标题】:using non-standard evaluation with formula使用带公式的非标准评估
【发布时间】:2017-10-19 19:12:23
【问题描述】:

我正在创建一个包,它使用non-standard evaluation 来跟踪列的含义。该包在函数之间传递一个数据框,这些函数执行不同的操作并执行相同的列集。非标准评估非常适合:

my_select <- function(df, xcol, ycol) {
    new_df <- dplyr::select(df, !!xcol, !!ycol)
    new_df
}
my_select(mtcars, quo(wt), quo(mpg))

但是,我想要一个可以使用公式的函数:

my_lm <- function(df, xcol, ycol) {
    new_lm <- lm(!!xcol, !!ycol, data=df)
    new_lm
}
my_lm(mtcars, quo(wt), quo(mpg)

返回Error in !xcol : invalid argument typequo()enquo()!!的各种组合我都试过了,但基本的问题是我不知道lm需要什么样的对象。

【问题讨论】:

  • 我可以通过以下方式解决这个问题:new_lm &lt;- lm(unlist(select(df, !!xcol)) ~ unlist(select(df, !!ycol))) 但这很不优雅,问题仍然是我不明白非标准评估如何处理数据帧

标签: r tidyeval quosure


【解决方案1】:

您可以通过将公式的值粘贴在一起来创建公式,然后将公式传递给lm。我确信有更好的方法可以做到这一点,但这是一种可行的方法:


library(rlang)

my_lm <- function(df, xcol, ycol) {
  form <- as.formula(paste(ycol, " ~ ", xcol)[2])
  my_lm <- lm(form, data=df)
  my_lm
}

my_lm(mtcars, quo(wt), quo(mpg))
#> 
#> Call:
#> lm(formula = form, data = mtcars)
#> 
#> Coefficients:
#> (Intercept)           wt  
#>      37.285       -5.344

【讨论】:

    【解决方案2】:

    @zlipp 给出了一个可行的答案,但这里有一个更新的版本

    my_lm <- function(df, xcol, ycol) {
      xcol_e <- rlang::enquo(xcol)
      ycol_e <- rlang::enquo(ycol)
      form <- paste0(rlang::as_label(ycol_e), "~", rlang::as_label(xcol_e))
        new_lm <- lm(form, data=df)
        new_lm
    }
    my_lm(mtcars, wt, mpg)
    

    使用 rlang 代替粘贴

    my_lm <- function(.df, xcol, ycol) {
      form <- rlang::new_formula(rlang::ensym(ycol), rlang::ensym(xcol)) 
      new_lm <- lm(form, data=.df) 
      new_lm
    }
    my_lm(mtcars, wt, mpg)
    

    【讨论】:

    • rlang 版本如何与多个 xcol 一起使用,或者我应该将此作为新问题发布?例如。 xcols_e &lt;- lang::enquos(...)form &lt;- paste0(rlang::as_label(ycol_e), "~", paste(sapply(xcols_e, rlang::as_label), collapse = "+")).
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-23
    • 1970-01-01
    • 2016-09-18
    • 1970-01-01
    • 1970-01-01
    • 2018-08-01
    相关资源
    最近更新 更多