Nested measurements · Choose a method

Dendritic spine density statistics: spines per 10 µm, segments within neurons within animals, and count models

Compare spine density per animal: total spines ÷ total dendrite length for each animal's neurons, animals as n. In a simulation with no real effect, segments as n gave 26% false positives. Python and R code.

By Licklider · Published · Last reviewed · How this page was made · Markdown

On this page
  1. Which analysis for your question
  2. Worked example: a knockout with no real effect
  3. Before you analyse
  4. Check what an AI assistant ran
  5. Report it
  6. References

Quick answer. Spines are counted on dendritic segments of neurons from each animal, so segments and neurons are subsamples of the animal (the unit that received the genotype or treatment). For each animal, divide the total spines by the total dendrite length measured (spines per 10 µm), and compare animals with a Welch t-test (a Welch ANOVA for three or more groups). A Poisson model that treats every segment as independent is the worst choice; a count mixed model with animal and neuron random effects respects the nesting. With few animals, that mixed model’s p-values are too small. In a simulation of 6 vs 6 mice with 6 neurons each, 2 segments per neuron and no real difference, segments as n gave false positives in 25.8% of studies, neurons as n 18.3%, the all-segments Poisson model 46.2%, and mice as n 4.4%. In the same simulation, spreading the same 36 neurons per group over 12 mice × 3 neurons instead of 6 × 6 raised the chance of detecting a 20% drop from 61.0% to 83.0%.

Terms used below. Dendritic spine: a small protrusion on a dendrite that carries most excitatory synapses. Segment: a stretch of dendrite (here 10–30 µm of a secondary branch, one that branches off a primary dendrite leaving the cell body) on which spines are counted. Spine density: spines per unit length, here per 10 µm. Experimental unit: the thing randomised to a group, here the mouse. Poisson model: a regression for counts that assumes their variance equals their mean; an offset of log(length) turns counts into rates per µm. Rate ratio: knockout density ÷ wild-type density from a count model. Negative-binomial model: a count model that allows more scatter than Poisson. Mixed model: a regression with random effects (an adjustment for each animal and each neuron), so segments are not treated as independent. Wald test: the test mixed-model software uses for p-values by default. Welch ANOVA: one-way ANOVA for three or more groups without assuming equal spread. 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 genotype or treatment change spine density? Total spines ÷ total length per animal (spines per 10 µm), Welch t-test across animals Difference with 95% CI, n animals (neurons, segments, µm)
Uneven numbers of neurons or segments per animal Total spines ÷ total length per animal still gives one density per animal. Alternative: Poisson or negative-binomial mixed model with log(length) offset and random effects for animal and neuron; with few animals the mixed model’s Wald p-values are too small (here p = 0.037 with no real effect). Report it beside the animal-level result Difference or rate ratio with 95% CI
Spine types (thin, stubby, mushroom) Density of each type per animal, analysed the same way, with a Holm correction across all types tested (which correction) Differences per type
Proximal vs distal or apical vs basal Density per animal for each compartment; paired t-test on each animal’s difference between compartments, or a mixed model with animal as a random effect Differences with 95% CI
Three or more groups Animal densities in a Welch ANOVA, then comparisons chosen before seeing the data Differences with adjusted CIs

Benavides-Piccione and colleagues determined spine density “by counting the number of spines per 10 µm of dendritic length”, and “the analysis of all spine variables was performed under blinded conditions” (Benavides-Piccione et al. 2025). Wilson and colleagues note that “an additional neuron from the same animal does not provide the same amount of additional information as another neuron from a different animal” (Wilson et al. 2017), and Lazic describes pseudoreplication as observations that “are not statistically independent, but treated as if they are”, using synapse counts on many cells per rat as an example (Lazic 2010).

Worked example: a knockout with no real effect

Constructed data: spines counted on 2 secondary dendritic segments (10–30 µm) of 6 neurons in each of 6 wild-type and 6 knockout mice (144 segments, 3,453 spines). Density is about 12 spines per 10 µm and varies between mice (standard deviation 0.12 on the log scale), between neurons of a mouse (0.15) and between segments (0.10); each count scatters around its segment’s density. By design, the knockout does not change spine density. The data’s random seed was the first one tried and was not chosen for its result. Stored code and data: spines.csv, model.py, make_data.py, analysis.py, analysis.R and the analysis output; analysis.py and analysis.R print the same output.

Knockout mice ranged from 11.2 to 15.9 spines per 10 µm (1,864 spines on 1,370 µm) and wild-type mice from 9.2 to 14.5 (1,589 spines on 1,397 µm). By chance the knockout mice in this draw had a higher spine density.

Analysis of constructed data with no real effect, knockout vs wild-type Result
A. (Not valid: segments share neurons and mice) Segments as n (72 vs 72), Welch t-test ratio 1.22, p = 0.00027
B. (Not valid: neurons share mice) Neurons as n (36 vs 36), Welch t-test ratio 1.21, p = 0.0033
C. Mice as n (6 vs 6), spines per 10 µm, Welch t-test difference 2.32 (95% CI −0.31 to 4.94), p = 0.078
D. (Not valid: mice ignored) Poisson model of all segments as independent counts, log(length) offset rate ratio 1.20, p = 1.5 × 10⁻⁷
E. (Nesting respected, but Wald p too small with 6 mice per group) Poisson mixed model with mouse, neuron and segment random effects (mixed_model.R, output; R only) rate ratio 1.21 (95% CI 1.01 to 1.44), p = 0.037

Four of the five analyses reached p < 0.05 on data with no real effect: the three invalid analyses (A, B and D), and the mixed model, which respects the nesting but whose Wald test was too confident with 6 mice per group. Only the analysis with mice as n did not. Its p = 0.078 is not evidence of no effect either: in the simulation below, this design detected a real 20% drop in only 61.0% of studies, and the confidence interval shows what the data allow. Across 5,000 simulated studies of this design (simulation.py, the simulation output):

Scenario A. Segments as n (invalid) B. Neurons as n (invalid) C. Mice as n D. Poisson, all segments (invalid)
No effect, 6 mice × 6 neurons (false positives) 25.8% 18.3% 4.4% 46.2%
20% fewer spines, 6 mice × 6 neurons (power) 90.7% 87.3% 61.0% 95.7%
No effect, 12 mice × 3 neurons (false positives) 17.2% 10.4% 4.5% 36.6%
20% fewer spines, 12 mice × 3 neurons (power) 95.1% 91.7% 83.0% 98.0%

These percentages describe this simulated design (2 segments per neuron, the variation between mice, neurons and segments set in model.py), not every spine study. The all-segments Poisson model was the most wrong, because it treats every spine count as independent and assumes no variation between neurons or mice. Mice as n kept false positives near 5%; for the same 36 neurons (72 segments) per genotype, spreading them over 12 mice instead of 6 raised power from 61.0% to 83.0%. The mixed model (E) was not included in the simulation; report the animal-level analysis (C) as the result and the mixed model, if you fit it, as a secondary analysis.

The code expects one row per segment with columns genotype (labels exactly wild-type and knockout), mouse (unique across genotypes), neuron (numbered within each mouse or across the experiment; either works), segment, length_um and spines. If you only have a mean density per neuron, go back to the spine count and length of each segment or neuron: averaging neuron densities weights a short dendrite as much as a long one. Check that every row has a length above 0 and a spine count. Rename your columns and labels to match, save the table as spines.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 (install.packages("lme4")).

import numpy as np, pandas as pd
from scipy import stats

d = pd.read_csv("spines.csv")
m = d.groupby(["genotype", "mouse"])[["spines", "length_um"]].sum()       # totals per mouse
m["per10"] = 10 * m.spines / m.length_um                                  # spines per 10 um
k, w = m.loc["knockout", "per10"], m.loc["wild-type", "per10"]
t = stats.ttest_ind(k, w, equal_var=False); ci = t.confidence_interval()
print(f"difference {k.mean() - w.mean():.2f} per 10 um (95% CI {ci.low:.2f} to {ci.high:.2f}), p = {t.pvalue:.2g}")
# difference 2.32 per 10 um (95% CI -0.31 to 4.94), p = 0.078
d <- read.csv("spines.csv")
m <- aggregate(cbind(spines, length_um) ~ genotype + mouse, data = d, FUN = sum)   # totals per mouse
m$per10 <- 10 * m$spines / m$length_um                                           # spines per 10 um
t.test(per10 ~ genotype, data = m)       # Welch; knockout - wild-type 2.32, 95% CI -0.31 to 4.94, p = 0.078

Before you analyse

  1. Define the segments before imaging: branch order (for example secondary dendrites), distance from the soma, length range and number per neuron, the same for every animal.
  2. Choose neurons and segments by a rule set in advance, and count blind to genotype, with images coded by someone else.
  3. Record length with every count and analyse densities (or counts with a length offset), never raw counts.
  4. Plan animals, not just neurons: in our simulation, spreading the same 36 neurons per group over twice the mice raised the power to detect a 20% drop from 61% to 83%.
  5. Use the animal as n; if you fit a mixed model, include animal and neuron random effects and check it against the animal-level result (nested data).
  6. Plot the per-animal densities: with 6 animals per group one animal can drive the result, and a Welch t-test does not fix strong skew (consider a log scale).
  7. Check cages and litters: if treatment was given per cage, or mice in a group share a cage or litter, they are not independent; use the cage or litter as the unit, or model it as a random effect (what counts as n).

Check what an AI assistant ran

  1. The assistant ran a t-test on all segments or neurons. Ask for one density per animal.
  2. The assistant fitted a Poisson regression to all segments. Ask how animals and neurons were handled.
  3. The assistant compared raw spine counts. Ask for densities per length.
  4. The assistant classified spine types and tested each one without saying how many types there were. Ask for a Holm correction across all types tested.

Report it

Spines were counted blind to genotype on [2] secondary dendritic segments ([10–30] µm) of [6] neurons per mouse in [6] wild-type and [6] knockout mice. For each mouse, the total spine count was divided by the total length measured (spines per 10 µm), and genotypes were compared with a Welch t-test (R [4.3.3]).

In the constructed example, which has no effect built in, spine density did not clearly differ between genotypes (knockout − wild-type [2.32] spines per 10 µm, 95% CI [−0.31] to [4.94]; p = [0.078]; n = [6] mice per genotype, [36] neurons and [72] segments per genotype).

Replace the bracketed values with your own.

References

  • Benavides-Piccione R, Fernaud-Espinosa I, Kastanauskaite A, DeFelipe J (2025). Principles for dendritic spine size and density in human and mouse cortical pyramidal neurons. Journal of Comparative Neurology 533:e70060. doi:10.1002/cne.70060
  • Wilson MD, Sethi S, Lein PJ, Keil KP (2017). Valid statistical approaches for analyzing Sholl data: mixed effects versus simple linear models. Journal of Neuroscience Methods 279:33–43. doi:10.1016/j.jneumeth.2017.01.003
  • Lazic SE (2010). The problem of pseudoreplication in neuroscientific studies: is it affecting your analysis? BMC Neuroscience 11:5. doi:10.1186/1471-2202-11-5

How this page was made

  • Written and published by Licklider. Recommendations cite peer-reviewed methods papers 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; the simulation was run in Python.
  • Separate review passes checked the statistics, the citations and readability before publication.