生信从湿到干 · 交互式动画教程
⭑ 试用 OmicOne
第 7 章数据分析

归一化:消除测序深度的差异

质控之后,细胞之间的 UMI 总数仍然可以相差好几倍,其中很大一部分来自液滴里的捕获效率和测序深度,而不是生物学。归一化的目的,是让不同细胞的表达可以放在一起比较。

为什么不能直接比较原始计数

设想两个同类型的细胞,基因 A 的真实表达一样。第一个细胞所在的液滴捕获效率高、分到的 reads 多,总共 6,000 个 UMI;第二个只有 3,000 个。第一个细胞里基因 A 的计数大约会是第二个的两倍。如果直接比较原始计数,这个差别会被误读成表达差异。

细胞的总 UMI 数(文库大小)混合了三种来源:液滴里的捕获和逆转录效率(第 3 章)、测序深度(第 4 章),以及细胞真实的 RNA 含量。前两种是技术噪音,第三种是生物学,但从数据里很难把它们分开。

Seurat 默认的 LogNormalize 分两步:

  1. 每个细胞的计数除以该细胞的总 UMI,再乘 10,000(即 CP10k):每个细胞被缩放到相同的总量。
  2. 取 log1p,即 log(1 + x):压缩动态范围,让高表达基因不至于主导后续分析;加 1 是为了处理 0。
obj <- NormalizeData(obj, normalization.method = "LogNormalize", scale.factor = 10000)

在 pbmc3k 上检查深度效应

归一化前后:深度效应去哪了真实数据
正在加载数据…

组件横轴是 QC 后每个细胞的文库大小,纵轴是表达量最高的 500 个基因的平均值,左边是原始 UMI,右边是缩放到每 10,000 之后(取对数之前),并标出 Spearman 相关系数 ρ。归一化前,文库越大,表达值越高,两者几乎同步;缩放之后,这种依赖基本消失。

剩下的少量相关不一定是失败。PBMC 里单核细胞本来就比淋巴细胞大、RNA 多,文库大小有一部分是真实生物学。这也说明了归一化的代价:缩放到相同总量,同时抹掉了细胞之间真实的 RNA 含量差异。

还要注意取对数这一步。第三个面板对 log1p 之后的值画了同样的图,相关明显回升:测得浅的细胞零值更多、计数更离散,对数变换会把这种差别重新带进来。这也是 SCTransform 这类方法想要解决的问题之一。

另一种常用方法是 SCTransform:对每个基因,用正则化负二项回归把计数对测序深度建模,取 Pearson 残差作为归一化后的值。它对深度效应校正得更彻底,并且直接给出后续使用的高变基因。对主要细胞类型而言,两种方法的结果通常相近。

常见误区

  • 以为归一化能去掉一切技术因素。 它处理的是总量差异,环境 RNA、批次效应和细胞组成差异都还在。
  • 盲目回归 percent.mt 或 nCount_RNA。 在 ScaleData 里回归这些变量,可能连同真实的生物学一起去掉。
  • 把 CP10k 当作绝对表达量。 10,000 只是一个方便的尺度,归一化值只在细胞之间相对可比。
  • 用 z 分数做差异分析。 缩放后的值放大了低表达基因的噪音,不适合计算倍数变化。