1 License

This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License (http://creativecommons.org/licenses/by-sa/4.0/).

The R markdown source for this document is https://www.stat.umn.edu/geyer/5421/notes/random.Rmd.

2 CRAN

Another name for random effects models is mixed models.

CRAN has a task view https://cran.r-project.org/view=MixedModels listing many packages doing some sort of random effects models.

We use four of them.

3 R

library(CatDataAnalysis)
library(MASS)
library(lme4)
## Loading required package: Matrix
library(glmm)
## Loading required package: trust
## Loading required package: mvtnorm
## Loading required package: parallel
## Loading required package: doParallel
## Loading required package: foreach
## Loading required package: iterators
library(parallel)
library(aster)
# need bug fix
stopifnot(compareVersion(as.character(packageVersion("aster")), "1.3-8") >= 0)
library(numDeriv)

Set random number generator seed for reproducibility.

set.seed(42)

4 Random Effects Models (Mixed Models)

A statistical model becomes a random effects model when you start with a parametric statistical model and the reconsider some of the parameters turning them into random variables. To distinguish

In order to complete the specification of a statistical model, we need a distribution for the random effects. Usually, they are considered independent and normally distributed but sometimes also dependent and normally distributed.

4.1 Linear Mixed Models (LMM)

When we have both fixed effects and random effects, this is also called a mixed model. And when the model we started with was a linear model (LM) we say we have a linear mixed model (LMM).

LMM are not really in what this course is about, since they have continuous rather than categorical response. But they are much simpler, so we start there to get some intuition. We are following Oehlert (2010), Section 11.1 and 11.2.

Here is a simple example. Suppose we have data on patients and each patient is observed multiple times. Typically there will be some variability of the observations on one patient, and this may be much less than the between patient variability. So we have two levels of variability.

Here is the model in equations. Denote the components of the response vector as a matrix \(y_{i j}\) where \(i\) indexes patients and \(j\) indexes different measurements on each patient. Then we assume \[\begin{equation} y_{i j} = \mu_i + b_i + e_{i j} \tag{4.1} \end{equation}\] where

  • the \(\mu_i\) are the fixed effects,

  • the \(b_i\) are the random effects, assumed to be independent normal with mean zero and variance \(\sigma^2\), and

  • the \(e_{i j}\) are the errors, assumed to be independent normal with mean zero and variance \(\tau^2\).

The components of the response vector are still multivariate normal but are no longer independent. Rather we have \[\begin{alignat*}{2} \mathop{\rm var}(y_{i j}) & = \sigma^2 + \tau^2 \\ \mathop{\rm cov}(y_{i j}, y_{i k}) & = \sigma^2, & \qquad j \neq k \\ \mathop{\rm cov}(y_{i j}, y_{k m}) & = 0, & \qquad i \neq j \end{alignat*}\]

Estimating this is more or less like conventional ANOVA with minor differences. Oehlert (2010), Display 11.1, gives the following ANOVA table

Source DF EMS
Patients \(m - 1\) \(\tau^2 + m \sigma^2\)
Error \(N - m\) \(\tau^2\)

Here \(N\) is the total number of observations and \(m\) is the number of observations per individual.

This means the error sum of squares \[ \tfrac{1}{N - m} \sum\nolimits_{i j} (y_{i j} - \hat{\mu}_i)^2 \] is an unbiased estimator of \(\tau^2\), where \(\hat{\mu}_i\) is the average (sample mean) of the observations for patient \(i\). And the patient sum of squares \[ \tfrac{1}{m - 1} \sum\nolimits_i ( \hat{\mu}_i - \hat{\hat{\mu}})^2 \] where \(\hat{\hat{\mu}}\) is the average (sample mean) of all the observations, is an unbiased estimator of \(\tau^2 + m \sigma^2\).

But, of course, we don’t want to estimate that, so we subtract \[\begin{equation} \frac{1}{m} \left[ \left( \tfrac{1}{m - 1} \sum\nolimits_i ( \hat{\mu}_i - \hat{\hat{\mu}})^2 \right) - \left( \tfrac{1}{N - m} \sum\nolimits_{i j} (y_{i j} - \hat{\mu}_i)^2 \right) \right] \tag{4.2} \end{equation}\] is an unbiased estimate of \(\sigma^2\).

We already see a complication. Because of the subtraction in (4.2), it can give a negative estimate of variance, which is ridiculous.

So even in this simplest case, things are trickier than they seem at first sight. We should write down the log likelihood for the model and maximize it subject to the constraints \(\sigma^2 \ge 0\) and \(\tau^2 \ge 0\). We can always write down the log likelihood because the joint distribution of \(y\) and \(u\) is multivariate normal, hence so is the marginal distribution of \(y\) (because every marginal of a multivariate normal is again multivariate normal). And we can write as an R function the log likelihood for any multivariate normal distribution. It involves matrix inverses and determinants, but R knows how to do them. \[ l(\theta) = - \tfrac{1}{2} \log(\mathop{\rm det}(M(\theta))) - \tfrac{1}{2} (y - \mu(\theta))^T M(\theta)^{-1} (y - \mu(\theta)) \] where the distribution of \(y\) is multivariate normal with mean vector \(\mu(\theta)\) and variance matrix \(M(\theta)\).

4.2 Generalized Linear Mixed Models (GLMM)

The next step is generalized linear mixed models (GLMM), which were introduced by Stiratelli et al. (1984), although earlier authors had steps in that direction. We get GLMM from GLM in the same way we get LMM from LM: start with a parametric statistical model and the reconsider some of the parameters turning them into random variables.

Start with the model equation for a canonical affine submodel, which we copy here \[\begin{equation} \theta = a + M \beta \tag{4.3} \end{equation}\] where \(\theta\) is the saturated model canonical parameter vector, \(a\) the offset vector, \(M\) the model matrix, and \(\beta\) the submodel canonical parameter vector.

Now we want to turn some components into random effects. We denote this by writing what was \(\beta\) as a partitioned vector \((\beta, b)\) where now \(\beta\) is the fixed effects vector and \(b\) is the random effects vector. This means we have to also write the model matrix as a partitioned matrix \((M, Z)\) where now \(M\) is the model matrix for fixed effects and \(Z\) is the model matrix for random effects. \[\begin{equation} \theta = a + M \beta + Z b \tag{4.4} \end{equation}\] We could divide up the random effects even farther, writing \[\begin{equation} \theta = a + M \beta + \sigma_1 Z_1 u_1 + \cdots + \sigma_k Z_k u_k \tag{4.5} \end{equation}\] where now the random effects \(u_1\), \(\ldots,\) \(u_k\) all have independent standard normal components, and we see the standard deviation parameters explicitly.

In (4.4) the variance parameters are not explicit. They are implicit in \[ D = \mathop{\rm var}(b) \] Since the components of \(b\) are independent, \(D\) is a diagonal matrix. Let \(\nu_i = \sigma_i^2\). These parameters are called variance components. Thus the parameters of a random effects model are (to a frequentist)

  • the fixed effects (the components of \(\beta\)) and

  • the variance components (the \(\nu_i\)) or their square roots (the \(\sigma_i)\)

(of course, Bayesians also consider the random effects parameters). To keep straight which variance components go with which random effects, we define \[ E_i = \frac{\partial D}{\partial \nu_i} \] so \[ D = \sum_{i = 1}^k \nu_i E_i \] and we see that each diagonal component of \(D\) is some variance component and each \(E_i\) is a diagonal matrix with zero-or-one-valued diagonal components and \(E_i E_j = 0\) if \(i \neq j\) and \(\sum_i E_i\) is the identity matrix.

Note well that although we are assuming \(b\) has independent components (so \(D\) is diagonal), this does not mean that \(Z b\) has independent components. Its variance matrix is \[ \mathop{\rm var}(Z b) = E (Z b b^T Z^T) = Z \mathop{\rm var}(b b^T) Z^T = Z^T D Z \] and that is not (in general) a diagonal matrix. Hence the components of \(Z b\) are not independent.

The other parts of a GLMM are the same as a GLM (the link function, the family, and so forth).

4.3 Exponential Family Mixed Models (EFMM)

All of the preceding section except the last sentence extends to arbitrary exponential family models Geyer et al. (2013), with one proviso. The full canonical parameter space of the model need not be a whole vector space (the negative binomial distribution provides an example). But the random effects (if assumed normal) take values that can be any real number. Thus the proviso is that the function (4.4) map into the full canonical parameter space for any real-valued vector \(b\).

5 Random Effects, Missing Data, Etc.

5.1 Theory

A random effects model is a statistical in which some of the random variables are observed and other random variables are not. The latter are called random effects. But the same kind of model occurs in many contexts and these unobserved random variables have been given many different names in different contexts: missing data, latent variables, hidden variables, parameters (in so-called empirical Bayes)

It does not matter what they are called, the data comes in two parts \(x\) and \(y\), where \(y\) is the observed data and \(x\) is unobserved, whether unobservable (when we say random effects, latent variables, or hidden variables) or whether could have been observed but wasn’t (when we say missing data). And we assume it is easy to write down the joint distribution.

But likelihood theory says the likelihood is the probability of the observed data thought of as a function of the parameter vector. So we must eliminate \(x\), that is, we need the marginal distribution of \(y\). When \(x\) is a continuous random vector, we need to do an integral. \[\begin{equation} f_\theta(y) = \int f_\theta(x, y) \, d x \tag{5.1} \end{equation}\] where, if \(x\) is a vector, this is a multiple integral. Then taking logs gives the log likelihood \[\begin{equation} l(\theta) = \log \left( \int f_\theta(x, y) \, d x \right) \tag{5.2} \end{equation}\] There is no question that this is the Right Thing with a capital R and a capital T. Likelihood theory (our course notes here and here and Geyer (2013) and references cited therein) says that maximizers of (5.2) are consistent and asymptotically normal with asymptotic variance matrix inverse Fisher information matrix, and no estimators can be (asymptotically) better.

5.2 Computation

But there is a problem (except for LMM, where we can do the integral in (5.2) because every marginal of a multivariate normal distribution is again multivariate normal): we can almost never do the integral in (5.2); it is not found in any calculus book.

5.2.1 Monte Carlo

We can do the integral by Monte Carlo, either Markov chain Monte Carlo (MCMC) (Thompson and Guo (1991); Geyer (1994); Booth and Hobert (1999)) or ordinary Monte Carlo (OMC) (Sung and Geyer (2007); Knudson et al. (2021)).

5.2.2 Numerical Integration

We can do the integral by so-called numerical integration (https://cran.r-project.org/view=NumericalMathematics) but when the integral is high-dimensional, this is too slow. There is one special case where we can do numerical integration: when there is only one random effect involved in each observation. Then the multiple integral breaks up into a product of univarate integrals, and these can be done efficiently by numerical integration. There is even a special method for integrating out normal random effects called Gauss-Hermite quadrature (CRAN package fastGHQuad to do these univariate integrals. But this method is no help when there is more than one random effect involved in each observation (so-called crossed random effects).

5.2.3 Laplace Approximation

We can do the integral by so-called Laplace approximation Wikipedia article following Breslow and Clayton (1993) and Geyer et al. (2013). This works as follows. Let \(l(\,\cdot\,)\) be the saturated model log likelihood and \(W(\,\cdot\,)\) be its second derivative. Then the integral (5.1) becomes \[\begin{equation*} \int \exp\left( l(a + M \beta + Z b) - \tfrac{1}{2} b^T D^{-1} b - \tfrac{1}{2} \log \mathop{\rm det}(D) \right) \, d b \end{equation*}\] The method of Laplace approximation procedes in two steps. First we find the point \(b\) where the integrand is highest; call that \(b^*\). Note that \(b^*\) is a function of \(\beta\) and \(\nu\) even though the notation does not indicate that. Then replace the log of the integrand with its best quadratic approximation (the Taylor series up to quadratic terms). This gives the integral \[\begin{equation} \int \exp\left( l(a + M \beta + Z b^*) + \tfrac{1}{2} (b - b^*)^T \bigl[ Z^T W(a + M \beta + Z b^*) Z - D^{-1} \bigr] (b - b^*) - \tfrac{1}{2} \log \mathop{\rm det}(D) \right) \, d b \tag{5.3} \end{equation}\] The point of this is that because now the integrand in (5.3) is now the exponential of a function quadratic in \(b\). Hence it is the kind of integral that occurs in calculating the marginal distribution of a multivariate normal distribution. Hence it can be done in closed form giving \[\begin{equation} l_\text{approx}(\beta, \nu) = l(a + M \beta + Z b^*) - \tfrac{1}{2} (b^*)^T D^{-1} b^* - \log \mathop{\rm det} \bigl[ Z^T W(a + M \beta + Z b^*) Z D + \text{Id} \bigr] \tag{5.4} \end{equation}\] where \(\text{Id}\) denotes the identity matrix of the appropriate dimension. But this is still too hard to maximize because we need derivatives of \(l_\text{approx}(\,\cdot\,)\) to find solutions and Fisher information, and don’t know derivatives of \(W(\,\cdot\,)\) (they do exist but are horribly messy). Hence we make, following Breslow and Clayton (1993), yet another approximation, treating \(W(\,\cdot\,)\) as a constant function having the value \(W^*\). This gives us \[\begin{equation} l_\text{approx}(\beta, \nu) = l(a + M \beta + Z b^*) - \tfrac{1}{2} (b^*)^T D^{-1} b^* - \log \mathop{\rm det} \bigl[ Z^T W^* Z D + \text{Id} \bigr] \tag{5.5} \end{equation}\] as our approximation to the log likelihood for the random effects model.

So we maximize (5.5) to find (approximate) maximum likelihood parameter estimates \(\hat{\beta}\) and \(\hat{\nu}\). But then we note that we used the wrong \(W^*\). So we set \[ W^* = W(a + M \hat{\beta} + Z b^*(\hat{\beta}, \hat{\nu})) \] and then re-optimize (5.5) and keep repeating this until \(W^*\) does not change (much).

This gives us estimates (even standard errors, Geyer et al. (2013), Section 2) but they are based on approximations of unknown validity. It is true that log likelihoods get approximately quadratic as sample size goes to infinity (so says the theory of maximum likelihood, Geyer (2013), Appendix C) but if \(b\) is a high-dimensional vector the sample size may need to be exceedingly large for Laplace approximation to be good. The second approximation, treating \(W(\,\cdot\,)\) as a constant function follows from the first: a quadratic function does have a constant second derivative function. But again sample size may need to be exceedingly large for this approximation to be good.

As always, if you distrust these large sample approximations, bootstrap! That what Geyer et al. (2013), Sections 5 and 8, recommend. Unfortunately, fitting these models is time-consuming, and bootstrap is even more so. Thus most users don’t bootstrap.

The main point of this section is not the mathematical details. It is that this is an approximation of unknown validity. We have changing from doing the actual random effects problem to an easier problem that is (hopefully) related.

5.2.4 CRAN Packages

  • R function glmmPQL in R package MASS uses Laplace approximation.

  • R function glmer in R package lme4 uses Laplace approximation if there are crossed random effects and Gauss-Hermite quadrature otherwise.

  • R function glmm in R package glmm uses ordinary Monte Carlo.

  • R function reaster in R package aster uses Laplace approximation.

6 Example: Overdispersed Binomial

6.1 Data

We use the following data from Agresti.

data(table_13.2)
head(table_13.2)
##   state    pi   n   x proportion
## 1    AK 0.379   5   3  0.6000000
## 2    AL 0.387  29   9  0.3103448
## 3    AR 0.389  17   2  0.1176471
## 4    AZ 0.449  35  13  0.3714286
## 5    CA 0.609 207 129  0.6231884
## 6    CO 0.537  37  16  0.4324324
resp <- with(table_13.2, cbind(x, n - x))

Clearly what is \(T\) in the book is \(n\) in R.

What we have here is overdispersed binomial data. Each state has a different proportion of voters voting for Obama. So this is a competitor for analyses using R function glm with family quasibinomial. The difference is that here we have a real statistical model (the random effects model), and the quasi-likelihood approach does not.

So we could have used any of the analyses below for problem 4.13 in Agresti (which was our homework problem 4-4).

6.2 GlmmPQL

gout <- glmmPQL(resp ~ 1, ~ 1 | state, family = binomial, data = table_13.2)
## iteration 1
## iteration 2
## iteration 3
summary(gout)
## Linear mixed-effects model fit by maximum likelihood
##   Data: table_13.2 
##   AIC BIC logLik
##    NA  NA     NA
## 
## Random effects:
##  Formula: ~1 | state
##         (Intercept) Residual
## StdDev:   0.1974425 1.429759
## 
## Variance function:
##  Structure: fixed weights
##  Formula: ~invwt 
## Fixed effects:  resp ~ 1 
##                  Value  Std.Error DF   t-value p-value
## (Intercept) 0.06679477 0.07459273 51 0.8954596  0.3747
## 
## Standardized Within-Group Residuals:
##        Min         Q1        Med         Q3        Max 
## -2.1297601 -0.6454223  0.1034602  0.5145442  1.5567157 
## 
## Number of Observations: 51
## Number of Groups: 51

That is clear as mud, but (from the examples in the help) the way this function is supposed to be used.

6.3 Glmer

gout.too <- glmer(resp ~ 1 + 1 | state, family = binomial, data = table_13.2)
sout <- summary(gout.too)
sout
## Generalized linear mixed model fit by maximum likelihood (Laplace
##   Approximation) [glmerMod]
##  Family: binomial  ( logit )
## Formula: resp ~ 1 + 1 | state
##    Data: table_13.2
## 
##       AIC       BIC    logLik -2*log(L)  df.resid 
##     288.9     292.8    -142.5     284.9        49 
## 
## Scaled residuals: 
##     Min      1Q  Median      3Q     Max 
## -1.9780 -0.3909  0.1121  0.3454  1.7044 
## 
## Random effects:
##  Groups Name        Variance Std.Dev.
##  state  (Intercept) 0.1721   0.4149  
## Number of obs: 51, groups:  state, 51
## 
## Fixed effects:
##             Estimate Std. Error z value Pr(>|z|)
## (Intercept)  0.03027    0.08182    0.37    0.711

This makes a lot more sense. The fixed effect estimate

sout$coefficients
##               Estimate Std. Error   z value  Pr(>|z|)
## (Intercept) 0.03027032 0.08181548 0.3699828 0.7113953

corresponds to the mean value parameter

invlogit <- function(theta) 1 / (1 + exp(- theta))
sout$coefficients[ , "Estimate"] |> invlogit()
## [1] 0.507567

And we can make a Wald confidence interval.

conf.level <- 0.95
crit <- qnorm((1 + conf.level) / 2)
crit
## [1] 1.959964
(sout$coefficients[ , "Estimate"] + c(-1, 1) * crit *
sout$coefficients[ , "Std. Error"]) |> invlogit()
## [1] 0.4675245 0.5475126

using the trick of mapping the Wald interval from the canonical to the mean value parameter that we saw in Chapter Zero.

6.3.1 Comparison with glm, family = binomial

Note that this confidence interval is very different from the intro stats interval

pi.hat <- with(table_13.2, sum(x) / sum(n))
pi.hat
## [1] 0.5245
n <- with(table_13.2, sum(n))
(pi.hat + c(-1, 1) * crit * sqrt(pi.hat * (1 - pi.hat) / n))
## [1] 0.5026133 0.5463867

Both the point estimate and the confidence interval are different. Our interval from glmer uses the heterogeneity of the states. The intro stats interval assumes the states are homogenous (all have exactly the same proportion of vote for this candidate, which is an obviously false assumption).

6.3.2 Comparison with glm, family = quasi-binomial

gout.over <- glm(resp ~ 1, family = quasibinomial, data = table_13.2)
pout.over <- predict(gout.over, se.fit = TRUE, type = "response",
    newdata = data.frame(state = "AK"))
# point estimate
pout.over$fit
##      1 
## 0.5245
# 95% confidence interval
pout.over$fit + c(-1, 1) * crit * pout.over$se.fit
## [1] 0.4900696 0.5589304

We see, as explained in the notes about quasi-likelihood, that quasi-likelihood has the same point estimates as likelihood, even though this is wrong for any actual model of overdispersion. We have now looked at two models of overdispersion

and both change the point estimate, not just its standard error.

6.3.3 Comments

There does not seem to be any programmatic access to the estimate of the variance component and its standard error (which the summary function does print but does not put in the returned object). This is bad design.

It says it uses Laplace approximation rather than Gauss-Hermite quadrature, even though the function help says the opposite. What does it do? Are these accurate estimates or not?

6.4 Glmm

gout.too.too <- glmm(resp ~ 1, ~ 0 + state, data = table_13.2,
     family = binomial.glmm, m = 1e6, varcomps.names = "state")
 summary(gout.too.too)
## 
## Call:
## glmm(fixed = resp ~ 1, random = ~0 + state, varcomps.names = "state", 
##     data = table_13.2, family.glmm = binomial.glmm, m = 1e+06)
## 
## 
## Link is: "logit (log odds)"
## 
## Fixed Effects:
##             Estimate Std. Error z value Pr(>|z|)
## (Intercept)        0          0   0.359     0.72
## 
## 
## Variance Components for Random Effects (P-values are one-tailed):
##       Estimate Std. Error z value Pr(>|z|)/2   
## state        0          0   2.482    0.00653 **
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

This looks like nonsense, but the estimates are not actually zero. A look inside the code reveals that it is trying to round the printout to the number of significant figures it accurately calculates, and here that is no significant figures. The estimates themselves are not actually zero.

gout.too.too$beta
## (Intercept) 
##  0.03045109
gout.too.too$nu
##     state 
## 0.1767598

Nor are the estimates of standard errors

vcov(gout.too.too) |> diag() |> sqrt()
## (Intercept)       state 
##  0.08490472  0.07121765

Nor are the estimates of Monte Carlo standard errors

mcse(gout.too.too)
## (Intercept)       state 
##         NaN         NaN

Hmmmm. Something wrong there. Maybe that is the source of the bug.

6.5 Reaster

R package aster is not really designed for this, but can do it.

dat <- with(table_13.2,
    data.frame(root = n, resp = x, state = state,
        varb = factor(rep("only", length(state))),
        id = seq_along(state)))
head(dat)
##   root resp state varb id
## 1    5    3    AK only  1
## 2   29    9    AL only  2
## 3   17    2    AR only  3
## 4   35   13    AZ only  4
## 5  207  129    CA only  5
## 6   37   16    CO only  6
rout <- reaster(resp ~ 1, list(state = ~ 0 + state), pred = 0, fam = 1,
    varb, id, root, data = dat)
summary(rout, standard.deviation = FALSE)
## 
## Call:
## reaster.formula(fixed = resp ~ 1, random = list(state = ~0 + 
##     state), pred = 0, fam = 1, varvar = varb, idvar = id, root = root, 
##     data = dat)
## 
## 
## Fixed Effects:
##             Estimate Std. Error z value Pr(>|z|)
## (Intercept)  0.03035    0.08047   0.377    0.706
## 
## Variance Components (P-values are one-tailed):
##       Estimate Std. Error z value Pr(>|z|)/2   
## state  0.16512    0.07049   2.342    0.00958 **
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

We see that the estimates and standard errors more or less agree between R function glmer and R function reaster which is perhaps no suprise since they may be using the same method (unless glmer is using Gauss-Hermite quadrature, contrary to what the summary says).

But we were not able to compare with a function that does exact results for sufficient Monte Carlo sample size.

6.6 Prediction

6.6.1 Methods of the Generic

It is very unclear what “prediction” (in scare quotes) even means for a random effects model. What should R generic function predict even do for these model fits? Do methods even exist?

try(getS3method("predict", class(gout)[1]), silent = TRUE) |> is.function()
## [1] TRUE
try(getS3method("predict", class(gout.too)[1]), silent = TRUE) |> is.function()
## [1] FALSE
try(getS3method("predict", class(gout.too.too)[1]), silent = TRUE) |> is.function()
## [1] FALSE
try(getS3method("predict", class(rout)[1]), silent = TRUE) |> is.function()
## [1] FALSE

Only one has methods of predict for its results.

6.6.2 What Could Prediction Even Mean?

Prediction could mean

  • the unconditional expectation of the quantity being predicted,

  • the conditional expectation of the quantity being predicted given the observed data for that case,

  • a conditional mode if this is easier to do, or

  • many other ideas.

6.6.3 A Prediction

Here we will pick the last option to get per state predictions. R function reaster output contains a component b that is the conditional modes of the conditional distribution of the random effects given the observed data.

rout$b
##      stateAK      stateAL      stateAR      stateAZ      stateCA      stateCO 
##  0.063256937 -0.432795309 -0.651131912 -0.323091751  0.420667615 -0.181851750 
##      stateCT      stateDC      stateDE      stateFL      stateGA      stateHI 
##  0.106583691  0.279502729  0.126385522  0.211962776 -0.164241860  0.314222041 
##      stateIA      stateID      stateIL      stateIN      stateKS      stateKY 
## -0.226845271 -0.478529236  0.087427893 -0.079657141 -0.152219599 -0.323763255 
##      stateLA      stateMA      stateMD      stateME      stateMI      stateMN 
## -0.312895098 -0.216947551  0.551520963  0.389876483  0.136920711 -0.019575461 
##      stateMO      stateMS      stateMT      stateNC      stateND      stateNE 
##  0.124929007  0.076767385 -0.070860589 -0.470647614 -0.073633402  0.434353605 
##      stateNH      stateNJ      stateNM      stateNV      stateNY      stateOH 
## -0.293850221  0.098766325  0.043139713 -0.062597834  0.528552618  0.138405961 
##      stateOK      stateOR      statePA      stateRI      stateSC      stateSD 
## -0.628378814 -0.016273650  0.217890702  0.314222041 -0.432795309  0.126385522 
##      stateTN      stateTX      stateUT      stateVA      stateVT      stateWA 
## -0.206029866 -0.038943198  0.243990717 -0.045923802  0.200296849  0.441406524 
##      stateWI      stateWV      stateWY 
##  0.183033773  0.047312733 -0.004301847

adding the fixed effect to that gives

with(rout, alpha + b)
##      stateAK      stateAL      stateAR      stateAZ      stateCA      stateCO 
##  0.093608709 -0.402443537 -0.620780140 -0.292739979  0.451019387 -0.151499978 
##      stateCT      stateDC      stateDE      stateFL      stateGA      stateHI 
##  0.136935462  0.309854501  0.156737293  0.242314548 -0.133890088  0.344573813 
##      stateIA      stateID      stateIL      stateIN      stateKS      stateKY 
## -0.196493499 -0.448177464  0.117779665 -0.049305369 -0.121867827 -0.293411483 
##      stateLA      stateMA      stateMD      stateME      stateMI      stateMN 
## -0.282543326 -0.186595779  0.581872735  0.420228255  0.167272483  0.010776311 
##      stateMO      stateMS      stateMT      stateNC      stateND      stateNE 
##  0.155280779  0.107119157 -0.040508817 -0.440295842 -0.043281630  0.464705377 
##      stateNH      stateNJ      stateNM      stateNV      stateNY      stateOH 
## -0.263498449  0.129118097  0.073491485 -0.032246063  0.558904390  0.168757733 
##      stateOK      stateOR      statePA      stateRI      stateSC      stateSD 
## -0.598027042  0.014078122  0.248242474  0.344573813 -0.402443537  0.156737293 
##      stateTN      stateTX      stateUT      stateVA      stateVT      stateWA 
## -0.175678095 -0.008591426  0.274342489 -0.015572031  0.230648621  0.471758296 
##      stateWI      stateWV      stateWY 
##  0.213385545  0.077664505  0.026049925

and then mapping to the probability scale gives

e <- with(rout, alpha + b) |> invlogit() |> print()
##   stateAK   stateAL   stateAR   stateAZ   stateCA   stateCO   stateCT   stateDC 
## 0.5233851 0.4007254 0.3496040 0.4273332 0.6108816 0.4621973 0.5341805 0.5768497 
##   stateDE   stateFL   stateGA   stateHI   stateIA   stateID   stateIL   stateIN 
## 0.5391043 0.5602840 0.4665774 0.5853011 0.4510341 0.3897942 0.5294109 0.4876762 
##   stateKS   stateKY   stateLA   stateMA   stateMD   stateME   stateMI   stateMN 
## 0.4695707 0.4271689 0.4298304 0.4534859 0.6414982 0.6035379 0.5417209 0.5026941 
##   stateMO   stateMS   stateMT   stateNC   stateND   stateNE   stateNH   stateNJ 
## 0.5387424 0.5267542 0.4898742 0.3916705 0.4891813 0.6141298 0.4345039 0.5322348 
##   stateNM   stateNV   stateNY   stateOH   stateOK   stateOR   statePA   stateRI 
## 0.5183646 0.4919392 0.6361990 0.5420896 0.3547952 0.5035195 0.5617439 0.5853011 
##   stateSC   stateSD   stateTN   stateTX   stateUT   stateVA   stateVT   stateWA 
## 0.4007254 0.5391043 0.4561931 0.4978522 0.5681587 0.4961071 0.5574079 0.6157998 
##   stateWI   stateWV   stateWY 
## 0.5531449 0.5194064 0.5065121

And we can get standard errors

vout <- vcov(rout, re.too = TRUE, standard.deviation = FALSE)

Make a function to post-process these estimates.

foo.factory <- function(v) {
    is.alpha <- attr(v, "is.alpha")
    is.bee <- attr(v, "is.b")
    is.nu <- attr(v, "is.nu")
    function(theta) {
        stopifnot(is.numeric(theta))
        stopifnot(is.finite(theta))
        stopifnot(length(theta) == length(is.alpha))
        alpha <- theta[is.alpha]
        bee <- theta[is.bee]
        invlogit(alpha + bee)
    }
}
foo <- foo.factory(vout)

Try it.

alphabeenu <- with(rout, c(alpha, b, nu))
all.equal(e, foo(alphabeenu))
## [1] TRUE

6.6.4 Standard Errors via the Delta Method

The delta method is easily applied in this problem using R function jacobian in CRAN package numDeriv to do the calculus.

jack <- jacobian(foo, alphabeenu)
vcov.e <- jack %*% vout %*% t(jack)

Now assemble the results.

data.frame(Estimate = e, `Std. Error` = sqrt(diag(vcov.e))) |> round(3)
##         Estimate Std..Error
## stateAK    0.523      0.017
## stateAL    0.401      0.023
## stateAR    0.350      0.040
## stateAZ    0.427      0.016
## stateCA    0.611      0.005
## stateCO    0.462      0.011
## stateCT    0.534      0.011
## stateDC    0.577      0.030
## stateDE    0.539      0.019
## stateFL    0.560      0.005
## stateGA    0.467      0.008
## stateHI    0.585      0.029
## stateIA    0.451      0.016
## stateID    0.390      0.038
## stateIL    0.529      0.005
## stateIN    0.488      0.008
## stateKS    0.470      0.015
## stateKY    0.427      0.019
## stateLA    0.430      0.017
## stateMA    0.453      0.011
## stateMD    0.641      0.023
## stateME    0.604      0.031
## stateMI    0.542      0.006
## stateMN    0.503      0.007
## stateMO    0.539      0.008
## stateMS    0.527      0.012
## stateMT    0.490      0.017
## stateNC    0.392      0.014
## stateND    0.489      0.018
## stateNE    0.614      0.032
## stateNH    0.435      0.026
## stateNJ    0.532      0.007
## stateNM    0.518      0.013
## stateNV    0.492      0.013
## stateNY    0.636      0.010
## stateOH    0.542      0.005
## stateOK    0.355      0.035
## stateOR    0.504      0.009
## statePA    0.562      0.006
## stateRI    0.585      0.029
## stateSC    0.401      0.023
## stateSD    0.539      0.019
## stateTN    0.456      0.011
## stateTX    0.498      0.003
## stateUT    0.568      0.020
## stateVA    0.496      0.006
## stateVT    0.557      0.024
## stateWA    0.616      0.017
## stateWI    0.553      0.010
## stateWV    0.519      0.014
## stateWY    0.507      0.017

For more about applying the delta method, with more examples, see the vignette about the delta method in CRAN package aster.

7 Example: Crossed Random Effects

7.1 Data

As an example with crossed random effects we look at the salamander data taken from the authoritative book on generalized linear models McCullagh and Nelder (1983) (and ultimately coming from a biology paper cited therein) and put in R package glmm

data(salamander)
class(salamander)
## [1] "data.frame"
sapply(salamander, class)
##      Mate     Cross    Female      Male 
## "numeric"  "factor"  "factor"  "factor"
unique(salamander$Mate)
## [1] 1 0
unique(salamander$Cross)
## [1] R/R R/W W/R W/W
## Levels: R/R R/W W/R W/W

These data are about a salamander mating experiment. The response variable Mate is Bernoulli (zero-or-one-valued). It is whether two salamanders placed together by the experimenters mated. The salamanders came from two locations called “Rough Butt” and “White Side” (names of locations, not descriptions of salamanders). The Cross variable says which was mated with which, female first, that is, type "R/W" indicates Rough Butt female with White Side male. The variables Female and Male indicate the individual salamanders in the experiment. Each salamander occurs in more than one line of the data (was involved in more than one mating trial).

The model we fit has Cross as fixed effects and Female and Male as crossed random effects.

7.2 Glmer

lout <- glmer(Mate ~ 0 + Cross + (1 | Female) + (1 | Male),
    data = salamander, family = binomial)
summary(lout)
## Generalized linear mixed model fit by maximum likelihood (Laplace
##   Approximation) [glmerMod]
##  Family: binomial  ( logit )
## Formula: Mate ~ 0 + Cross + (1 | Female) + (1 | Male)
##    Data: salamander
## 
##       AIC       BIC    logLik -2*log(L)  df.resid 
##     430.6     453.9    -209.3     418.6       354 
## 
## Scaled residuals: 
##     Min      1Q  Median      3Q     Max 
## -2.0508 -0.6156  0.2714  0.5973  2.5506 
## 
## Random effects:
##  Groups Name        Variance Std.Dev.
##  Female (Intercept) 1.174    1.084   
##  Male   (Intercept) 1.041    1.020   
## Number of obs: 360, groups:  Female, 60; Male, 60
## 
## Fixed effects:
##          Estimate Std. Error z value Pr(>|z|)    
## CrossR/R   1.0082     0.3937   2.561   0.0105 *  
## CrossR/W   0.3062     0.3747   0.817   0.4138    
## CrossW/R  -1.8959     0.4460  -4.251 2.13e-05 ***
## CrossW/W   0.9904     0.3912   2.532   0.0113 *  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Correlation of Fixed Effects:
##          CrsR/R CrsR/W CrsW/R
## CrossR/W  0.280              
## CrossW/R  0.112 -0.019       
## CrossW/W  0.042  0.249  0.145

7.3 Glmm

time <- system.time(
gout <- glmm(Mate ~ 0 + Cross, list(~ 0 + Female, ~ 0 + Male),
    data = salamander, varcomps.names = c("Female", "Male"),
    family = binomial.glmm, m = 1e6,
    cluster = makePSOCKcluster(detectCores()))
)
time
##     user   system  elapsed 
##   38.352   12.339 1665.858
summary(gout)
## 
## Call:
## glmm(fixed = Mate ~ 0 + Cross, random = list(~0 + Female, ~0 + 
##     Male), varcomps.names = c("Female", "Male"), data = salamander, 
##     family.glmm = binomial.glmm, m = 1e+06, cluster = makePSOCKcluster(detectCores()))
## 
## 
## Link is: "logit (log odds)"
## 
## Fixed Effects:
##          Estimate Std. Error z value Pr(>|z|)    
## CrossR/R     1.03       0.42   2.435   0.0149 *  
## CrossR/W     0.33       0.40   0.836   0.4030    
## CrossW/R    -1.91       0.45  -4.274 1.92e-05 ***
## CrossW/W     1.02       0.44   2.308   0.0210 *  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## 
## Variance Components for Random Effects (P-values are one-tailed):
##        Estimate Std. Error z value Pr(>|z|)/2   
## Female     1.40       0.59   2.371    0.00886 **
## Male       1.20       0.49   2.445    0.00724 **
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

So this took 27 minutes and 45.9 seconds of clock time on my computer.

7.4 Reaster

dat <- transform(salamander, root = 1, varb = "only",
    id = 1:nrow(salamander)) |> transform(varb = as.factor(varb))
head(dat)
##   Mate Cross Female Male root varb id
## 1    1   R/R     10   10    1 only  1
## 2    1   R/R     11   14    1 only  2
## 3    1   R/R     12   11    1 only  3
## 4    1   R/R     13   13    1 only  4
## 5    1   R/R     14   12    1 only  5
## 6    1   R/W     15   28    1 only  6
rout <- reaster(fixed = Mate ~ 0 + Cross,
    random = list(Female = ~ 0 + Female, Male = ~ 0 + Male),
    pred = 0, fam = 1, varb, id, root, data = dat)
summary(rout, standard.deviation = FALSE)
## 
## Call:
## reaster.formula(fixed = Mate ~ 0 + Cross, random = list(Female = ~0 + 
##     Female, Male = ~0 + Male), pred = 0, fam = 1, varvar = varb, 
##     idvar = id, root = root, data = dat)
## 
## 
## Fixed Effects:
##          Estimate Std. Error z value Pr(>|z|)    
## CrossR/R   0.7782     0.3144   2.476   0.0133 *  
## CrossR/W   0.2448     0.3033   0.807   0.4195    
## CrossW/R  -1.4822     0.3494  -4.242 2.22e-05 ***
## CrossW/W   0.7690     0.3135   2.453   0.0142 *  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Variance Components (P-values are one-tailed):
##        Estimate Std. Error z value Pr(>|z|)/2  
## Female   0.6544     0.3072   2.131     0.0166 *
## Male     0.5764     0.2874   2.005     0.0225 *
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Bibliography

Booth, J. G. and Hobert, J. P. (1999) Maximizing generalized linear mixed model likelihoods with an automated Monte Carlo EM algorithm. Journal of the Royal Statistical Society, Series B, 61, 265–285. DOI: 10.1111/1467-9868.00176.
Breslow, N. E. and Clayton, D. G. (1993) Approximate inference in generalized linear mixed models. Journal of the American Statistical Association, 88, 9–25. DOI: 10.1080/01621459.1993.10594284.
Geyer, C. J. (1994) On the convergence of Monte Carlo maximum likelihood calculations. Journal of the Royal Statistical Society, Series B, 61, 261–274. DOI: 10.1111/j.2517-6161.1994.tb01976.x.
Geyer, C. J. (2013) Asymptotics of maximum likelihood without the LLN or CLT or sample size going to infinity. In Advances in Modern Statistical Theory and Applications: A Festschrift in Honor of Morris l. Eaton (eds G. L. Jones and X. Shen), pp. 1–24. Hayward, CA: Institute of Mathematical Statistics. DOI: 10.1214/12-IMSCOLL1001.
Geyer, C. J., Ridley, C. E., Latta, R. G., et al. (2013) Local adaptation and genetic effects on fitness: Calculations for exponential family models with random effects. Annals of Applied Statistics, 7, 1778–1795. DOI: 10.1214/13-AOAS653.
Knudson, C., Benson, S., Geyer, C., et al. (2021) Likelihood-based inference for generalized linear mixed models: Inference with the r package ‘glmm‘. Stat, 10, e339. DOI: 10.1002/sta4.339.
McCullagh, P. and Nelder, J. A. (1983) Generalized Linear Models. second. London: Chapman & Hall/CRC.
Oehlert, G. W. (2010) A First Course in Design and Analysis of Experiments. Available at: https://hdl.handle.net/11299/168002.
Stiratelli, R., Laird, N. and Ware, J. H. (1984) Random-effects models for serial observations with binary response. Biometrics, 40, 961–971. DOI: 10.2307/2531147.
Sung, Y. J. and Geyer, C. J. (2007) Monte Carlo likelihood inference for missing data models. Annals of Statistics, 35, 990–1011. DOI: 10.1214/009053606000001389.
Thompson, E. A. and Guo, S. W. (1991) Evaluation of likelihood ratios for complex genetic models. Mathematical Medicine and Biology: A Journal of the IMA, 8, 149–169. DOI: 10.1093/imammb/8.3.149.