0

Applying lmer() function across all columns in dataframe. I have made a list of variables and used lapply. Below is the code:

varlist=names(Genus_abundance)[5:ncol(Genus_abundance)]

lapply(varlist, function(x){lmer(substitute(i ~ Status + (1|Match), list(i=as.name(x), data=Genus_abundance, na.action = na.exclude)))})

However, I keep getting this error:

 Error in eval(predvars, data, env) : object 'Acetatifactor' not found

I have checked and Acetatifactor is in the Genus_abundance dataframe. Bit stuck about where its going wrong

EDIT: Added a working example:

set.seed(43)
n <- 6
dat <- data.frame(id=1:n, Status=rep(LETTERS[1:2], n/2), age= sample(18:90, n, replace=TRUE), match=1:n, Acetatifactor=runif(n), Acutalibacter=runif(n), Adlercreutzia=runif(n))

head(dat)
id Status age match Acetatifactor Acutalibacter Adlercreutzia
1  1      A  49     1     0.1861022     0.1364904     0.8626298
2  2      B  31     2     0.7297301     0.8246794     0.3169752
3  3      A  23     3     0.4118721     0.5923042     0.2592606
4  4      B  64     4     0.4140497     0.7943970     0.7422665
5  5      A  60     5     0.4803101     0.7690324     0.7473611
6  6      B  79     6     0.4274945     0.9180564     0.9179040
Fiona
  • 53
  • 7
  • 4
    To get a great answer quickly, include a [reproducible example](https://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example). – Kat Aug 23 '21 at 15:06
  • 1
    Even better - try this [question and answer](https://stackoverflow.com/questions/44295957/r-loop-multiple-independent-variables-through-a-mixed-effect-model). – Kat Aug 23 '21 at 15:13

1 Answers1

2
lapply(varlist,
       function(x){lmer(substitute(i ~ status + (1|match), list(i=as.name(x))),
   data=dd)
})

The specific problem here is misplaced parentheses. You should close the substitute(..., list(i=as.name(x))) with three close-parentheses so that the whole chunk is properly understood as the first argument to lme4.

More generally I agree with @Kat in the comments that this is a good place to look. Since your arguments are already strings (not symbols) you don't really need all of the substitute() business and could use

fit_fun <- function(v) {
   lmer(reformulate(c("status", "(1|match)"), response = v),
        data = dd, na.action = na.exclude)
}
lapply(varlist, fit_fun)

Or you could use refit to fit the first column, then update the fit with each of the next columns. For large models this is much more efficient.

m1 <- lmer(resp1 ~ status + (1|match), ...)
m_other <- lapply(dd[-(1:3)], refit, object = m1)
c(list(m1), m_other)
Ben Bolker
  • 211,554
  • 25
  • 370
  • 453
  • Thank you, I see the issue ```list()``` was part of the first argument of lmer – Fiona Aug 23 '21 at 15:31
  • Great. I do recommend taking at look at the other solutions provided here - IMO they're more robust and more efficient than your current setup with `substitute` etc. (although I agree that your current setup should work fine if you don't have complicated workflow and your data are not large) – Ben Bolker Aug 23 '21 at 15:34
  • @BenBolker Where does the "here" refer to? – MrFlick Aug 23 '21 at 17:14
  • "here" means "in this answer". (i.e., I'm encouraging the OP to look beyond the proximal fix-my-parentheses solution I provided first, to the other solutions provided) – Ben Bolker Aug 23 '21 at 18:21