Transcriptome
Count normalisation: CPM, TPM, FPKM
Turn a raw RNA-seq count matrix into CPM, TPM or FPKM, with library size and detected gene counts for every sample.
The first column is the gene id and the rest are per-sample counts. A column named length is used for TPM and FPKM. Tabs, commas and semicolons all work as separators.
Library statistics
Normalised matrix
The point most often missed: TPM cannot be computed for a single gene, because the denominator is the summed rate of every gene in that sample. That is why this tool takes the whole table rather than one row. TPM and FPKM differ only in the order of the two normalisation steps — TPM divides by length first and by the total second, FPKM the other way round — which is why TPM columns sum to exactly one million and FPKM columns do not. Neither replaces the between-sample normalisation DESeq2 performs for differential expression.
Formula
TPM = (count ÷ length) ÷ Σ(count ÷ length) × 10⁶
- CPM
- count divided by library size times a million — length is ignored
- FPKM
- divided by library size first, then by length
- TPM
- divided by length first, then by the summed rates — each column sums to exactly a million
Worked example
Why TPM cannot be computed for one gene alone
- g1: length 1000, count 10
- g2: length 2000, count 30
- g3: length 500, count 60
- Rate per gene: count divided by length in kilobases. That is 10, 15 and 120.
- Sum of rates: 145. This number depends on every gene in the sample.
- TPM of each gene: its own rate over 145, times a million.
Answer g1 is 68,966 — a number that could not be reached without g2 and g3
Common mistakes
- Normalising a matrix that was already normalised. If most values are not whole numbers you have probably pasted TPM or FPKM instead of raw counts; the tool warns when it sees this.
- Using CPM to compare two genes with each other. CPM ignores length, so a longer gene collects more reads by construction; use TPM for within-sample comparisons.
- Comparing FPKM across samples. Because FPKM columns do not sum to a fixed total, direct comparison between samples is misleading. TPM does not have that flaw.
- Feeding these values into a differential expression tool. DESeq2 and edgeR want raw counts and perform their own between-sample normalisation.
Frequently asked
TPM or FPKM?
TPM. They differ only in the order of the two normalisation steps, but because every TPM column sums to a million, each gene\u2019s share stays comparable across samples. FPKM has no such guarantee.
Where do I get gene lengths?
From the same annotation used for counting. featureCounts writes a Length column in its output. For more accuracy, the effective length reported by Salmon or RSEM is preferable.
What library size should I aim for?
It depends on the question, but the spread between samples matters more than the absolute figure. If one sample totals a fraction of the others, examine it before analysis.