# RNA-seq Expression Normalization Metrics

> Compare raw count, CPM, RPK, RPKM, FPKM, and TPM by their inputs, denominators, formulas, and intended uses.

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

- $c_i$: raw read count mapped to gene $i$
- $\ell_i$: length of gene $i$, in kb
- $N = \sum_j c_j$: total mapped reads in the sample

In aggregation and normalization code, the structure looks like this.

```python
raw_count = alignments.groupby("gene_id").size()
rpk = raw_count / gene_length_kb
tpm = rpk / rpk.sum() * 1_000_000
```

## Raw count

Raw count is the integer $c_i$ 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

**RPK** (reads per kilobase) divides count by gene length.

$$
\mathrm{RPK}_i = \frac{c_i}{\ell_i}
$$

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

**CPM** (counts per million) divides count by total sample count and multiplies by $10^6$.

$$
\mathrm{CPM}_i = \frac{c_i}{N} \times 10^6
$$

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

**RPKM** (reads per kilobase per million) divides count by both gene length and total reads.

$$
\mathrm{RPKM}_i = \frac{c_i}{\ell_i \cdot (N / 10^6)}
$$

**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

**TPM** (transcripts per million) first calculates RPK, divides by the sum of RPK in the sample, and multiplies by $10^6$.

$$
\mathrm{TPM}_i = \frac{\mathrm{RPK}_i}{\sum_j \mathrm{RPK}_j}\times 10^6
= \frac{c_i / \ell_i}{\sum_j c_j / \ell_j}\times 10^6
$$

Because the final denominator is the sample's own sum, every sample satisfies:

$$
\sum_i \mathrm{TPM}_i = 10^6
$$

If RPKM values are already available, they can be normalized by their sum to obtain TPM.

$$
\mathrm{TPM}_i = \frac{\mathrm{RPKM}_i}{\sum_j \mathrm{RPKM}_j}\times 10^6
$$

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

| 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](/en/lessons/rna-seq-quantification/) to manipulate these calculations. For condition testing with replicate samples, see [Testing Differential Expression across Multiple Samples](/en/lessons/bulk-rna-deg/).

---

### Sources

- Wagner et al., *Measurement of mRNA abundance using RNA-seq data: RPKM measure is inconsistent among samples*, Theory in Biosciences 2012: [DOI](https://doi.org/10.1007/s12064-012-0162-3)
- Lior Pachter, *Models for transcript quantification from RNA-Seq*: [arXiv:1104.3889](https://arxiv.org/abs/1104.3889)
- [Official DESeq2 documentation](https://bioconductor.org/packages/DESeq2/)