Consider the following function:
lm_eqn <- function(df, indep, dep){
lm(formula = dep ~ indep, data = df)
}
lm_eqn(iris, Sepal.Length, Sepal.Width) ## does not work, throws error.
I tried to quote/unquote in several ways. None of those were succesful, throwing different errors and none of them were exactly helpful for me:
Using deparse(substitute(dep))
Error in
contrasts<-(*tmp*, value = contr.funs[1 + isOF[nn]]) : contrasts can be applied only to factors with 2 or more levels
Using quo(dep) or enquo(dep) or expr(dep)
Error in model.frame.default(formula = dep ~ indep, data = df, drop.unused.levels = TRUE) : object is not a matrix
Using above with unquoting using !!:
Error in !dep : invalid argument type
Specifying the variable names for the formula within the function body works:
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
What am I missing?
If you want to keep the formula in the output pretty, you can call substitute on the whole call, which will interpolate the variable names, then call eval on the result to run it:
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
Or to make it all really simple (and a lot more flexible), just pass a formula directly:
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
Wrapping the lm call in eval(substitute(...)) will fix the stored call structure with this approach, too.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With