我在这里显然缺少对评估/环境的理解(我怀疑后者是这里的问题)。
考虑以下关闭:
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
我想念什么?
答案 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(...))
调用也将使用这种方法来修复存储的调用结构。