STEP 11 / 14

組學定量分析

RNA-seq、Proteomics——counts、TPM、log2FC、DESeq2 的正確使用姿勢。

RNA-seq, proteomics — counts, TPM, log2FC, and DESeq2 done right.

為什麼 raw counts 不能直接比?

RNA-seq 與 LFQ proteomics 的原始 counts 受 (1) 樣本總定序深度、(2) 基因/蛋白長度、(3) 組成偏差影響。Wagner et al. 2012 證明 RPKM/FPKM 在樣本間不可比(總和不為定值),TPM 才是現代標準。但 TPM 仍不適合 DE 分析——應改用 negative binomial 模型(DESeq2 / edgeR)或 voom 加權 (Law 2014)。

差異基因分析的金標準是 DESeq2 (Love et al. 2014, Genome Biol) + apeglm (Zhu et al. 2018) 的 shrinkage log2FC。蛋白體 LFQ 用 MaxLFQ (Cox et al. 2014, MCP) 配合 Perseus / FragPipe / DIA-NN。

Raw counts from RNA-seq / LFQ proteomics are influenced by (1) total sequencing depth, (2) gene/protein length, (3) composition bias. Wagner 2012 proved RPKM/FPKM are not comparable across samples (sum is not constant); TPM is now the standard. But TPM is still wrong for DE — use negative binomial models (DESeq2 / edgeR) or voom weighting (Law 2014).

The DE gold standard: DESeq2 (Love et al. 2014, Genome Biol) + apeglm (Zhu et al. 2018) shrinkage log2FC. Proteomics LFQ uses MaxLFQ (Cox et al. 2014, MCP) with Perseus / FragPipe / DIA-NN.

⚠️
核心:(1) DE 分析絕不直接用 TPM/FPKM 做 t-test;應給 DESeq2 raw counts;(2) 排序基因時應用 shrunken log2FC,否則低 count 基因因大變異被誤判。Core: (1) Never run t-test on TPM/FPKM for DE — feed raw counts to DESeq2; (2) Rank genes by shrunken log2FC; otherwise low-count genes get inflated by noise.

一、定量單位辨識卡

單位計算可比?DE 用
Raw counts原始 read 數✓ DESeq2
RPKM / FPKMcounts / (length × total/1e6 / 1000)總和不定
TPM先除長度總和固定無變異模型
DESeq2 norm counts中位比例
vst / rlogVSTPCA
MaxLFQ intensity配對比例蛋白

apeglm shrinkage 讓低 count 基因不再吵

調整 base mean 與 dispersion,觀察 raw 與 shrunken log2FC 差異。關鍵:低 count 基因 raw log2FC 變異極大,shrinkage 把它們拉回 0,讓排序更可靠。

Adjust base mean and dispersion. Key: low-count genes have wild raw log2FC; shrinkage pulls them toward zero, making rankings reliable.

MA plot

二、DESeq2 完整流程

library(DESeq2); library(apeglm)

# 1. 從 tximport 建 dds(建議 gene-level)
library(tximport)
txi <- tximport(files=salmon_files, type="salmon", tx2gene=tx2gene)
dds <- DESeqDataSetFromTximport(txi, colData=coldata, design= ~ condition)

# 2. 預過濾低 count(提速)
dds <- dds[rowSums(counts(dds)) >= 10, ]

# 3. 跑差異分析
dds <- DESeq(dds)
res <- results(dds, contrast=c("condition","treated","control"))

# 4. log2FC shrinkage(apeglm 推薦)
res_shr <- lfcShrink(dds, coef="condition_treated_vs_control", type="apeglm")

# 5. VST 用於 PCA / heatmap
vsd <- vst(dds, blind=FALSE)
plotPCA(vsd, intgroup="condition")

# 6. Volcano plot
library(EnhancedVolcano)
EnhancedVolcano(res_shr, lab=rownames(res_shr), x="log2FoldChange", y="padj")
from pydeseq2.dds import DeseqDataSet
from pydeseq2.ds import DeseqStats

dds = DeseqDataSet(counts=counts_df, metadata=meta, design_factors="condition", refit_cooks=True)
dds.deseq2()

stat_res = DeseqStats(dds, contrast=["condition","treated","control"])
stat_res.summary()             # 含 padj (BH-FDR)
stat_res.lfc_shrink(coeff="condition_treated_vs_control")   # apeglm

# PCA (sklearn)
from sklearn.decomposition import PCA
import numpy as np
log_counts = np.log1p(dds.layers["normed_counts"])
pca = PCA(n_components=2).fit_transform(log_counts.T)

三、最常見錯誤

把 TPM 餵 t-test

TPM 不滿足 NB 假設,違反獨立性。請給 DESeq2 raw counts。

TPM violates NB assumptions and independence. Feed raw counts to DESeq2.

忽略 shrinkage

未 shrink 的 log2FC 在低 count 區噪聲極大;篩 top hits 會優先選到低 count 基因。

Un-shrunken log2FC is noisy at low counts; top hits become dominated by low-count genes.

n=3 就跑 DE

DESeq2 / edgeR 在 n=3 對 dispersion 估計很差,多為 false positive。2025 文獻建議 biological n ≥ 6,理想 12。

DESeq2 / edgeR estimate dispersion poorly at n=3 → high FP. 2025 reviews recommend biological n ≥ 6, ideally 12.

蛋白體亂 imputation

MaxLFQ 缺失值常為 MNAR(低豐度未檢出)。先以 valid value 過濾再用 left-shifted Gaussian imputation。

MaxLFQ missing values are usually MNAR (low-abundance, not detected). Filter valid values first, then left-shifted Gaussian imputation.

🎯 章末小測驗

1. 樣本間可比的 RNA-seq 單位?

Raw counts
RPKM / FPKM
TPM
log2 counts

2. 排序 DE 基因用?

Raw log2FC
Shrunken log2FC
−log10(p)
TPM ratio

3. RNA-seq DE 最少 n?

2
3
≥ 6(理想 12)
100