# Litter effects in rodent studies: pups within litters, litter as the unit and litter size

> When dams receive the treatment, analyse litters, not pups: litter means or a mixed model with planned covariates (litter size only if treatment cannot change it). In simulation, pups as n gave 44% false positives. Python and R code.

Canonical: https://www.licklider.ai/guides/litter-effects/
Section: Guides › Design, replicates and sample size
Author: Licklider · Published 2026-11-12 · Last reviewed 2026-11-12 (UTC)

> **Quick answer.** When a treatment is given to pregnant or nursing dams (diet, drug, stress, infection), the **litter** is the experimental unit and the pups are subsamples, so n is the number of litters. Average the pups of each litter and compare litter means (a Welch t-test for two groups), or fit a mixed model of every pup with litter as a random effect. Decide in advance whether sex and litter size go in the model; if the treatment itself may change litter size, report the result without that adjustment as well. In a simulation of 6 vs 6 dams with 4 to 10 pups each and no real effect, a t-test with pups as n gave false positives in 43.7% of studies; litter means gave 4.2%. Adjusting for litter size raised power, and testing only one pup per litter lowered it.

**Terms used below.** *Dam*: the mother. *Litter*: the pups born to one dam at one time. *Experimental unit*: the thing randomised to a group, here the dam with her litter. *Subsample*: a measurement that repeats the same unit, such as another pup from the same litter. *Litter mean*: the average of the pups in one litter. *Mixed model*: a regression with a *random effect* (an adjustment for each litter), so pups of one litter are not treated as independent. *Intraclass correlation (ICC)*: the share of variation that lies between litters (below, after allowing for sex and litter size); the higher it is, the more pups as n overstates the evidence. *Covariate* (or *fixed effect*): a measured variable added to the model, such as sex or litter size. *Block*: a group of units within which treatments are compared; a litter is a block only when its pups receive different treatments. *Satterthwaite degrees of freedom*: a small-sample correction for the mixed model's test. *Welch t-test*: a two-group t-test that does not assume equal spread. *95% confidence interval (CI)*: the range of values compatible with the data. *Power*: the chance of detecting an effect that is really there. *False positive*: a "significant" result when there is no real effect.

## Which analysis for your question

| Question | Analysis | Report |
| --- | --- | --- |
| Does a treatment given to dams change an outcome in their pups? | Litter means, Welch t-test across litters; litter size as a covariate if planned and the treatment cannot change it; with 3 or fewer litters per group, show every litter mean and plan more litters | Difference with 95% CI, n litters (pups) |
| Pups of both sexes, where the sexes may differ | Mixed model with litter as a random effect and sex as a covariate; separate tests in each sex are not a test of a sex difference | Difference with 95% CI, by sex if they differ ([sex as a variable](/guides/sex-as-a-biological-variable-analysis/)) |
| Uneven numbers of pups per litter | Litter means are still valid; or a mixed model with litter as a random effect and Satterthwaite degrees of freedom (unstable with 3 or fewer litters per group) | Difference with 95% CI |
| Only one pup per litter is tested (for example a behaviour test) | Pups as n is then the same as litters as n; choose the pup by a rule set in advance | Difference with 95% CI |
| Treatment given to pups individually within litters (each litter split between groups) | Paired or mixed analysis with litter as a block; pups are the units | Difference with 95% CI |
| Binary outcome per pup (survival, malformation) | Affected and total pups per litter, a quasi-binomial or logistic mixed model with litter, or litter proportions with litters as n ([comparing percentages](/guides/comparing-percentages-between-groups/)) | Odds ratio or difference in proportion with 95% CI |
| Three or more treatments given to dams | Litter means in a [Welch ANOVA](/guides/welch-anova/), or a mixed model | Differences with adjusted CIs |

Lazic and Essioux explain that when dams are treated, "the experimental unit ... is the pregnant dam and not the individual offspring", and that "the offspring are considered subsamples". They describe Holson and Pearce's finding that with three treated and three control litters and two offspring each, "the false positive rate (Type I error) is 20% rather than the assumed 5%", rising to 80% with 12 offspring per litter, and list three valid designs: "using only one animal per litter (randomly selected)", averaging animals within each litter, or a mixed-effects model that "avoids artificially inflating the sample size" ([Lazic and Essioux 2013](https://doi.org/10.1186/1471-2202-14-37)). The ARRIVE 2.0 guidelines ask authors to report "the experimental unit (e.g., a single animal, litter, or cage of animals)", and note that it may be the litter, as in "a treatment administered to a dam and investigated in her pups" ([Percie du Sert et al. 2020](https://doi.org/10.1371/journal.pbio.3000411)).

## Worked example: a prenatal treatment with no real effect

Constructed data: **6 control and 6 treated dams**, each with a litter of 4 to 10 pups, every pup weighed at weaning (75 pups). Pup weight varies between litters (standard deviation 0.8 g) and between pups of a litter (0.6 g); pups in larger litters are lighter (0.25 g per extra pup) and males are 0.4 g heavier. By design, **the treatment does not change pup weight**. The data's random seed was the first one tried and was not chosen for its result. Stored code and data: [pups.csv](/guides/litter-effects/pups.csv), [model.py](/guides/litter-effects/model.py), [make_data.py](/guides/litter-effects/make_data.py), [analysis.py](/guides/litter-effects/analysis.py), [analysis.R](/guides/litter-effects/analysis.R) and [the analysis output](/guides/litter-effects/analysis_output.txt); analysis.py and analysis.R print the same output.

Litter size was drawn independently of treatment, so the adjustment in C is allowed; in this draw the treated litters were larger by chance (mean 6.7 pups against 5.8) and their litter means were lower (9.85 g against 10.66 g).

| Analysis of constructed data with no real effect, treated − control | Result |
| --- | --- |
| A. (Not valid: pups share litters) Pups as n (40 vs 35), Welch t-test | difference −0.76 g, p = 0.00025 (invalid) |
| B. Litters as n (6 vs 6), Welch t-test on litter means | difference −0.82 g (95% CI −1.62 to −0.02), p = 0.047 |
| **C. Litters as n, litter means adjusted for litter size** | **difference −0.76 g (95% CI −1.60 to 0.08), p = 0.071** |
| D. Mixed model of all pups, litter random effect, sex and litter size ([mixed_model.R](/guides/litter-effects/mixed_model.R), [output](/guides/litter-effects/mixed_model_output.txt); R only) | difference −0.79 g (95% CI −1.64 to 0.06), p = 0.065 |

Pups as n reported overwhelming evidence (p = 0.00025) for an effect that does not exist. The litter-level analyses put the same difference near the 0.05 threshold with wide intervals. The litter means (B) fell below it: in the simulation below, this test gave false positives in 4.2% of studies, so a valid test is expected to do this about once in 20 studies. The treated litters also happened to be larger here, and the analysis that adjusted for litter size (C) did not. C is in bold because it is the analysis planned for this design, not because of its p-value. In the mixed model of these constructed data, 43% of the variation left after sex and litter size lay between litters. Across 5,000 simulated studies per row ([simulation.py](/guides/litter-effects/simulation.py), [the simulation output](/guides/litter-effects/simulation_output.txt)):

| Scenario (the mixed model, D, was not simulated) | A. Pups as n (invalid) | B. Litter means | C. Litter means adjusted for litter size | E. One pup per litter |
| --- | --- | --- | --- | --- |
| No effect, 6 vs 6 dams (false positives) | **43.7%** | 4.2% | 4.7% | 4.4% |
| Treated pups 1 g lighter, 6 vs 6 dams (power; inflated for A) | 82.0% | 35.3% | 42.8% | 26.9% |
| No effect, 12 vs 12 dams (false positives) | **40.5%** | 4.3% | 4.4% | 4.3% |
| Treated pups 1 g lighter, 12 vs 12 dams (power; inflated for A) | 94.6% | 67.1% | **78.1%** | 52.5% |

These percentages describe this simulated design (4 to 10 pups per litter, the variation in model.py), not every developmental study. Treating pups as independent found a "difference" in more than 4 in 10 studies with no effect, and more dams did not fix it, because the error comes from counting pups as units. The litter-level analyses kept false positives near 5%. Adjusting for litter size removed variation that has nothing to do with the treatment and raised power; testing one pup per litter threw information away. The 1 g effect was chosen after a first run with 0.5 g (power 12.5% and 22.7% for litter means), so that the differences between analyses are visible; the mixed model was not simulated.

If the treatment itself changes litter size, adjusting for litter size removes part of the treatment's effect; report litter size per group and the result with and without the adjustment.

The code expects one row per pup with columns `treatment` (labels exactly `control` and `treated`), `litter` (an ID per litter), `litter_size` (the same definition for every litter, for example pups at weaning), `pup`, `sex` (exactly `male` or `female`) and `weight_g`. The Python block runs B, and the R block runs B and C; analysis.py runs A, B and C, and mixed_model.R the mixed model. Rename your columns and labels to match, save the table as pups.csv (or change the file name in the code), and run the code in that folder (`python analysis.py` or `Rscript analysis.R`). Python needs NumPy, pandas and SciPy 1.11 or later (`pip install numpy pandas scipy`); the R code uses base R; the optional mixed model needs lme4 and lmerTest (`install.packages("lmerTest")`).

```python
import pandas as pd
from scipy import stats

d = pd.read_csv("pups.csv")
m = d.groupby(["treatment", "litter"]).agg(weight_g=("weight_g", "mean"), litter_size=("litter_size", "first")).reset_index()
tr, co = m.weight_g[m.treatment == "treated"], m.weight_g[m.treatment == "control"]       # one mean per litter
t = stats.ttest_ind(tr, co, equal_var=False); ci = t.confidence_interval()
print(f"difference {tr.mean() - co.mean():.2f} g (95% CI {ci.low:.2f} to {ci.high:.2f}), p = {t.pvalue:.2g}")
# difference -0.82 g (95% CI -1.62 to -0.02), p = 0.047
```

```r
d <- read.csv("pups.csv")
m <- aggregate(cbind(weight_g, litter_size) ~ treatment + litter, data = d, FUN = mean)   # one row per litter
t.test(m$weight_g[m$treatment == "treated"], m$weight_g[m$treatment == "control"])   # Welch: treated - control -0.82 g, 95% CI -1.62 to -0.02, p = 0.047
fit <- lm(weight_g ~ treatment + litter_size, data = m); summary(fit); confint(fit)   # adjusted: -0.76 g, 95% CI -1.60 to 0.08, p = 0.071
```

## Before you analyse

1. **Randomise dams, not pups**, to the treatment, and plan the number of litters; extra pups from the same litter add little.
2. **Record the litter, the dam, litter size at birth and at weaning, and sex** for every pup; decide in advance whether litters are culled to a standard size.
3. **Set the pup-selection rule in advance** when only some pups are tested (for example one pup per litter chosen at random, or one of each sex analysed with sex in a mixed model, because two pups from one litter are not independent).
4. **Measure blind to treatment** where possible, and house litters from both groups together in time and place.
5. **Check whether the treatment changed litter size or pup survival**, because both change pup weight and many other outcomes.

## Check what an AI assistant ran

1. **The assistant ran a t-test or ANOVA on all pups.** Ask for one value per litter, or a mixed model with litter.
2. **The assistant reported the number of pups as n.** Ask for the number of litters per group.
3. **The assistant ignored litter size or sex.** Ask whether they affect the outcome and whether they were in the model.
4. **The assistant selected pups after seeing their values.** Ask for the selection rule.

## Report it

> Dams were randomised to [control] or [treatment] ([6] per group). Pups were weighed at [postnatal day 21] ([75] pups). Because the treatment was given to dams, the litter was the experimental unit: pup weights were averaged per litter and groups were compared with a linear model of litter means with litter size as a covariate (R [4.3.3]); a mixed model of all pups with litter as a random effect and sex as a covariate gave [a similar estimate].

> In the constructed example, which has no effect built in, pup weight did not clearly differ between groups (treated − control [−0.76] g, 95% CI [−1.60] to [0.08]; p = [0.071]; n = [6] litters per group, [75] pups).

Replace the bracketed values with your own.

## References

- Lazic SE, Essioux L (2013). Improving basic and translational science by accounting for litter-to-litter variation in animal models. *BMC Neuroscience* 14:37. [doi:10.1186/1471-2202-14-37](https://doi.org/10.1186/1471-2202-14-37)
- Percie du Sert N, Ahluwalia A, Alam S, et al. (2020). Reporting animal research: Explanation and elaboration for the ARRIVE guidelines 2.0. *PLoS Biology* 18:e3000411. [doi:10.1371/journal.pbio.3000411](https://doi.org/10.1371/journal.pbio.3000411)

## Related

- [What counts as n](https://www.licklider.ai/guides/what-counts-as-n/)
- [Nested data: means or mixed model](https://www.licklider.ai/guides/nested-data-mixed-model/)
- [Sex as a biological variable](https://www.licklider.ai/guides/sex-as-a-biological-variable-analysis/)
- [How to report a mixed model](https://www.licklider.ai/guides/how-to-report-a-mixed-model/)

## How this page was made

- Written and published by Licklider. Recommendations cite peer-reviewed methods papers and reporting guidelines listed under References; cited passages were checked against the source text.
- The worked example uses constructed data. Its numbers were produced by stored code (Python 3.13 with SciPy 1.18.1; R 4.3.3, base R), and the two languages print identical output; the optional mixed model uses R with lme4 1.1-35.1 and lmerTest 3.1-3; the simulation was run in Python.
- Separate review passes checked the statistics, the citations and readability before publication.
