Answer

Fixed vs random effects in mixed models: what is the difference?

Inspired by a question on Cross Validated ·

multilevel modelsregression

The short answer

A fixed effect is a quantity you care about in itself and estimate directly, such as the difference between two treatments. A random effect treats the groups in your data (schools, patients, sites) as a sample from a larger population of groups: instead of a separate free parameter per group, the model estimates how much groups vary. That lets you generalize beyond the groups you observed, gives honest standard errors for clustered data, and pulls noisy group estimates toward the overall mean.

The core idea

Picture a study of test scores for students in 12 schools, with some students taught by a new method. A mixed model has two kinds of terms.

The label depends on the question, not on the variable. The same school factor could be fixed in a study comparing three specific named schools and random in a study that samples schools to learn about schools in general.

When to treat a grouping factor as random

Treat the factor as fixed when its levels are the whole point (treatment arms, the two sexes, three named regions), when there are very few levels (as a rough rule, fewer than about five makes the between-group variance hard to estimate), or when you worry that the group effects are correlated with your predictors.

See it in R and Python

The simulation creates 12 schools with 6 students each, where schools truly differ with an SD of 4 points and students within a school with an SD of 8. It fits a fixed-effects model (a separate mean for each school) and a random-intercept model using the nlme package, which ships with R. The Python tab reproduces the random-intercept fit with NumPy: for a balanced design like this one, the REML estimates equal the classic ANOVA variance-component formulas.

R

library(nlme)   # ships with R
set.seed(4700)
J <- 12; n <- 6                         # 12 schools, 6 students each
school <- factor(rep(1:J, each = n))
u <- rnorm(J, 0, 4)                     # true school effects (SD 4)
y <- 50 + u[school] + rnorm(J * n, 0, 8)  # student scores (residual SD 8)

# Fixed effects: one separate mean per school (no pooling)
fe <- lm(y ~ 0 + school)
fe_means <- coef(fe)

# Random effects: schools drawn from a population of schools (REML)
re <- lme(y ~ 1, random = ~ 1 | school)
vc <- as.numeric(VarCorr(re)[, "StdDev"])   # school SD, residual SD
round(vc, 2)
round(summary(re)$tTable[, 1:2], 2)         # overall mean and its SE

# Intraclass correlation: share of variance between schools
icc <- vc[1]^2 / (vc[1]^2 + vc[2]^2)
round(icc, 2)

# Ignoring the clustering understates the SE of the overall mean
round(summary(lm(y ~ 1))$coefficients[, 1:2], 2)

# Shrinkage: random-effect school estimates are pulled toward the overall mean
re_means <- coef(re)[, 1]
lambda <- vc[1]^2 / (vc[1]^2 + vc[2]^2 / n)
round(lambda, 2)
round(c(sd_fixed = sd(fe_means), sd_random = sd(re_means)), 2)
round(rbind(fixed = fe_means, random = re_means)[, 1:4], 1)

Python

import numpy as np

rng = np.random.default_rng(4700)
J, n = 12, 6                                  # 12 schools, 6 students each
school = np.repeat(np.arange(J), n)
u = rng.normal(0, 4, J)                       # true school effects (SD 4)
y = 50 + u[school] + rng.normal(0, 8, J * n)  # student scores (residual SD 8)

# Fixed effects: one separate mean per school (no pooling)
fe_means = np.array([y[school == j].mean() for j in range(J)])
grand = y.mean()

# Random intercept model; for a balanced design REML equals the ANOVA
# estimates below (as long as the between-school variance is positive)
msw = sum(((y[school == j] - fe_means[j]) ** 2).sum() for j in range(J)) / (J * (n - 1))
msb = n * ((fe_means - grand) ** 2).sum() / (J - 1)
tau2, sigma2 = (msb - msw) / n, msw
print("school SD, residual SD:", np.round(np.sqrt([tau2, sigma2]), 2))
print("overall mean, SE:", round(grand, 2), round(np.sqrt(msb / (J * n)), 2))

# Intraclass correlation: share of variance between schools
print("ICC:", round(tau2 / (tau2 + sigma2), 2))

# Ignoring the clustering understates the SE of the overall mean
print("naive SE:", round(y.std(ddof=1) / np.sqrt(J * n), 2))

# Shrinkage: random-effect school estimates are pulled toward the overall mean
lam = tau2 / (tau2 + sigma2 / n)
re_means = grand + lam * (fe_means - grand)
print("lambda:", round(lam, 2))
print("SD fixed, SD random:", round(fe_means.std(ddof=1), 2), round(re_means.std(ddof=1), 2))
print(np.round(np.vstack([fe_means, re_means])[:, :4], 1))
R output from one seeded run (same numbers on a second run):
[1] 3.76 9.00
    Value Std.Error 
    50.83      1.52 
[1] 0.15
  Estimate Std. Error 
     50.83       1.14 
[1] 0.51
 sd_fixed sd_random 
     5.26      2.69 
       school1 school2 school3 school4
fixed     49.5    55.4    47.6    46.7
random    50.2    53.2    49.2    48.7

The figures below come from one seeded run of the R code. Python uses a different random number generator, so its figures differ slightly, but the pattern is the same.

Common confusions

How to report a mixed-effects model in APA style (7th edition)

Describe the structure in the method section (what is nested in what, which effects are random, the estimation method and the software), then give the fixed effects with their standard errors and the random-effect variances or SDs. Using the example above:

"Scores were analyzed with a random-intercept model for students (N = 72) nested in 12 schools, estimated by REML with the nlme package in R. The estimated overall mean was 50.83 (SE = 1.52). The between-school SD was 3.76 and the residual SD was 9.00, giving an intraclass correlation of .15."

With predictors in the model, add a table with b, SE, the 95% CI, the test statistic and p for each fixed effect, and list the random-effect variances below it, along with the number of groups and observations.

Related tools and guides

More answered questions

Working with your own data?

General answers only go so far. Send us your situation and we'll reply by email within two business days.

Ask your question

Written by AskStats with AI assistance. This is general information, not advice for your specific data or study. When the results matter, check your approach with a qualified statistician.