第4章 数据标准化方法

标准化这步太容易被忽略了。我刚入行时也觉得差不多就行了,结果第一次投文章,审稿人直接问:“你的样本测序深度差了三倍,凭什么直接比绝对数?” 那叫一个尴尬。从此我再也不敢跳过标准化。

说白了,标准化的目的就一个:消除技术偏差,保留生物学差异。不同样本的测序深度、PCR扩增偏好、批次效应……都会把真实信号淹没掉。你想想看,一个样本测了100万条序列,另一个测了500万条,原始计数差5倍,这能直接比吗?

下面这5种方法是我在实际项目里用得最多的。我会把原理、代码、适用场景和踩过的坑都讲清楚。

核心观点:没有“万能”的标准化方法。选择的关键在于你的数据特征和分析目标。后面我会给出一张决策流程图,帮你快速定位。


4.1 总丰度标准化(Total Sum Normalization)

最直白的方法。每个OTU的计数除以该样本的总计数,再乘以一个统一缩放因子(通常是一百万,得到CPM,即Counts Per Million)。

R代码实现非常简单:

# 原始计数矩阵: 行为OTU, 列为样本
counts <- otu_table
total <- colSums(counts)
cpm <- sweep(counts, 2, total, "/") * 1e6

适用场景:样本间测序深度差异不大(最大/最小 < 2倍),或者做快速探索性分析时用。

缺点也很明显:如果一个样本里出现几个高丰度OTU,会压低其他OTU的相对比例,造成假阴性。我在项目中遇到过这种情况——一个样本里某个OTU占了80%的丰度,其他OTU全部被“稀释”了,差异分析几乎找不到任何差异特征。

避坑:总丰度标准化对异常值非常敏感。如果你的数据里有极端高丰度特征,建议先做过滤再标准化,或者直接换用下文更稳健的方法。


4.2 CSS 标准化(Cumulative Sum Scaling)

CSS来自 metagenomeSeq 包,专为宏基因组数据设计。它的思路是:找到每个样本的“可靠分位数”作为缩放基准,而不是用全部计数。

为什么这样做?因为宏基因组数据极度稀疏,大量OTU在部分样本里计数为0。总丰度标准化会被这些0值干扰,CSS则通过分位数截断来规避这个问题。

用法示例:

library(metagenomeSeq)

# 构建 MRexperiment 对象
obj <- newMRexperiment(counts)

# 计算缩放因子,p=0.5 表示用中位数分位数
obj <- cumNorm(obj, p = 0.5)

# 获取标准化后的计数
norm_counts <- MRcounts(obj, norm = TRUE)

我个人习惯在分析人类肠道宏基因组时优先试CSS。这类数据稀疏度通常 > 80%,CSS的表现明显优于总丰度标准化。

注意: CSS假设数据是负二项分布,如果你的数据不符合这个分布,结果可能不稳定。建议跑完后检查一下缩放因子之间的相关性。


4.3 TMM 标准化(Trimmed Mean of M-values)

TMM来自 edgeR 包,最早是为RNA-seq差异表达设计的。它的核心假设是:大部分特征在样本间没有差异表达,基于这个假设估算出一个缩放因子。

具体操作时,它会剔除掉差异最大的那部分特征(两端的M值),只取中间部分来估算比例。

library(edgeR)

dge <- DGEList(counts = counts)
dge <- calcNormFactors(dge, method = "TMM")

# 获取标准化后的CPM
norm_counts <- cpm(dge)

适用场景:当你怀疑大部分OTU在组间是稳定的时候。比如同一生态位下的重复样本,或者时间序列中相邻时间点的样本。

技巧: 如果你用 edgeR 做差异分析,TMM是默认的标准化方法,直接走完整流程即可,不用手动再算一遍。


4.4 RLE 标准化(Relative Log Expression)

RLE来自 DESeq2 包,思路和TMM类似,也假设大部分特征不变。但计算方法不同:它用每个特征相对于几何均值的比值中位数作为缩放因子。

library(DESeq2)

# 构建 DESeqDataSet
dds <- DESeqDataSetFromMatrix(
  countData = counts,
  colData = metadata,
  design = ~ condition
)

# 估算大小因子
dds <- estimateSizeFactors(dds, type = "ratio")

# 提取标准化后的计数
norm_counts <- counts(dds, normalized = TRUE)

我记得在一个土壤微生物项目中,样本间的测序深度差了将近10倍。用总丰度标准化后,主成分分析(PCA)的第一主成分几乎完全被测序深度解释。换成RLE后,生物学分组才清晰地分开了。

需要留意的是: RLE和TMM都依赖“大部分特征不变”这个前提。在微生物组数据中,如果处理组和对照组的群落结构差异极大(比如 > 50%的OTU发生变化),这个前提就不成立了。这时候两个方法都会偏差。


4.5 分位数标准化(Quantile Normalization)

这个方法的思路很简单:让所有样本的丰度分布完全一致。先把每个特征在各个样本中的丰度排序,然后取同一排名的平均值,替换原始值。

说白了,就是把所有样本强行对齐到同一个分布上。

library(preprocessCore)

# 输入必须是矩阵,行为特征,列为样本
mat <- as.matrix(counts)
norm_mat <- normalize.quantiles(mat)

# 恢复行名和列名
rownames(norm_mat) <- rownames(counts)
colnames(norm_mat) <- colnames(counts)

适用场景: 当你有明显的批次效应,或者样本间分布形态差异很大时。我在整合多个公开数据集时经常用分位数标准化来消除技术层面的分布差异。

但是—— 这个方法很“暴力”。它假设所有样本的丰度分布应该是相同的,这个假设在微生物组里不一定成立。如果不同组之间的群落结构本来就不同,分位数标准化会人为拉平这些差异,导致假阴性。我曾经在一个项目中因此丢掉了两个重要的生物标志物,后悔不已。

避坑: 分位数标准化不适合用于寻找生物标志物。它更适合做降维、聚类等不需要保留绝对丰度关系的分析。


4.6 方法对比与选择依据

上面5种方法各有各的脾气。我整理了一张对比表,方便你快速做决策。

方法 核心原理 适用场景 主要假设 我最推荐的场景
总丰度标准化 除以总计数 × 缩放因子 快速探索、样本深度差异小 无异常高丰度特征 初步数据检查、热图展示
CSS 分位数截断后计算缩放因子 宏基因组、稀疏数据 数据符合负二项分布 人类肠道/环境宏基因组
TMM 修剪M值后估算比例 差异分析、组间差异小 大部分特征不变 使用edgeR做差异分析时
RLE 相对于几何均值的中位数比值 差异分析、组间差异小 大部分特征不变 使用DESeq2做差异分析时
分位数标准化 强制对齐到相同分布 批次校正、降维、聚类 所有样本分布一致 整合多个数据集、PCA/PCoA

下面这张决策流程图,是我根据自己的项目经验总结的。你可以直接从“原始计数数据”出发,沿着问题走到底,找到最适合你的方法。

物种丰度标准化方法选择流程 原始计数数据 需要快速简单? 是 总丰度标准化 否 数据稀疏或宏基因组? 是 CSS 标准化 否 假设大部分OTU不变? 是 TMM 或 RLE 否 需要消除分布差异? 是 分位数标准化 否 试多种方法,看哪个让 生物学分组最清晰 📌 我的建议: • 做差异分析时,优先使用分析工具自带的标准化方法(edgeR→TMM,DESeq2→RLE) • 做降维/聚类时,试试分位数标准化或总丰度标准化 • 数据稀疏度 > 70% 且不做差异分析时,CSS是不错的选择

这张图覆盖了大部分常见场景。但我想强调一点:没有绝对正确的选择。我个人习惯的做法是:针对同一个数据集,跑2-3种标准化方法,然后对比PCA/PCoA的分组分离度,选择那个让生物学分组最清晰的结果。

一个小技巧: 用 cor 函数检查标准化前后样本间的相关性变化。好的标准化应该提高组内相关性,同时不破坏组间差异。如果在标准化后所有样本都变得高度相似(相关系数 > 0.99),那可能是过度标准化了。

标准化方法选好了,下一件事就是怎么评估效果——哪些特征在组间真的有差异?那些就留到后面的差异分析章节去聊了。先把标准化做好,后面的路会顺很多。