The Multiple-Testing Problem

A single p-value of 0.05 is a reasonable bar. Run 20,000 of them at once, one per gene, and that same bar will hand you a thousand "discoveries" that are pure noise. This is the single most important statistical idea in genomics, and the reason DESeq2 output has a "padj" column you should trust instead of the raw p-value. This lesson explains the problem and the two standard fixes, then has you implement one yourself.

🟡 Cross-cutting ⏱️ ~45 min 🌐 Runs in your browser 🧮 Statistics

Before you start

  • You know what a p-value is. If "p-value" feels shaky, do Stats you can't avoid first.
  • No coding required to follow along, but a runnable Python cell lets you implement the correction yourself.
  • Any term new? The Glossary has it.

Learning objectives

By the end of this lesson you will be able to: explain why testing thousands of genes inflates false positives, distinguish controlling the FWER from controlling the FDR, apply Bonferroni and Benjamini-Hochberg corrections, and read a p-value histogram as a diagnostic.

The problem, in one number

Recall what p < 0.05 means: if the null hypothesis is true, you will still get a "significant" result 5% of the time, purely by chance. That is the false-positive rate baked into the threshold. It is acceptable when you run one test. But genomics never runs one test.

A typical RNA-seq experiment tests every gene for differential expression, around 20,000 tests in one analysis. Suppose, in the worst case, that not a single gene truly changed. How many would still cross p < 0.05 by chance alone?

20,000 × 0.05 = 1,000 false positives. A thousand genes flagged "significant" from a dataset with zero real signal.

If you hand in that gene list, almost all of it could be noise, and you would have no way to tell the real hits from the garbage. That is the multiple-testing (or multiple-comparisons) problem. GWAS is even more extreme: millions of variants tested at once.

Two different things you might want to control

The fix depends on what kind of error you are willing to tolerate. There are two formal targets:

TargetWhat it controlsUse when
Family-wise error rate (FWER)The probability of making even one false positive across all testsA single false positive is costly: clinical decisions, confirmatory studies
False discovery rate (FDR)The expected proportion of false positives among the hits you call significantExploratory genomics: you accept some false hits as long as most of your list is real

The distinction matters enormously. Controlling FWER is strict: it tries to avoid any false alarm at all, which makes it conservative and prone to missing real effects. Controlling FDR is more permissive and is the right tradeoff for discovery-stage genomics, where you want a gene list that is "mostly true" and will be validated later anyway.

Decode the jargonFalse discovery rate (FDR)

If your significant list is controlled at 5% FDR, you expect about 5% of the genes on that list to be false positives. It is a property of the whole list, not of any one gene. This is exactly what "we report genes at FDR < 0.05" means in a methods section.

Fix 1: Bonferroni (controls FWER)

The simplest correction. To keep the family-wise error rate at 0.05 across m tests, only call a result significant if its p-value is below 0.05 / m. For 20,000 genes, that threshold becomes 0.05 / 20,000 = 0.0000025. A gene now needs an extraordinarily small p-value to survive.

Bonferroni is correct, simple, and bulletproof, but very conservative: by guarding against even a single false positive, it throws away many genuine effects (false negatives). In GWAS the famous "genome-wide significance" threshold of p < 5×10⁻⁸ is a Bonferroni-style correction reflecting roughly a million independent common variants tested across the genome (it is a fixed community standard, not recalculated per study). For a 20,000-gene RNA-seq study, Bonferroni is usually too strict and you lose real biology.

Fix 2: Benjamini-Hochberg (controls FDR)

This is the genomics workhorse, the method behind the padj (DESeq2) and FDR (edgeR, limma) columns you will actually use. The Benjamini-Hochberg (BH) procedure (1995) controls the false discovery rate instead of the family-wise error rate, so it is far more powerful while still keeping your hit list honest.

The algorithm is surprisingly simple:

  1. Sort all m p-values from smallest to largest. Give each a rank i (1, 2, 3, …).
  2. For each, compute the "BH critical value" (i / m) × Q, where Q is your chosen FDR (say 0.05).
  3. Find the largest rank i where the p-value is still ≤ its critical value.
  4. Call that p-value and everything ranked below it significant.

The "adjusted p-value" (q-value-like number) reported in your results is this procedure expressed per gene, so you can simply filter padj < 0.05 and trust that your list is controlled at 5% FDR.

Decode the jargonAdjusted p-value / q-value

A p-value that has been rescaled to account for all the other tests. The padj column in DESeq2 is BH-adjusted. Storey's q-value is a closely related quantity: the minimum FDR at which a given test would be called significant. In practice you filter on the adjusted p-value, not the raw one.

Implement Benjamini-Hochberg yourself

Below is a small set of 10 p-values. The cell first counts how many pass a naive 0.05 cutoff, then applies BH correction and counts how many survive. Watch how BH is stricter than the raw cutoff but far less brutal than Bonferroni would be. Press Run (first run loads Python in your browser).

Try editing the list: add twenty entries of 0.9 (null genes) and rerun. The naive count barely moves, but it should: those extra tests are exactly the multiple-testing burden that BH and Bonferroni account for and a raw cutoff ignores.

A free diagnostic: the p-value histogram

Before trusting any large set of p-values, plot their histogram. Under the null (nothing real), p-values are uniformly distributed, a flat histogram. Real signal shows up as a spike near zero on top of that flat background. Two warning shapes:

  • A spike near 1, or a hill in the middle: something is wrong with your test or model (often a mis-specified or overly conservative test). FDR correction on these is meaningless.
  • Perfectly flat with no spike at zero: you likely have no real signal, so a long "significant" list after correction should make you suspicious.

This one plot catches more analysis bugs than almost anything else, and you will learn to read it in the next lesson on honest visualization.

⚠️ The cardinal sins of multiple testing

Reporting raw p-values from a genome-wide screen as if they were significant. Running many tests, then correcting only the ones that "looked promising." And the subtlest one: testing many models or subgroups, reporting only the one that worked, and never disclosing how many you tried (this is "p-hacking," and it silently inflates your real false-positive rate far beyond 0.05).

What to actually do

  1. For genome-wide discovery (RNA-seq, methylation, screens): report results at an FDR threshold using Benjamini-Hochberg. Filter on padj / adjusted p-value, never the raw p-value.
  2. When a single false positive is genuinely costly, use Bonferroni or another FWER method and accept the loss of power.
  3. Decide the threshold and the correction method before looking at results, and report how many tests were performed.
  4. Always glance at the p-value histogram first.

Check your understanding

A methods section reads: "We tested 20,000 genes and report 1,200 with raw p < 0.05 as differentially expressed." Even before seeing the data, what is the strongest objection?
Correct. At 20,000 tests, the 0.05 threshold alone yields roughly 1,000 false positives even with no true signal, so a raw-p list of 1,200 is largely uninterpretable. The fix is to control the FDR (Benjamini-Hochberg) and report adjusted p-values.
A clinical lab and an exploratory RNA-seq screen both test thousands of hypotheses. The lab chooses Bonferroni; the screen chooses Benjamini-Hochberg. Why is each choice defensible?
Exactly. Bonferroni controls the family-wise error rate, the chance of any false positive, which suits high-stakes confirmatory settings but is conservative. BH controls the false discovery rate, the expected proportion of false hits, trading a little error tolerance for much more power, which fits exploratory genome-wide discovery.
After differential-expression testing, you plot a histogram of all 20,000 raw p-values and see a roughly flat distribution with a clear spike near 0. What does this most likely indicate?
Right. Under the null, p-values are uniform (flat). Real signal adds an excess of very small p-values, the spike near 0. This flat-plus-spike shape is exactly what you want to see, and it tells you FDR correction will behave sensibly. A spike near 1 or a central hump would instead signal a modeling problem.
In a 20,000-gene RNA-seq study, why is the Bonferroni correction (threshold 0.05 / 20,000) often considered too strict?
Correct. Bonferroni controls the family-wise error rate, the chance of any false positive at all. That makes it bulletproof but conservative, costing power and discarding real biology, which is why FDR methods are usually preferred for genome-wide discovery.
In the Benjamini-Hochberg procedure, after sorting m p-values and assigning each a rank i, which p-values are called significant?
Right. BH finds the largest rank i where p is at or below (i / m) x Q, then declares that gene and all smaller-ranked p-values significant. This controls the false discovery rate while retaining far more power than Bonferroni.

Sources & further reading

  1. Benjamini Y, Hochberg Y. Controlling the False Discovery Rate: A Practical and Powerful Approach to Multiple Testing. J. Royal Statistical Society B, 1995. (The original BH procedure.)
  2. Storey JD, Tibshirani R. Statistical significance for genomewide studies. PNAS, 2003. (q-values.) doi:10.1073/pnas.1530509100
  3. Noble WS. How does multiple testing correction work? Nature Biotechnology, 2009. (A classic plain-English primer.)
  4. Korthauer K, et al. A practical guide to methods controlling false discoveries in computational biology. Genome Biology 20, 118, 2019. (Modern, covariate-aware FDR methods benchmarked across RNA-seq, single-cell, microbiome, ChIP-seq, and GWAS.) doi:10.1186/s13059-019-1716-1
  5. Love MI, Huber W, Anders S. DESeq2. Genome Biology, 2014. (The padj column is BH-adjusted.)

Last reviewed: June 2026.

Next in Track 5

Plots that tell the truth: visualization best practices →