差异表达分析基本概念:log2倍变化、平均表达量

好,咱们进入正题。要理解 MA 图,得先把两个基本指标说透:log2 倍变化和平均表达量。说白了,一个告诉你基因表达涨了多少倍,另一个告诉你这个基因本身的表达水平高不高。我刚开始做 RNA-seq 那会儿,常常只看 fold change 就激动,结果掉进低表达基因的坑里,后来才明白这俩得放一起看。

1. log2 倍变化 – 涨跌尺度

差异表达分析里最核心的概念就是「倍变化」(Fold Change, FC)。简单说,就是处理组表达量除以对照组表达量。但直接拿原始比值做分析很麻烦——上调 2 倍和下调 2 倍在数值上不对称(2 vs 0.5),而且倍数分布极度右偏。于是我们取 log₂ 变换,把乘法变为加法,对称性就出来了。

定义:log₂FC = log₂(处理组表达量 / 对照组表达量)

或者写成:log₂FC = log₂(处理组) – log₂(对照组)

举个例子,处理组 CPM=100,对照组 CPM=25,那么 log₂FC = log₂(100/25) = log₂(4) = 2。上调 4 倍就是 +2,下调 4 倍就是 –2,完美对称。我个人很喜欢这种镜像关系,在后续可视化里特别直观。

常见的倍数值对照表如下:

倍数变化 (FC)log₂FC生物学含义
0.25–2下调 4 倍
0.5–1下调 2 倍
10无差异
21上调 2 倍
42上调 4 倍
83上调 8 倍

为什么要用 log₂ 而不是自然对数?

因为 log₂ 的每单位变化对应“翻倍”或“减半”,生物学家和白板图最吃这一套。我习惯在报告中直接标 log₂FC,听众秒懂。

不过有个坑要提前说——当某个样品表达量为 0 时,log₂(0) 是负无穷。我曾经在项目里因为没做 pseudo-count 处理,直接导致几十个基因掉了。所以实践中通常会给所有计数加一个小常数(比如 0.5 或 1),再取对数。

# Python 伪代码:计算 log2FC 和平均表达量(添加 pseudo-count)
import numpy as np

cpm_ctrl = np.array([25, 48, 0.2])
cpm_treat = np.array([100, 24, 0.0])
pseudo = 0.5

log2_ctrl = np.log2(cpm_ctrl + pseudo)
log2_treat = np.log2(cpm_treat + pseudo)

log2FC = log2_treat - log2_ctrl
ave_log2 = (log2_ctrl + log2_treat) / 2

print("log2FC:", log2FC)
print("AveLog2:", ave_log2)

2. 平均表达量 – 基因的“底噪”坐标

MA 图里的 A 代表 average,也就是两个条件下平均的 log₂ 表达量。计算公式很简单:

A = (log₂(处理组) + log₂(对照组)) / 2

这个值有什么意义?你想想看:一个低表达基因(比如 CPM=0.5)和一个高表达基因(CPM=500),它们的 log₂FC 可能都是 1,但低表达基因的测量噪音要大得多。A 值就像坐标轴的“底盘”,帮我们区分哪些差异是可靠的。

我个人做差异分析的第一步,就是先用 A 值过滤掉那些平均表达量太低的基因(比如 A < 0.5 或 A < 1),不然 MA 图上会飘出一大片假阳性。这是我在一个线虫项目里吃了亏才学乖的。

注意:平均表达量必须在同一尺度上计算。两个样本的测序深度不同,不能直接拿原始 counts 取平均。必须先用 CPM、TPM 或 RPKM 归一化。我见过有人硬怼 raw counts,结果 A 值完全歪了。

3. log₂FC 与平均表达量联手:MA 图的灵魂

好了,现在我们有 M = log₂FC,有 A = 平均 log₂ 表达量。把每个基因的 (A, M) 点画在二维平面上,就是 MA 图。这张图的核心逻辑是:基因的差异倍数(M)与其表达强度(A)之间通常存在依赖关系。

咱们用一张 SVG 来画清楚这个关系:

MA 图概念示意 – M 与 A 的关系 A (平均 log₂ 表达量) M (log₂FC) M = 0 图例 上调显著 (M>阈值) 下调显著 (M<–阈值) 不显著 低A区域 (高噪音)

从图里可以读出几条经验规律:

  • A 值越小(左侧),散点越“炸”——低表达基因的 log₂FC 波动极大,很多都是假阳性。我建议对于 A < 1 的基因,直接砍掉,除非你有很强的先验知识。
  • A 值中等偏大时,差异倍数趋于稳定——此时 M 的变异主要来自生物学差异,噪音干扰小。
  • 上调 / 下调基因通常分布在 M 轴的上下两端,但需要结合统计学检验(p 值、FDR)才能确认显著性,光看 log₂FC 阈值(比如 |M|>1)是不够的。

4. 实践流程与避坑指南

我们做一个完整差异表达分析时,通常按这个步骤来:

步骤做什么涉及指标
1归一化(CPM/TPM/FPM)文库大小、基因长度
2添加 pseudo-count 并取 log₂处理 0 表达
3计算 log₂FC 和平均表达量 AM、A
4绘制 MA 图,过滤低 A 基因A 阈值(如 A>0.5)
5统计检验(如 edgeR、DESeq2)p 值、FDR
6结合 M 和 p 值判定差异表达基因|M|>1 & FDR<0.05

曾经有个坑:我在一个客户项目里直接用原始 count 算 log₂FC,结果发现某个管家基因的 log₂FC 高达 5,兴奋了半天。后来才想起来,那个样品的测序深度差了 10 倍,根本没有归一化。从那以后,我每次跑差异分析前,必先检查文库大小和归一化方法。

另外,不要迷信固定的 log₂FC 阈值。有些人喜欢设 |M|>1(即 2 倍变化)作为显著,但我在单细胞数据里经常看到真实差异只有 1.5 倍(M≈0.58),而某些高表达基因的噪音也能产生 2 倍差异。所以我更倾向于用统计模型(如 DESeq2 的倍数收缩)给 M 值做一次“去噪音”处理,再画 MA 图——那才是真正干净的图。

一个小技巧:在 MA 图上叠加颜色或大小表示 p 值,可以一眼看到哪些点既变化大又统计显著。我常用 Python 的 matplotlib 配合 scatter plot,alpha 设低一点,再把显著基因用高饱和色突出。

好了,log₂FC 和平均表达量这两个概念讲完了。它们就像 MA 图的左右脚,缺一不可。下一部分咱们会正式进入 MA 图的绘制和解读,到时候这些概念会派上大用场。