# How to report a mixed model: what to write in the Methods and Results, with a template

> Report a mixed model's formula, random effects, estimation method, degrees-of-freedom method and software; then the fixed effect with its 95% CI, the random-effect SDs and the numbers at each level. Python and R code.

Canonical: https://www.licklider.ai/guides/how-to-report-a-mixed-model/
Section: Guides › Writing and reporting
Author: Licklider · Published 2026-11-11 · Last reviewed 2026-11-11 (UTC)

> **Quick answer.** A reader should be able to refit your model from the Methods. State the **model** (outcome, fixed effects, random effects, for example `y ~ group + (1 | mouse)`), the **estimation method** (REML), how **p-values and degrees of freedom** were obtained (Satterthwaite or Kenward–Roger; lme4 gives none for linear mixed models), the **software and versions**, and how many units there were at each level (cells, and mice per group). This page covers linear mixed models for continuous outcomes; for counts or yes/no outcomes (`glmer`), report the same items, but such models are fitted by maximum likelihood (not REML) and lme4 reports Wald z p-values, which are unreliable with few animals. The template is under "Report it" below. In the Results, give the **fixed effect with its 95% CI** and test, the **random-effect standard deviations** (or variances), and say whether the fit was singular. The template below fills in these items for a typical cells-within-mice study.

**Terms used below.** *Mixed model*: a regression with fixed effects (the comparisons you want) and random effects (grouping such as mouse or litter). *Fixed effect*: an effect estimated for its own sake, such as drug versus vehicle. *Random effect*: a term letting each unit (here each mouse) have its own baseline, with a standard deviation estimated across units. *Random intercept*: a random effect for each unit's baseline, written `(1 | mouse)`. *REML*: restricted maximum likelihood, the usual way to estimate a mixed model's variances. *Degrees of freedom (df)*: here, an approximation that reflects how many units inform a test; Satterthwaite and Kenward–Roger are two methods. *Wald test*: a test using the estimate divided by its standard error; statsmodels compares it with a normal distribution (no small-sample df), while lmerTest compares it with a t distribution with Satterthwaite or Kenward–Roger df. *ICC*: the share of variation lying between units (mice) rather than within them. *Marginal and conditional R²*: the variance explained by the fixed effects alone, and by fixed and random effects together. *Singular fit*: a fit in which a random-effect variance is estimated as zero or a correlation as ±1. *95% confidence interval (CI)*: the range of effects compatible with the data. *SE*: standard error. *Random slope*: a random effect letting each unit have its own response to a predictor (for example its own time trend). *Crossed random effects*: two grouping factors that are not nested, such as mouse and scoring session. *Balanced design*: the same number of measurements in every unit and group. *Covariate*: an extra predictor, such as cell size. *Convergence warning*: a message that the fitting algorithm may not have reached the best estimates. *Type I and Type II errors*: false positives and missed real effects. *Profile interval*: a confidence interval from the likelihood, lme4's default for `confint()`. *Covariance structure*: the assumed pattern of correlation between repeated measurements. *Optimiser*: the algorithm that searches for the best estimates. *ddf*: the denominator degrees-of-freedom method used for tests.

## What to report

| Item | Example | Why |
| --- | --- | --- |
| Model formula | `y ~ group + (1 \| mouse)` in lme4 | Readers can refit it; shows what is fixed and what is random |
| Units at each level | 160 cells from 16 mice (8 mice per group) | The mice, not the cells, carry the group comparison |
| Estimation | REML | Affects the variance estimates |
| Tests and df | Satterthwaite (lmerTest's default) or Kenward–Roger, chosen in advance | lme4 prints no p-values for linear mixed models; methods differ with few units |
| Software | R 4.3.3, lme4 1.1-35.1, lmerTest 3.1-3 (pbkrtest 0.5.2 for Kenward–Roger); or Python 3.13, statsmodels 0.15.0 | Defaults change between versions |
| Fixed effect | Difference with 95% CI (state the method, for example Wald t with Satterthwaite df), t(df), p | The answer to the question |
| Random effects | SD (or variance) of each random effect and of the residual | Shows how much variation lies between animals |
| Fit problems | Singular fit, convergence warnings, and what was done | Simplified models must be disclosed |
| Optional | ICC; marginal and conditional R² | Summaries readers sometimes ask for |

Meteyard and Davies recommend that the final model be "reported in a table that includes all parameter estimates for fixed effects (coefficients, standard errors and/or confidence intervals, associated test statistics and p-values if used), random effects (standard deviation and/or variance for each random effect …)" ([Meteyard & Davies 2020](https://doi.org/10.1016/j.jml.2020.104092)). On p-values, Bates and colleagues note of lme4's output: "Note that there are no p values" ([Bates et al. 2015](https://doi.org/10.18637/jss.v067.i01)); lmerTest adds Satterthwaite's approximation and, through pbkrtest, Kenward–Roger ([Kuznetsova et al. 2017](https://doi.org/10.18637/jss.v082.i13)). Luke's simulations found Type I error rates "closest to .05 when models are fitted using REML and p-values are derived using the Kenward-Roger or Satterthwaite approximations" ([Luke 2017](https://doi.org/10.3758/s13428-016-0809-y)). The marginal and conditional R² follow [Nakagawa & Schielzeth 2013](https://doi.org/10.1111/j.2041-210x.2012.00261.x).

## Worked example: 10 cells from each of 16 mice

Constructed data: a measurement in 10 cells from each of 8 vehicle and 8 drug-treated mice. By construction the drug adds 2.0 units, mice differ with SD 1.5 and cells with SD 3.0. The random seed was the first one tried and was not chosen for its result. Stored code and data: [cells.csv](/guides/how-to-report-a-mixed-model/cells.csv), [make_data.py](/guides/how-to-report-a-mixed-model/make_data.py), [analysis.R](/guides/how-to-report-a-mixed-model/analysis.R) with [its output](/guides/how-to-report-a-mixed-model/analysis_R_output.txt), and [analysis.py](/guides/how-to-report-a-mixed-model/analysis.py) with [its output](/guides/how-to-report-a-mixed-model/analysis_py_output.txt).

| Quantity | lme4 + lmerTest (R) | statsmodels (Python) |
| --- | --- | --- |
| Drug − vehicle | 1.482 (SE 0.762) | 1.482 (SE 0.762) |
| Test | **Report this:** Satterthwaite t(14.0) = 1.95, **p = 0.072**; Kenward–Roger gives the same t(14.0) here | Wald z = 1.95, p = 0.052 (too optimistic with 16 mice) |
| 95% CI | **Report this:** −0.151 to 3.116 (Wald t with 14 Satterthwaite df) | −0.011 to 2.975 (normal approximation, Wald z; R prints the same interval from `confint(method = "Wald")`) |
| Between-mouse SD; residual SD | 1.259; 2.712 | 1.259; 2.712 |
| ICC | 0.177 | 0.177 |
| Marginal / conditional R² | 0.058 / 0.225 | 0.058 / 0.225 |
| Singular fit | No | — |

The two programs agree on the estimates but not on the test: statsmodels' Wald test ignores that only 16 mice inform the comparison, so its p-value and interval are too optimistic with so few units; the Satterthwaite result (t(14) = 1.95, p = 0.072) matches a Student's (equal-variance) t-test on the 16 mouse means exactly (difference 1.482, t(14) = 1.95, p = 0.072, printed by analysis.R and analysis.py), as expected for this balanced design. Report the small-sample version. With one random intercept and a balanced design, the mixed model and the mouse-means t-test answer the same question ([nested data](/guides/nested-data-mixed-model/)); the mixed model earns its place with unbalanced data, covariates at the cell level, or crossed random effects.

```r
library(lmerTest)                                    # lme4 plus Satterthwaite or Kenward–Roger tests
d <- read.csv("cells.csv")    # one row per cell: group, mouse, cell, y (rename to yours; "groupdrug" below follows the level names)
d$group <- factor(d$group, levels = c("vehicle", "drug"))
fit <- lmer(y ~ group + (1 | mouse), data = d, REML = TRUE)
isSingular(fit)                                      # report if TRUE, and what you did about it
summary(fit, ddf = "Satterthwaite")$coefficients     # estimate, SE, df, t, p
summary(fit, ddf = "Kenward-Roger")$coefficients     # if Kenward-Roger was chosen in advance (needs pbkrtest)
VarCorr(fit)                                         # random-effect SD and residual SD
co <- summary(fit)$coefficients["groupdrug", ]
co["Estimate"] + c(-1, 1) * qt(0.975, co["df"]) * co["Std. Error"]   # 95% CI with Satterthwaite df (confint() defaults to profile)
vc <- as.data.frame(VarCorr(fit)); vc$vcov[1] / sum(vc$vcov)          # ICC
plot(fitted(fit), resid(fit)); ranef(fit)                            # residual check; each mouse's estimated effect
```

```python
# Same estimates in Python; statsmodels reports Wald z-tests without small-sample df (see the table above)
import pandas as pd
import statsmodels.formula.api as smf

d = pd.read_csv("cells.csv"); d["drug"] = (d.group == "drug").astype(int)   # one row per cell
fit = smf.mixedlm("y ~ drug", d, groups=d["mouse"]).fit(reml=True)
print(fit.summary())                                 # fixed effects, group (mouse) variance, residual scale
# With few animals, report a t-test on animal means instead of the Wald z-test:
from scipy import stats
m = d.groupby(["mouse", "drug"]).y.mean().reset_index()
print(stats.ttest_ind(m.y[m.drug == 1], m.y[m.drug == 0]))   # t(14) = 1.95, p = 0.072
```

## Before you write it up

1. **Choose the random effects from the design**, before looking at results: a random intercept for each animal (or litter, cage) whose cells you measured. For repeated time points, a random intercept assumes all pairs of time points are equally correlated; consider a random slope or a covariance structure ([repeated measures](/guides/repeated-measures-anova-vs-mixed-model/)). Barr and colleagues argue for "the maximal random effects structure justified by the design" ([Barr et al. 2013](https://doi.org/10.1016/j.jml.2012.11.001)); Matuschek and colleagues show that this protection "implies a significant increase in Type II error rate" when the data cannot support it ([Matuschek et al. 2017](https://doi.org/10.1016/j.jml.2017.01.001)). State the structure and, in advance, the rule you will follow if it does not fit (for example: drop the random slope, then the correlation).
2. **If the fit is singular**, a situation lme4's documentation describes as "estimated variance-covariance matrices with less than full rank" ([lme4 `isSingular` documentation](https://www.rdocumentation.org/packages/lme4/versions/1.1-35.5/topics/isSingular); the analysis used lme4 1.1-35.1), simplify the random effects by the rule set in advance (for example drop a random slope), refit, and report both the warning and the change. In a random-intercept-only model such as the template's, there is nothing left to drop: a between-mouse variance estimated as zero is, with few mice, an estimation limit rather than proof that mice do not differ; report the mouse-means comparison as well and say so ([nested-data guide](/guides/nested-data-mixed-model/)). For a convergence warning, centre and scale predictors, try another optimiser (for example `lmer(..., control = lmerControl(optimizer = "bobyqa"))`) or more iterations, and report what you did.
3. **Count units at every level** and report them; the number of animals matters most for the group comparison.
4. **Use small-sample tests** (Satterthwaite, lmerTest's default, or Kenward–Roger in R; choose before analysis). In Python, with fewer than about 50 animals (and always with three or fewer per group, as our [nested-data guide](/guides/nested-data-mixed-model/) explains), compare groups on animal means instead, as in the Python block above.
5. **Check residuals and random effects** for skew or outliers (plots of residuals against fitted values, and of each mouse's estimated effect).

## Check what an AI assistant ran

1. **The assistant reported a mixed model without its formula.** Ask for the exact model call.
2. **The assistant gave p-values from lme4** without saying how they were computed. Ask whether lmerTest (Satterthwaite or Kenward–Roger) was used.
3. **The assistant reported statsmodels' z-test p-values** for a study with few animals. Ask for small-sample df, or a comparison of animal means.
4. **The assistant left out the random-effect SDs** or ignored a singular-fit warning. Ask for them, and for what was done about the warning.

## Report it

Methods:

> The outcome was analysed with a linear mixed model with group as a fixed effect and a random intercept for each mouse (`y ~ group + (1 | mouse)`), fitted by REML in R [4.3.3] with lme4 [1.1-35.1]; the test for the group effect used Satterthwaite's degrees of freedom (lmerTest [3.1-3]). The analysis included [160] cells from [16] mice ([8] mice per group). [If the fit was singular: the random effects were simplified to [ ] by a rule set in advance.]

Results:

> The estimated difference (drug − vehicle) was [1.48] units (95% CI [−0.15] to [3.12], Wald t with Satterthwaite df; t([14.0]) = [1.95], p = [0.072]), so the data are compatible with no difference and with an increase of about [3] units. The between-mouse standard deviation was [1.26] and the residual (between-cell) standard deviation [2.71] (ICC [0.18]). The fit was not singular, and there were no convergence warnings. [If the effect is not significant: "The difference was [x] (95% CI [ ] to [ ]; p = [ ]); the data are compatible with no effect and with an effect of [upper limit]."]

If you compared animal means instead (for example in Python):

> Cell values were averaged within each mouse, and the [16] mouse means were compared with Student's t-test (Python [3.13], SciPy [1.18.1]): difference [1.48] units (95% CI [−0.15] to [3.12]; t([14]) = [1.95], p = [0.072]).

Replace the bracketed values with your own, and keep only the bracketed clause that applies.

## References

- Meteyard L, Davies RAI (2020). Best practice guidance for linear mixed-effects models in psychological science. *Journal of Memory and Language* 112:104092. [doi:10.1016/j.jml.2020.104092](https://doi.org/10.1016/j.jml.2020.104092)
- Bates D, Mächler M, Bolker B, Walker S (2015). Fitting linear mixed-effects models using lme4. *Journal of Statistical Software* 67(1):1–48. [doi:10.18637/jss.v067.i01](https://doi.org/10.18637/jss.v067.i01)
- Kuznetsova A, Brockhoff PB, Christensen RHB (2017). lmerTest package: tests in linear mixed effects models. *Journal of Statistical Software* 82(13):1–26. [doi:10.18637/jss.v082.i13](https://doi.org/10.18637/jss.v082.i13)
- Luke SG (2017). Evaluating significance in linear mixed-effects models in R. *Behavior Research Methods* 49:1494–1502. [doi:10.3758/s13428-016-0809-y](https://doi.org/10.3758/s13428-016-0809-y)
- Nakagawa S, Schielzeth H (2013). A general and simple method for obtaining R² from generalized linear mixed-effects models. *Methods in Ecology and Evolution* 4:133–142. [doi:10.1111/j.2041-210x.2012.00261.x](https://doi.org/10.1111/j.2041-210x.2012.00261.x)
- Barr DJ, Levy R, Scheepers C, Tily HJ (2013). Random effects structure for confirmatory hypothesis testing: keep it maximal. *Journal of Memory and Language* 68:255–278. [doi:10.1016/j.jml.2012.11.001](https://doi.org/10.1016/j.jml.2012.11.001)
- Matuschek H, Kliegl R, Vasishth S, Baayen H, Bates D (2017). Balancing Type I error and power in linear mixed models. *Journal of Memory and Language* 94:305–315. [doi:10.1016/j.jml.2017.01.001](https://doi.org/10.1016/j.jml.2017.01.001)

## Related

- [Nested data: means or mixed model](https://www.licklider.ai/guides/nested-data-mixed-model/)
- [Repeated measures ANOVA vs mixed model](https://www.licklider.ai/guides/repeated-measures-anova-vs-mixed-model/)
- [How to write the statistical methods section](https://www.licklider.ai/guides/how-to-write-statistical-methods-section/)
- [How to report ANOVA results](https://www.licklider.ai/guides/how-to-report-anova-results/)

## How this page was made

- Written and published by Licklider. Recommendations cite peer-reviewed methods papers and software documentation listed under References; cited passages were checked against the source text.
- The worked example uses constructed data. Its numbers were produced by stored code (R 4.3.3 with lme4 1.1-35.1, lmerTest 3.1-3 and pbkrtest 0.5.2; Python 3.13 with statsmodels 0.15.0); the two give the same estimates, and their p-values differ by method, as explained on the page.
- Separate review passes checked the statistics, the citations and readability before publication.
