Mixed models for repeated measurements¶
Use a mixed model when observations share a participant, site or other
grouping unit. lmer() fits a continuous Gaussian response with ML or REML.
glmer() fits binomial or Poisson responses with a Laplace approximation.
The snippets below assume a pandas data frame data with score, time,
treatment and participant columns. Set treatment to a categorical column
to make its levels and ordering explicit. For a complete runnable dataset,
see the quickstart and
mixed-model example.
Fit a random intercept or slope¶
from rparity import lmer
model = lmer("score ~ treatment + time + (1 | participant)", data)
print(model.summary())
print(model.fixef())
print(model.VarCorr())
slopes = lmer("score ~ treatment + time + (time | participant)", data)
(1 | participant) allows each participant a different intercept.
(time | participant) adds a participant-specific time slope and estimates
its correlation with the intercept. Use (time || participant) for
independent intercept and slope components. REML is the default; set
reml=False for maximum likelihood.
Predict for existing or new participants¶
conditional = model.predict(data)
population = model.predict(data, re_form="NA")
new_predictions = model.predict(newdata, allow_new_levels=True)
Here newdata is a data frame containing the predictors in the fitted
formula. Default predictions include the fitted random effects for known
participants. re_form="NA" sets those effects to zero. With
allow_new_levels=True, a new participant contributes a zero random effect.
Test effects and compare models¶
from rparity import Anova, anova, emmeans, pairs
print(Anova(model, type=2))
means = emmeans(model, "treatment", lmer_df="satterthwaite")
print(pairs(means, adjust="tukey").summary())
reduced = lmer("score ~ time + (1 | participant)", data)
print(anova(reduced, model))
Anova() tests fixed-effect terms. anova(reduced, model) compares
likelihoods and refits REML fits using ML by default. Use models fitted to
the same observations when comparing their likelihoods. For Type III
main-effect tests involving interactions, fit with contrasts="sum".
Binary and count responses¶
If data instead contains a binary success column or a nonnegative integer
count column, choose the corresponding family:
from rparity import glmer
binary = glmer("success ~ time + (1 | participant)", data,
family="binomial")
counts = glmer("count ~ time + (1 | participant)", data,
family="poisson")
Use glmmTMB() for negative-binomial counts,
zero inflation or modeled dispersion. Supported glmer() links and further
formula examples appear in the lme4 migration guide.
Review singular-fit and convergence warnings before interpreting uncertainty;
see numerical limitations.