Chatomics Field GuideWhat They Don't Teach You

Glossary · Statistics, Artifacts and Pitfalls

Effect size

Log2 fold change tells you how big the difference is; the p-value only tells you how surprised to be that it's not zero, and mixing the two up is how real biology gets buried under statistical noise.

By Ming "Tommy" Tang, Director of Bioinformatics in Big Pharma · Reviewed September 2026 · 2 min read

Also: Cohen's d, magnitude

Definition

Effect size is the magnitude of a difference between two conditions, measured independently of sample size and independently of how confident you are that the difference is real. In RNA-seq differential expression, the standard effect size is log2 fold change (log2FC): the log2 ratio of normalized expression between two groups. Cohen's d is the general-statistics analogue, computed as the difference between two group means divided by the pooled standard deviation. A p-value tells you how surprised to be under the null hypothesis; effect size tells you how large the difference actually is, and the two are mathematically independent of each other.

You meet effect size the moment a differential expression run comes back with 4,000 "significant" genes and no way to prioritize them. DESeq2 or edgeR hands you a p-value and adjusted p-value for every gene, but those numbers only tell you how unlikely the observed difference is under the null. They say nothing about whether the difference is worth a follow-up experiment.

Effect size is the other half of the table: log2 fold change (log2FC) in RNA-seq, or Cohen's d in general statistics, and it measures magnitude independent of sample size. Once you have thousands of cells or dozens of replicates, p-values collapse toward zero for even trivial differences, so effect size becomes the number that actually does the work of separating biology from statistical power.

Why it matters

Get this wrong and you either bury real biology under a p-value filter or chase noise that happens to be statistically significant. In highly powered experiments, especially single-cell RNA-seq with thousands of cells, p-values become artificially tiny for trivial differences, sometimes reaching 1e-20 for changes nobody would call biologically interesting. Filtering only on adjusted p-value in that setting can hand you thousands of "significant" genes with no way to prioritize which ones matter.

The reverse failure is just as costly: X-chromosome inactivation escape and beta-thalassemia both show that a 50% expression change (log2FC ≈ 0.58) can drive a full disease phenotype. A rigid log2FC = 1 cutoff, applied without thinking about the gene's biology, would filter both of those real effects out of your candidate list before you ever look at them.

Where people get it wrong

The mistake is treating log2FC = 1 as a universal law instead of a convenience, and separately, confusing linear fold change with log2 fold change when reading a table (a 2-fold change is log2FC = 1, not FC = 1, and people misread these interchangeably). A second, quieter version of the same mistake is filtering only on adjusted p-value with no effect-size floor at all: with enough samples, that approach returns thousands of genes moving by a few percent, all "significant" and mostly useless for prioritization. The fix isn't a better default number, it's picking the threshold from what you know about the gene, pathway, and experimental system, the same way chapter 11 argues you should treat p = 0.05 as convention rather than a natural law.

A concrete example

A typical failure mode: filtering DESeq2 output on adjusted p-value alone returns genes moving by 5-10%, which is statistical noise dressed up as a hit list. Adding an effect-size floor on top of the significance filter is the standard fix, and edgeR's glmTreat() goes further by testing directly against a fold-change boundary instead of testing against zero and filtering afterward.

r
res <- results(dds, contrast = c("condition", "treated", "control"))

# post-hoc filter: statistically significant AND biologically meaningful
sig <- subset(res, padj < 0.05 & abs(log2FoldChange) >= 1)

# better for modest, biologically relevant effects: test against
# a fold-change threshold directly instead of testing against zero
library(edgeR)
tr <- glmTreat(fit, coef = 2, lfc = log2(1.5))
topTags(tr)

Related terms

Questions people ask

What is effect size vs p-value?

P-value answers "how likely is this difference to be pure chance under the null hypothesis?" Effect size answers "how big is the difference?" A gene can have a tiny p-value (1e-20) with a trivial log2FC of 0.1, or a marginal p-value (0.06) with a log2FC of 3. They measure different things and neither substitutes for the other.

What log2FC cutoff should I use for differential expression?

log2FC = 1 (2-fold change) is the most common default, but it's a convenience, not a law. Disease studies sometimes work at log2FC >= 0.58 (1.5-fold) because master regulators moving 50% can flip a phenotype; drug studies with strong perturbations sometimes require log2FC >= 2. Set the cutoff from the biology of the system, not from habit.

How do I calculate effect size in RNA-seq?

Most tools give it to you directly: DESeq2's results() and edgeR's topTags() both report log2FoldChange per gene, already computed from normalized counts. If you need a threshold test rather than a post-hoc filter, edgeR's glmTreat() tests directly against a specified log2FC boundary instead of testing against zero.

Is a 50% change (log2FC ≈ 0.58) biologically meaningful?

It can be. X-chromosome inactivation escape genes and the beta-thalassemia HBB locus both show that a 50% shift in expression is enough to drive a disease phenotype. A fixed log2FC = 1 cutoff would filter both of those out, which is exactly why the threshold has to come from what you know about the gene and pathway, not a default.

Why do p-values get so small in single-cell RNA-seq?

Large cell numbers give enormous statistical power, so even a trivial expression difference produces a vanishingly small p-value. This gets worse when you cluster cells and then test for markers between those same clusters, a form of double dipping that inflates significance further. Effect size, not p-value, is what should drive gene ranking in that setting.

Related pages

Related reading on the blog

Sources

  1. Feasibility of sample size calculation for RNA-seq studies — Fold change thresholds (FC >= 1.5, 2.0, 2.5) and their effect on power/sample size calculations
  2. glmTreat: Test for Differential Expression Relative to a Threshold — edgeR's threshold test against a specified log2FC boundary, with recommended lfc values
  3. limma_confects: Confident log2 fold changes based on a limma fit object — Ranking genes by confident effect size bounds under FDR control instead of p-value cutoffs alone