肝细胞癌(HCC,LIHC)是全球第六大常见肿瘤、第三大癌症死亡原因。TCGA-LIHC 队列一次性提供 373 例肿瘤 + 50 例癌旁正常的 HiSeqV2 转录组、配套的临床与生存数据,是验证『预后基因签名 + 分子分型』思路最经典的公开数据集之一。本系列两篇文章会把一份完整、可复现、可投稿的生信分析流程拆给你看 ——上篇从原始矩阵跑到一个判别力很强的 13 基因 LASSO-Cox 风险模型;下篇会把这个模型接到列线图、免疫微环境、WGCNA、分子亚型、通路活性、免疫治疗响应签名上,做完一整套机制 + 临床转化的故事线。
第一步 · 数据读入 + 样本注释 + PCA QC
我们直接读 UCSC Xena 镜像下来的三个文件:HiSeqV2 表达矩阵(log2 RSEM)、clinicalMatrix、Pan-Cancer survival。TCGA 的样本条码 14-15 位编码样本类型 —— 01-09 是肿瘤、10-19 是正常。表达矩阵做一次低表达过滤(要求 >25% 样本表达水平 > 1)后还剩 17 214 个基因 × 423 例样本。再用 MAD 取 top-2000 高变基因做 PCA。
# TCGA 条码 -> 样本类型
tcga_sample_type <- function(b) {
code <- substr(b, 14, 15)
ifelse(code %in% sprintf("%02d", 1:9), "Tumor",
ifelse(code %in% sprintf("%02d", 10:19), "Normal", "Other"))
}
keep_g <- rowMeans(expr > 1) >= 0.25 # 17 214 基因
top_var <- names(sort(apply(expr_f, 1, mad), decreasing = TRUE))[1:2000]
pca <- prcomp(t(expr_f[top_var, ]), scale. = TRUE)
第二步 · limma 差异表达:3 653 个稳健 DEG
用 limma + trend + robust eBayes(log2 RSEM 数据直接走 trend 模式)做肿瘤 vs 癌旁正常对比。阈值取 |log2FC| > 1 且 FDR < 0.05,得到 上调 1 605、下调 2 048 共 3 653 个差异基因。
design <- model.matrix(~ 0 + samp$type)
colnames(design) <- levels(samp$type) # Normal / Tumor
contr <- makeContrasts(TvsN = Tumor - Normal, levels = design)
fit <- lmFit(expr_f, design) |> contrasts.fit(contr) |>
eBayes(trend = TRUE, robust = TRUE)
deg <- topTable(fit, coef = "TvsN", number = Inf)
deg$dir <- with(deg, ifelse(adj.P.Val<0.05 & logFC> 1, "Up",
ifelse(adj.P.Val<0.05 & logFC<-1, "Down", "NS")))

第三步 · GO / KEGG / Hallmark 富集:肝代谢崩塌 + 细胞周期暴涨
GO 与 KEGG 用 clusterProfiler 的超几何检验分别对上调 / 下调集合做 ORA;Hallmark 通路则用全谱排序的 t 统计量跑 GSEA,既能看显著条目,也能看作用方向。
3.1 GO ORA · 三本体气泡图

3.2 KEGG ORA

3.3 Hallmark GSEA · NES 排序

第四步 · 生存分析:从 5000 高变基因到 571 个 Cox 显著基因
在 367 例带 OS 信息的肿瘤样本上,对 top-5000 MAD 高变基因 逐个跑 univariate Cox,BH 校正后得到 571 个 FDR < 0.05 的预后基因,与 DEG 取交集得到 432 个『又差异又预后』的稳健候选 —— 这就是下一步 LASSO 的输入特征池。
g_test <- names(sort(gene_mad, decreasing = TRUE))[1:5000]
uv <- do.call(rbind, lapply(g_test, function(g) {
fit <- coxph(Surv(OS.time, OS) ~ as.numeric(xT[g, ]))
s <- summary(fit)
data.frame(gene = g, HR = s$conf.int[,1],
p = s$coefficients[, "Pr(>|z|)"])
}))
uv$fdr <- p.adjust(uv$p, method = "BH") # 571 个 FDR<0.05


第五步 · LASSO-Cox 风险模型:13 个基因,Train AUC > 0.80
把 432 个候选特征送进 10 折交叉验证的 LASSO-Cox,70 / 30 按事件分层切训练 / 测试,seed = 42 全程固定。λ.min 选出的 13 基因 panel:
cvfit <- cv.glmnet(X_tr, y_tr, family = "cox",
alpha = 1, nfolds = 10,
type.measure = "deviance")
lam <- cvfit$lambda.min
beta <- coef(cvfit, s = lam)[, 1]
risk_score <- as.numeric(X %*% beta)
m$risk_group <- factor(ifelse(risk_score >= median_tr, "High", "Low"),
levels = c("Low", "High"))5.1 LASSO 调参与系数路径


5.2 风险评分三联图

5.3 KM 与 time-ROC:训练 / 测试两个集合一致




上篇小结 + 下篇预告
到这里上篇闭环:从原始 TCGA 矩阵 → 3 653 DEG → 571 个 Cox 显著基因 → 432 候选特征 → 13 基因 LASSO-Cox 风险模型。下篇会进一步:
① 把风险评分接进 5 变量列线图,做 1/3/5 年 OS 概率预测 + 校准曲线 + C-index 横向对比;
② ESTIMATE + 28 种免疫细胞 ssGSEA + 检查点表达,看高 / 低风险组的免疫微环境差异;
③ WGCNA 找出与风险评分相关的共表达模块和 hub 基因;
④ ConsensusClusterPlus 鉴定分子亚型 + 亚型 vs 临床 / 通路 / 免疫治疗签名比较。
如果你正打算用 TCGA 任意一个癌种重复这套思路,或者已经做了一半卡在某一步 —— 可以把数据丢给我们,复现 + 出图 + 报告一条龙。下篇见。
—— 长期承接 · 欢迎咨询 ——