RNA-seq Expression Normalization Metrics
RNA-seq expression normalization converts read or fragment counts into values suited to a particular comparison by dividing by gene length or total sample scale. The inputs are gene-level counts and lengths; the output is a floating-point expression vector such as CPM, RPK, RPKM, FPKM, or TPM.
Suppose an aggregation produces the following values.
| gene | raw count | length (kb) |
|---|---|---|
| A | 600 | 2 |
| B | 300 | 1 |
A has twice the count of B, but it is also twice as long. Dividing by length gives an RPK of 300 for both genes. The denominator determines which question a value answers.
Inputs and symbols
Section titled “Inputs and symbols”- : raw read count mapped to gene
- : length of gene , in kb
- : total mapped reads in the sample
In aggregation and normalization code, the structure looks like this.
raw_count = alignments.groupby("gene_id").size()rpk = raw_count / gene_length_kbtpm = rpk / rpk.sum() * 1_000_000Raw count
Section titled “Raw count”Raw count is the integer obtained by counting aligned reads for each gene. It is an observation with no correction for gene length or sequencing depth.
Differential-expression tools such as DESeq2 and edgeR take raw counts because they model count variance and sample scale internally. Do not substitute TPM values.
RPK: divide by length
Section titled “RPK: divide by length”RPK (reads per kilobase) divides count by gene length.
This reduces the tendency of longer genes to produce more fragments. It does not correct total sequencing depth and is mainly used as an intermediate value for TPM.
CPM: divide by total count
Section titled “CPM: divide by total count”CPM (counts per million) divides count by total sample count and multiplies by .
This reduces differences in the total amount read from each sample but does not correct gene length. It can support approximate cross-sample comparison of the same gene, but it is not suitable for direct comparison among genes of different lengths.
RPKM and FPKM: divide by length and total reads
Section titled “RPKM and FPKM: divide by length and total reads”RPKM (reads per kilobase per million) divides count by both gene length and total reads.
FPKM (fragments per kilobase per million) differs by counting two paired-end reads as one fragment. Both length and depth are corrected, but the sum of RPKM or FPKM values can differ among samples.
TPM: divide by the RPK sum
Section titled “TPM: divide by the RPK sum”TPM (transcripts per million) first calculates RPK, divides by the sum of RPK in the sample, and multiplies by .
Because the final denominator is the sample’s own sum, every sample satisfies:
If RPKM values are already available, they can be normalized by their sum to obtain TPM.
TPM is a relative composition within a sample. Even if the absolute number of molecules from one gene stays unchanged, its TPM can decrease when another gene rises sharply. This is the compositional effect.
Comparison by intended use
Section titled “Comparison by intended use”| Metric | Length correction | Sample-scale correction | Main use |
|---|---|---|---|
| raw count | ✗ | ✗ | Input to DESeq2 and edgeR |
| CPM | ✗ | ✓ | Approximate comparison of the same gene across samples |
| RPK | ✓ | ✗ | Intermediate value for TPM |
| RPKM/FPKM | ✓ | ✓ | Older expression-comparison metrics |
| TPM | ✓ | ✓ | Expression visualization and reference matching |
Use the interactive widgets in Turning Raw Counts into Comparable Values to manipulate these calculations. For condition testing with replicate samples, see Testing Differential Expression across Multiple Samples.
Sources
Section titled “Sources”- Wagner et al., Measurement of mRNA abundance using RNA-seq data: RPKM measure is inconsistent among samples, Theory in Biosciences 2012: DOI
- Lior Pachter, Models for transcript quantification from RNA-Seq: arXiv:1104.3889
- Official DESeq2 documentation