闭包中的lm的参数

时间:2018-10-17 13:58:24

标签: r

我在这里显然缺少对评估/环境的理解(我怀疑后者是这里的问题)。

考虑以下关闭:

lm_eqn <- function(df, indep, dep){

  lm(formula = dep ~ indep, data = df)
}

lm_eqn(iris, Sepal.Length, Sepal.Width)  ## does not work, throws error. 

我试图以多种方式引用/取消引用。这些都不成功,会引发不同的错误,并且对我没有任何帮助:

使用deparse(substitute(dep))

  

contrasts<-*tmp*中的错误,值= contr.funs [1 + isOF [nn]]):   对比只能应用于2个或更多级别的因素

使用quo(dep)enquo(dep)expr(dep)

  

model.frame.default中的错误(公式= dep〜indep,data = df,drop.unused.levels = TRUE):对象不是矩阵

在上面使用!!取消引用:

  

!dep错误:无效的参数类型

在函数体内指定公式的变量名是可行的:

lm_eqn2 <- function(df){

     lm(formula = Sepal.Length ~ Sepal.Width, data = df)
}

lm_eqn2(iris)

# Call:
# lm(formula = Sepal.Length ~ Sepal.Width, data = df)

# Coefficients:
# (Intercept)  Sepal.Width  
#     6.5262      -0.2234 

我想念什么?

4 个答案:

答案 0 :(得分:3)

您可以引用输入,然后在函数内部使用eval(as.name())

lm_eqn <- function(df, indep, dep){

  lm(formula = eval(as.name(dep)) ~ eval(as.name(indep)), data = df)
}

lm_eqn(iris, 'Sepal.Length', 'Sepal.Width')

答案 1 :(得分:3)

您可以将带引号和不带引号的列名与以下substitute技巧一起使用,这些技巧取自函数library的源,该方法也接受这两种方法。

lm_eqn <- function(df, indep, dep){
  indep <- as.character(substitute(indep))
  dep <- as.character(substitute(dep))
  fmla <- as.formula(paste(dep, indep, sep = "~"))
  lm(fmla, data = df)
}

lm_eqn(iris, 'Sepal.Length', 'Sepal.Width')
#
#Call:
#lm(formula = fmla, data = df)
#
#Coefficients:
# (Intercept)  Sepal.Length  
#     3.41895      -0.06188  
#

lm_eqn(iris, Sepal.Length, Sepal.Width)
#
#Call:
#lm(formula = fmla, data = df)
#
#Coefficients:
# (Intercept)  Sepal.Length  
#     3.41895      -0.06188  
#

答案 2 :(得分:3)

没有引号的方法:

> lm_eqn(iris, Sepal.Length, Sepal.Width)

Call:
lm(formula = dep ~ indep, data = df_lm)

Coefficients:
(Intercept)        indep  
    3.41895     -0.06188  

注意事项:不带引号的对象名称传递在视觉上是令人愉快的,但由于引入不稳定性,因此人们普遍对此表示反对。

代码

lm_eqn <- function(df_lm, indep, dep){
    df_lm <- eval(as.name(deparse(substitute(df_lm))))
    indep <- df_lm[, grep(deparse(substitute(indep)), colnames(df_lm))]
    dep <- df_lm[, grep(deparse(substitute(dep)), colnames(df_lm))]

    lm(formula = dep ~ indep, data = df_lm)
}

答案 3 :(得分:3)

如果要使公式在输出中保持漂亮,可以在整个调用中调用substitute,这将对变量名进行插值,然后在结果上调用eval以运行它:< / p>

lm_eqn <- function(data, x, y){
    eval(substitute(
        lm(formula = y ~ x, data = data)
    ))
}

lm_eqn(iris, Sepal.Width, Sepal.Length)
#> 
#> Call:
#> lm(formula = Sepal.Length ~ Sepal.Width, data = iris)    # <- pretty!
#> 
#> Coefficients:
#> (Intercept)  Sepal.Width  
#>      6.5262      -0.2234

或者要使其变得非常简单(并且更加灵活),只需直接传递一个公式即可:

lm_frm <- function(data, formula){
    lm(formula, data)
}

lm_frm(iris, Sepal.Length ~ Sepal.Width)
#> 
#> Call:
#> lm(formula = formula, data = data)
#> 
#> Coefficients:
#> (Intercept)  Sepal.Width  
#>      6.5262      -0.2234

lm中包装eval(substitute(...))调用也将使用这种方法来修复存储的调用结构。