Skip to content
Prev 11441 / 20628 Next

lme4: constrain sigma to 0

If you are really masochistic, you could trick the rma.mv() function from the 'metafor' package to fit such a model (in meta-analyses, you fix the variances of the residuals to known values -- and here, we could set those values to 0).

As an example, let me follow up on what Rolf Turner wanted to do:
##################################################################

library(metafor)
library(nlme)
library(lme4)

data(Orthodont)

V0 <- rep(0, nrow(Orthodont))

res1 <- rma.mv(distance ~ age, V=V0, random = ~ age | Subject, struct="UN", data=Orthodont, control=list(optimizer="nlminb", REMLf=FALSE))
summary(res1)

res2 <- lme(distance ~ age, random = ~ factor(age) - 1 | Subject, data=Orthodont)
summary(res2)

res3 <- gls(distance ~ age, correlation = corSymm(form = ~ 1 | Subject), weights = varIdent(form = ~ 1 | age), data=Orthodont)
summary(res3)

res4 <- lmer(distance ~ age + (factor(age) - 1 | Subject), data=Orthodont)
summary(res4)

# Note that lme() and lmer() also fit this model, but here the residual variance is being estimated. 
# As mentioned earlier by Rolf Turner, that model is actually over-parameterized. Marginally, you end 
# up with the same fit though:

logLik(res1)
logLik(res2)
logLik(res3)
logLik(res4)

# So, lme() and lmer() are splitting up the variance along the diagonal into variance due to the random 
# effects and residual variance. Added up, this yields the same values as with rma.mv() and gls():

round(res1$tau2, 4)
round(as.numeric(VarCorr(res2)[1:4,1]) + res2$sigma^2, 4)
round(unname(c(res3$sigma^2, (res3$sigma * coef(res3$modelStruct, unconstrained=FALSE)[7:9])^2)), 4)
round(unname(diag(VarCorr(res4)[[1]]) + sigma(res4)^2), 4)

# But the split is arbitrary and depends on how the optimization is done:

res2$sigma
sigma(res4)

##################################################################

A few more notes:

1) I had to switch to 'nlminb' for rma.mv() since the default ('optim' with 'Nelder-Mead') did not converge and gave strange results when it did (by increasing the number of iterations).

2) With REMLf=FALSE, a particular constant term is left out from the REML likelihood that is also not included in the likelihood computation for the other functions.

3) rma.mv() is slow as it was never intended for this. But it does work. In other cases, it may not.

Best,
Wolfgang

--   
Wolfgang Viechtbauer, Ph.D., Statistician   
Department of Psychiatry and Psychology   
School for Mental Health and Neuroscience   
Faculty of Health, Medicine, and Life Sciences   
Maastricht University, P.O. Box 616 (VIJV1)   
6200 MD Maastricht, The Netherlands   
+31 (43) 388-4170 | http://www.wvbauer.com