pa_ka
pa_ka

Reputation: 65

How to get covariance matrix for random effects (BLUPs/conditional modes) from lme4

So, I've fitted a linear mixed model with two random intercepts in R:

Y = X beta  + Z b + e_i, 

where b ~ MVN (0, Sigma); X and Z are the fixed- and random-effects model matrices respectively, and beta and b are the fixed-effect parameters and random-effects BLUPs/conditional modes.

I would like to get my hands on the underlying covariance matrix of b, which doesn't seem to be a trivial thing in lme4 package. You can get only the variances by VarCorr, not the actual correlation matrix.

According to one of the package vignettes (page 2), you can calculate the covariance of beta: e_i * lambda * t(lambda). And all those components you can extract from the output of lme4.

I was wondering if this is the way to go? Or do you have any other suggestions?

Upvotes: 6

Views: 4246

Answers (1)

Ben Bolker
Ben Bolker

Reputation: 226162

From ?ranef:

If ‘condVar’ is ‘TRUE’ each of the data frames has an attribute called ‘"postVar"’ which is a three-dimensional array with symmetric faces; each face contains the variance-covariance matrix for a particular level of the grouping factor. (The name of this attribute is a historical artifact, and may be changed to ‘condVar’ at some point in the future.)

Set up an example:

library(lme4)
fm1 <- lmer(Reaction ~ Days + (Days | Subject), sleepstudy)
rr <- ranef(fm1,condVar=TRUE)

Get the variance-covariance matrix among the b values for the intercept

pv <- attr(rr[[1]],"postVar")
str(pv)
##num [1:2, 1:2, 1:18] 145.71 -21.44 -21.44 5.31 145.71 ...

So this is a 2x2x18 array; each slice is the variance-covariance matrix among the conditional intercept and slope for a particular subject (by definition, the intercepts and slopes for each subject are independent of the intercepts and slopes for all other subjects).

To convert this to a variance-covariance matrix (see getMethod("image",sig="dgTMatrix") ...)

library(Matrix)
vc <- bdiag(  ## make a block-diagonal matrix
            lapply(
                ## split 3d array into a list of sub-matrices
                split(pv,slice.index(pv,3)),
                   ## ... put them back into 2x2 matrices
                      matrix,2)) 
image(vc,sub="",xlab="",ylab="",useRaster=TRUE)

enter image description here

Upvotes: 5

Related Questions