llewmills
llewmills

Reputation: 3568

Passing variable names as strings into the contrasts() argument in lm

I am trying to create a function that allows me to pass outcome and predictor variable names as strings into the lm() regression function. I have actually asked this before here, but I learned a new technique here and would like to try and apply the same idea in this new format.

Here is the process

library(tidyverse)

# toy data
df <- tibble(f1 = factor(rep(letters[1:3],5)),
             c1 = rnorm(15),
             out1 = rnorm(15))

# pass the relevant inputs into new objects like in a function 
d <- df
outcome <- "out1"
predictors <- c("f1", "c1")

# now create the model formula to be entered into the model
form <- as.formula(
    paste(outcome,
          paste(predictors, collapse = " + "),
          sep = " ~ "))


# now pass the formula into the model
model <- eval(bquote( lm(.(form), 
                         data = d) ))

model

# Call:
#   lm(formula = out1 ~ f1 + c1, data = d)
# 
# Coefficients:
#   (Intercept)          f1b          f1c           c1  
#       0.16304     -0.01790     -0.32620     -0.07239 

So this all works nicely, an adaptable way of passing variables into lm(). But what if we want to apply special contrast coding to the factorial variable? I tried

model <- eval(bquote( lm(.(form), 
                         data = d,
                         contrasts = list(predictors[1] = contr.treatment(3)) %>% setNames(predictors[1])) ))

But got this error

Error: unexpected '=' in:
"                                                 data = d,
                                                 contrasts = list(predictors[1] ="

Any help much appreciated.

Upvotes: 2

Views: 180

Answers (1)

GobiJerboa
GobiJerboa

Reputation: 185

Reducing this to the command generating the error:

list(predictors[1] = contr.treatment(3))

Results in:

Error: unexpected '=' in "list(predictors[1] ="

list() seems to choke when the left-hand side naming is a variable that needs to be evaluated.

Your approach of using setNames() works, but needs to be wrapped around the list construction step itself.

setNames(list(contr.treatment(3)), predictors[1])

Output is a named list containing a contrast matrix:

$f1
  2 3
1 0 0
2 1 0
3 0 1

Upvotes: 1

Related Questions