Bioinfo, bench to analysis · an interactive tutorial
⭑ Try OmicOne
Chapter 7Analysis

Normalization: removing sequencing depth

After QC, cells still differ several-fold in total UMIs, and much of that comes from capture efficiency in the droplet and sequencing depth rather than biology. Normalization makes the expression of different cells comparable.

Why raw counts cannot be compared

Picture two cells of the same type with the same true expression of gene A. The first cell’s droplet captured efficiently and received many reads, 6,000 UMIs in total; the second has 3,000. Gene A’s count in the first cell will be roughly twice that in the second. Compared as raw counts, the difference would be misread as differential expression.

A cell’s total UMI count (its library size) mixes three sources: capture and reverse-transcription efficiency in the droplet (chapter 3), sequencing depth (chapter 4), and the cell’s real RNA content. The first two are technical noise, the third is biology, and the data alone can hardly tell them apart.

Seurat’s default, LogNormalize, has two steps:

  1. Divide each cell’s counts by its total UMIs and multiply by 10,000 (CP10k), so every cell is scaled to the same total.
  2. Take log1p, i.e. log(1 + x), which compresses the dynamic range so highly expressed genes do not dominate what follows; the 1 handles zeros.
obj <- NormalizeData(obj, normalization.method = "LogNormalize", scale.factor = 10000)

Checking the depth effect on pbmc3k

Before and after normalization: where the depth effect goesReal data
Loading data…

The widget plots each cell’s library size after QC against the mean of the 500 most expressed genes, as raw UMIs on the left and scaled to 10,000 (before the log) on the right, with the Spearman correlation ρ. Before normalization, bigger libraries mean higher values and the two move almost in lockstep; after scaling, the dependence is essentially gone.

The little correlation that remains is not necessarily a failure. In PBMCs, monocytes are larger and carry more RNA than lymphocytes, so part of library size is real biology. That also shows the price of normalization: scaling every cell to the same total also removes real differences in RNA content between cells.

Watch the log step too. The third panel draws the same plot on the log1p values, and the correlation climbs back noticeably: shallow cells have more zeros and noisier counts, and the log transform reintroduces that difference. This is one of the problems methods such as SCTransform try to solve.

The other common method is SCTransform: for each gene, a regularised negative-binomial regression models the counts against sequencing depth, and the Pearson residuals become the normalized values. It removes the depth effect more thoroughly and directly provides the variable genes used next. For the main cell types, the two methods usually give similar results.

Common pitfalls

  • Expecting normalization to remove every technical factor. It handles differences in totals; ambient RNA, batch effects and composition differences remain.
  • Regressing out percent.mt or nCount_RNA by reflex. Regressing these in ScaleData can remove real biology with them.
  • Reading CP10k as absolute expression. 10,000 is just a convenient scale; normalized values are comparable between cells, not absolute.
  • Running differential expression on z-scores. Scaled values amplify the noise of lowly expressed genes and are unsuitable for fold changes.