Function which runs lm over different variables

You can fix this problem by using the quo_name's and formula:

lmfun <- function(data, y, x) {
  y <- enquo(y)
  x <- enquo(x)

  model_formula <- formula(paste0(quo_name(y), "~", quo_name(x)))
  lm(model_formula, data = data)
}

lmfun(mtcars, mpg, disp)

# Call:
#   lm(formula = model_formula, data = data)
# 
# Coefficients:
#   (Intercept)         disp  
#      29.59985     -0.04122  

If the arguments are unquoted, then convert to symbol (sym) after changing the quosure to string (quo_name) and evaluate the expression in lm (similar to the OP's syntax of lm)

library(rlang)
lmfun <- function(data, y, x) {
  y <- sym(quo_name(enquo(y)))
  x <- sym(quo_name(enquo(x)))
  expr1 <- expr(!! y ~ !! x)

  model <- lm(expr1, data = data)
  model$call$formula <- expr1 # change the call formula
  model
}

lmfun(mtcars, mpg, disp)
#Call:
#lm(formula = mpg ~ disp, data = data)

#Coefficients:
#(Intercept)         disp  
#   29.59985     -0.04122  

An option if we are passing strings would be convert to symbols with ensym and then quote it in lm

lmfun <- function(data, y, x) {
  y <- ensym(y)
  x <- ensym(x)
  expr1 <- expr(!! y ~ !! x)

  model <- lm(expr1, data = data)
  model$call$formula <- expr1 # change the call formula
  model

}

lmfun(mtcars, 'mpg', 'disp')
#Call:
#lm(formula = mpg ~ disp, data = data)


#Coefficients:
#(Intercept)         disp  
#   29.59985     -0.04122  

NOTE: Both the options are from tidyverse


Another solution:

lmf2 <- function(data,y,x){
  fml <- substitute(y~x, list(y=substitute(y), x=substitute(x)))
  lm(eval(fml), data)
}

lmf2(mtcars, mpg, disp)
# Call:
# lm(formula = eval(fml), data = data)
# 
# Coefficients:
# (Intercept)         disp  
#    29.59985     -0.04122  

Or, equivalently:

lmf3 <- function(data,y,x){
  lm(eval(call("~", substitute(y), substitute(x))), data)
}

Tags:

R

Lm

Quosure