library(tidyverse)LMM
Fixed vs Random Effects: Five Definitions
(1) Fixed effects are constant across individuals, and random effects vary. For example, in a growth study, a model with random intercepts \(a_i\) and fixed slope \(b\) corresponds to parallel lines for different individuals \(i\), or the model \(y_{it} = a_i + b t\). Kreft and De Leeuw (1998) thus distinguish between fixed and random coefficients.
(2) Effects are fixed if they are interesting in themselves or random if there is interest in the underlying population. Searle, Casella, and McCulloch (1992, Section 1.4) explore this distinction in depth.
(3) “When a sample exhausts the population, the corresponding variable is fixed; when the sample is a small (i.e., negligible) part of the population the corresponding variable is random.” (Green and Tukey, 1960)
(4) “If an effect is assumed to be a realized value of a random variable, it is called a random effect.” (LaMotte, 1983)
(5) Fixed effects are estimated using least squares (or, more generally, maximum likelihood) and random effects are estimated with shrinkage (“linear unbiased prediction” in the terminology of Robinson, 1991). This definition is standard in the multilevel modeling literature (see, for example, Snijders and Bosker, 1999, Section 4.2) and in econometrics.
The definitions are all different!
Example
df <- data.frame(
person = c("Person 1", "Person 2", "Person 3", "Person 4"),
diet = c("A", "A", "B", "B"),
`0` = c(102L, 96L, 83L, 79L),
`1` = c(97L, 93L, 79L, 77L),
`2` = c(95L, 87L, 78L, 75L),
`3` = c(93L, 85L, 74L, 72L)
)
df <- df |>
pivot_longer(3:6, names_to = "measure", values_to = "weight") |>
mutate(
measure = as.numeric(gsub("X", "", measure)),
person = factor(person),
diet = factor(diet)
)
df# A tibble: 16 × 4
person diet measure weight
<fct> <fct> <dbl> <int>
1 Person 1 A 0 102
2 Person 1 A 1 97
3 Person 1 A 2 95
4 Person 1 A 3 93
5 Person 2 A 0 96
6 Person 2 A 1 93
7 Person 2 A 2 87
8 Person 2 A 3 85
9 Person 3 B 0 83
10 Person 3 B 1 79
11 Person 3 B 2 78
12 Person 3 B 3 74
13 Person 4 B 0 79
14 Person 4 B 1 77
15 Person 4 B 2 75
16 Person 4 B 3 72
# install.packages("remotes")
# remotes::install_github("MatthewBJane/ThemePark")
library(ThemePark)df |>
ggplot(aes(x = measure, y = weight, colour = diet)) +
geom_point(size = 3) + theme_starwars()
ex_lm <- lm(weight ~ measure, data = df)
anova(ex_lm)Analysis of Variance Table
Response: weight
Df Sum Sq Mean Sq F value Pr(>F)
measure 1 177.01 177.013 2.0888 0.1704
Residuals 14 1186.43 84.745
library(lme4)
ex_mix <- lmer(weight ~ measure + (1 | person), data = df)
anova(ex_mix)Analysis of Variance Table
npar Sum Sq Mean Sq F value
measure 1 177.01 177.01 136.76
Using nlme
ex_nlme <- nlme::lme(
fixed = weight ~ measure,
random = ~1 | person,
data = df
)
anova(ex_nlme) numDF denDF F-value p-value
(Intercept) 1 11 298.0365 <.0001
measure 1 11 136.7612 <.0001
Using glmmTMB
ex_glmmtmb <- glmmTMB::glmmTMB(
formula = weight ~ measure + (1 | person),
dispformula = ~1,
REML = TRUE,
data = df
)
summary(ex_glmmtmb) Family: gaussian ( identity )
Formula: weight ~ measure + (1 | person)
Data: df
AIC BIC logLik -2*log(L) df.resid
74.2 77.3 -33.1 66.2 12
Random effects:
Conditional model:
Groups Name Variance Std.Dev.
person (Intercept) 97.359 9.867
Residual 1.294 1.138
Number of obs: 16, groups: person, 4
Dispersion estimate for gaussian family (sigma^2): 1.29
Conditional model:
Estimate Std. Error z value Pr(>|z|)
(Intercept) 89.7750 4.9564 18.11 <2e-16 ***
measure -2.9750 0.2544 -11.69 <2e-16 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Using sommer
ex_sommer <- sommer::mmer(
fixed = weight ~ measure,
random = ~person,
rcov = ~units,
data = df,
verbose = FALSE
)
summary(ex_sommer)$groups
weight
person 4
$varcomp
VarComp VarCompSE Zratio Constraint
person.weight-weight 97.34996 79.686001 1.221670 Positive
units.weight-weight 1.29435 0.552034 2.344692 Positive
$betas
Trait Effect Estimate Std.Error t.value
1 weight (Intercept) 89.775 4.9562084 18.11365
2 weight measure -2.975 0.2543963 -11.69435
$method
[1] "NR"
$logo
logLik AIC BIC Method Converge
Value 14.19706 -24.39413 -22.84895 NR TRUE
attr(,"class")
[1] "summary.mmer" "list"
Using ASReml-R
ex_asreml <- asreml::asreml(
fixed = weight ~ measure,
random = ~person,
residual = ~units,
data = df
)Online License checked out Fri Mar 13 10:32:35 2026
ASReml Version 4.2 13/03/2026 10:32:35
LogLik Sigma2 DF wall
1 -39.14458 60.82245 14 10:32:35 ( 1 restrained)
2 -30.52196 12.44806 14 10:32:35
3 -21.63403 2.117789 14 10:32:35
4 -20.47415 1.511946 14 10:32:35
5 -20.27159 1.343988 14 10:32:35
6 -20.25529 1.299438 14 10:32:35
7 -20.25509 1.294390 14 10:32:35
asreml::wald(ex_asreml)[0;34mWald tests for fixed effects.[0m
[0;34mResponse: weight[0m
[0;34mTerms added sequentially; adjusted for those above.[0m
Df Sum of Sq Wald statistic Pr(Chisq)
(Intercept) 1 385.85 298.10 < 2.2e-16 ***
measure 1 177.01 136.75 < 2.2e-16 ***
residual (MS) 1.29
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
summary(ex_asreml)$varcomp component std.error z.ratio bound %ch
person 97.36409 79.7330951 1.221125 P 0
units!R 1.29439 0.5519449 2.345143 P 0
Homework
Blocks as fixed vs random:
- https://newprairiepress.org/cgi/viewcontent.cgi?referer=&httpsredir=1&article=1474&context=agstatconference
- https://vsni.co.uk/the-great-debate-fixed-vs-random-blocks-in-experimental-design/
To reproduce:
Additional Resources
Ph.D. Andrew Gelman, Professor, Department of Statistics. Columbia University
Why I don’t use the term “fixed and random effects” link
Why I don’t use the terms “fixed” and “random” (again) link