跳到正文
百沐一下百沐一下
本节目录

单基因泛癌分析

跟完这篇,您能拿一个感兴趣的基因,在 TCGA 的 33 个癌种里系统扫一遍它的表达、预后、免疫浸润、突变四件事,把散落的分癌种结果拼成一条能讲的线索,并且清楚知道这条线索的分量到哪为止、下一步该往哪深挖。

泛癌分析在做什么

泛癌分析(pan-cancer analysis)就一句话:拿一个基因,横跨多种癌症统一看它的行为,而不是只盯着一种病。

它的默认舞台是 TCGA(The Cancer Genome Atlas)。TCGA 把肿瘤样本按癌种整理成 33 个项目,每个项目一个癌种,用四个字母的缩写标识:

缩写癌种缩写癌种
BRCA乳腺癌LUAD肺腺癌
LIHC肝细胞癌LUSC肺鳞癌
COAD结肠腺癌STAD胃腺癌
KIRC肾透明细胞癌PRAD前列腺腺癌

(上表只列了常见的几个,完整是 33 个。)

「泛癌」的价值在于看一致性:如果一个基因只在某一种癌里异常,可能是个案;但如果它在十几个癌种里都往同一个方向变,这种跨癌种的一致信号,往往更值得往下追。所以泛癌分析在您研究流程里的位置很明确——它是筛线索、提假设的第一步,不是下结论的最后一步。

具体到一个基因,一次标准分析通常就围绕这四个维度展开,逐个维度在每个癌种里各算一遍,再横向拼起来看:

维度问的问题常用做法
表达差异肿瘤 vs 正常,这个基因高了还是低了分癌种做 Wilcoxon 秩和检验,看方向和显著性
预后表达高低和病人活得久不久有没有关系按表达中位数分高/低组,做 KM + log-rank,或用 Cox 求风险比
免疫浸润表达和肿瘤里免疫细胞的多少相不相关和免疫浸润评分做 Spearman 相关
突变基因或其所在通路的突变状态与表达有没有关联比较突变型 vs 野生型的表达,或与 TMB 相关

下面就按「准备数据 → 四步各跑一遍 → 拼成线索」的顺序走一遍,代码用标准 R 包,改一个基因名就能套到您自己的分析上。

准备:选基因、取数据

您几乎不用自己从原始测序数据算起。主流两个入口,先看用哪个:

入口拿到的是什么适合
GDC(portal.gdc.cancer.govTCGA 官方门户,字段最全、最原始要最完整数据做深入分析;R 里常用 TCGAbiolinks 批量下载
UCSC Xena(xenabrowser.net已归一化、开箱即用的规整矩阵想快速把一个基因扫一遍、出泛癌图(推荐上手

Xena 还专门提供了一个把 TCGA 肿瘤和 GTEx 正常组织统一处理的合并队列(常记作 TCGA TARGET GTEx),正好补上 TCGA 正常样本太少的短板——这是做「肿瘤 vs 正常」泛癌图最常用的数据来源。这里就以 Xena 下载下来的文本矩阵为例。

先把三张表读进 R:

library(data.table)

gene <- "TP53"   # 换成您关心的基因

# 从 UCSC Xena 下载的文本矩阵,本地读入即可(文件名以您下载到的为准)
# expr:行是基因,列是样本;值是已做 log2 归一化的表达量
expr  <- fread("expression.tsv", data.table = FALSE)
# pheno:每个样本一行,含癌种、样本类型(肿瘤 / 正常)等注释
pheno <- fread("phenotype.tsv",  data.table = FALSE)
# surv:每个样本一行,含生存时间与结局(0 = 存活 / 1 = 死亡)
surv  <- fread("survival.tsv",   data.table = FALSE)

后面几步都建立在同一批对象上,先记清它们各自「一行是什么」:

对象一行是什么关键列
expr一个基因各样本列的表达值
pheno一个样本癌种、样本类型(肿瘤 / 正常)
surv一个样本生存时间、结局(0/1)
infil一个样本各免疫细胞评分(第三步再拿到)

再把目标基因那一行取出来,拼成「每行一个样本」的长表,方便按癌种分组:

library(dplyr)

# 取出目标基因所在行,转成每样本一行
dat <- data.frame(
  sample = colnames(expr)[-1],
  expr   = as.numeric(expr[expr[[1]] == gene, -1]),
  type   = pheno$sample_type,   # "Tumor" / "Normal"
  cancer = pheno$cancer
)

数据下下来后怎么整理成规范矩阵(去重、对齐样本、处理缺失),见 表达矩阵整理

第一步:肿瘤 vs 正常的表达差异

最基础的一件事——这个基因在肿瘤里是不是异常表达。泛癌的做法不是只比一次,而是逐癌种各比一次,再横着看

res <- dat %>%
  filter(!is.na(type)) %>%
  group_by(cancer) %>%
  summarise(p = wilcox.test(expr ~ type)$p.value, .groups = "drop") %>%
  mutate(padj = p.adjust(p, method = "BH"))   # 跨癌种做多重检验校正

这里用 Wilcoxon 秩和检验,是因为要在几十个癌种上快速统一比,非参数、不挑分布最省心。多个癌种一起检验,一定要做多重比较校正(这里用 BH 法);padj<0.05常用惯例、不是铁律,按数据和检验数量调整。

呈现上,跨癌种表达差异约定俗成用分组箱线图(每个癌种一对肿瘤/正常):

library(ggplot2)

ggplot(filter(dat, !is.na(type)), aes(cancer, expr, fill = type)) +
  geom_boxplot(outlier.size = 0.3) +
  labs(x = NULL, y = "log2 表达量", fill = NULL) +
  theme(axis.text.x = element_text(angle = 90, hjust = 1))

两点提醒:

  • TCGA 正常样本很少,很多癌种只有个位数甚至没有配对正常组织。补 GTEx 正常组织(即上一节的合并队列)能救急,但那是两个来源拼在一起,批次差异要留个心眼。
  • Wilcoxon 适合「快速扫一遍」。若要在某一个癌种里做严谨的差异表达,应回到原始 read count 用 DESeq2/edgeR,见 用 DESeq2 做差异表达

第二步:表达与预后

把每个癌种的病人按目标基因表达切成高、低两组,看表达高低和活得久不久有没有关系。泛癌里最常用 Cox 求风险比 HR,一个数就能横向比较各癌种:

library(survival)

cancers <- unique(surv$cancer)
hr <- lapply(cancers, function(cc) {
  d <- merge(subset(surv, cancer == cc), dat[, c("sample", "expr")], by = "sample")
  # 按中位数分高 / 低组,指定低表达为参照,HR 即「高 vs 低」
  d$group <- factor(ifelse(d$expr > median(d$expr), "high", "low"),
                    levels = c("low", "high"))
  s <- summary(coxph(Surv(time, event) ~ group, data = d))
  data.frame(cancer = cc,
             HR    = s$conf.int[1, "exp(coef)"],
             lower = s$conf.int[1, "lower .95"],
             upper = s$conf.int[1, "upper .95"],
             p     = s$coefficients[1, "Pr(>|z|)"])
})
hr <- do.call(rbind, hr)

按中位数切是最稳、最好复现的做法。想更直观地看「高低两组的生存曲线拉不拉得开」,再补 KM + log-rank(survdiff)。生存分析的门道(删失、log-rank、最佳截断为什么容易过拟合)见 生存分析

预后结果的约定画法是森林图:一张图看尽各癌种的 HR 与置信区间,HR = 1 的竖线是「无差异」的分界。

ggplot(hr, aes(x = HR, y = reorder(cancer, HR))) +
  geom_point() +
  geom_errorbarh(aes(xmin = lower, xmax = upper), height = 0.2) +
  geom_vline(xintercept = 1, linetype = "dashed") +
  scale_x_log10() +                       # HR 用对数轴,左右才对称
  labs(x = "风险比 HR(高表达 vs 低表达)", y = NULL)

读图:点落在竖线右侧(HR>1)且置信区间不跨过 1,说明在该癌种里高表达关联更差的生存;落在左侧则相反。

第三步:免疫浸润相关

想知道这个基因和肿瘤微环境里的免疫细胞有没有关系,标准做法分两步:先用成熟算法从表达谱反推每个样本的免疫浸润,再和目标基因表达做相关。常见的反推算法:

算法给出什么
CIBERSORT22 种免疫细胞的相对比例
ESTIMATE免疫评分(ImmuneScore)与基质评分(StromalScore)
ssGSEA / MCP-counter / xCell各有一套免疫细胞打分

假设您已经算出(或从工具导出)一张 infil 表——每样本一行、各免疫细胞评分为列。把它和表达并到一起,逐癌种、逐细胞类型做 Spearman 相关

library(tidyr)

m <- dat %>% inner_join(infil, by = "sample")   # 表达 + 各免疫细胞评分

corr <- m %>%
  pivot_longer(c(CD8_Tcell, Macrophage_M2, Treg),   # 举例几类细胞
               names_to = "cell", values_to = "score") %>%
  group_by(cancer, cell) %>%
  summarise(rho = cor(expr, score, method = "spearman"),
            p   = cor.test(expr, score, method = "spearman")$p.value,
            .groups = "drop")

多用 Spearman(不假设线性、对离群值更稳)。结果的约定画法是气泡热图:行是癌种、列是免疫细胞,颜色示相关方向、点大小示显著性。

ggplot(corr, aes(cell, cancer)) +
  geom_point(aes(size = -log10(p), color = rho)) +
  scale_color_gradient2(low = "blue", mid = "white", high = "red", midpoint = 0) +
  labs(x = NULL, y = NULL, color = "Spearman ρ", size = "-log10(p)")

不想自己跑算法,也有现成网页工具(如 TIMER2.0)能直接查一个基因和免疫浸润的跨癌种相关。无论哪条路,都要记住:相关不等于因果,这里得到的只是「表达和某类免疫细胞丰度同向或反向变化」,不能直接说谁调控谁。

第四步:突变关联

看目标基因的突变状态或整体突变负荷与表达的关系:比较突变型与野生型样本的表达差异,或和肿瘤突变负荷(TMB)、微卫星不稳定性(MSI)做相关。

# status:每个样本目标基因的突变状态("Mutant" / "WT")
wilcox.test(expr ~ status, data = mut_LUAD)

# 或与肿瘤突变负荷 TMB 做相关
cor.test(m$expr, m$TMB, method = "spearman")

这一维度的解读要更保守:单基因突变频率在多数癌种里都不高,样本一分组就很小,结论务必留余地,别在小样本上硬讲显著。

把四步串成一条线索

四步各自跑完,您手上是一堆分癌种的表格和三张图。真正有价值的一步,是把它们横向拼起来,看能不能连成一条自洽的线索。一个站得住的叙事骨架是这样递进的:

  1. 一致性:先看第一步。这个基因是不是在多个癌种里都朝同一方向异常(比如在十几种癌里都显著高表达)?跨癌种的一致,是整条故事的地基。
  2. 临床相关:叠上第二步。在那些高表达的癌种里,森林图上的 HR 是不是也大多关联更差的生存?表达异常又与结局相关,线索就从「有变化」升级到「可能有意义」。
  3. 机制线索:接着看第三、四步,给这条线索一个可能的方向。比如表达与某类免疫细胞浸润稳定相关,提示它可能牵涉免疫微环境——注意这只是提示方向,不是证明机制。
  4. 收敛到一个癌种:泛癌图把面铺开,真正能深挖的是点。根据前三步,挑一个信号最强、又最贴合您研究背景的癌种,作为后续单癌种深入研究的落点。

把这条线讲出来,大致就是:「基因 X 在多个癌种中一致高表达,且高表达普遍关联更差预后,同时与免疫浸润相关,提示它可能是一个值得深入研究的候选。」 注意每句都落在「关联」「提示」「候选」这类词上——泛癌分析支撑得起的,就是到这个分量为止。三张图各司其职:箱线图给一致性,森林图给临床相关,气泡热图给机制线索。

边界:别过度解读

这一节比前面都重要。泛癌分析最容易被过度解读,用之前请把下面几条钉在心里。

  • 它是广撒网筛线索,不是下定论。 泛癌的产出是假设:哪个基因、在哪些癌种里、值得深入看。它本身不构成机制证明,也替代不了单癌种的精细分析和实验验证。
  • 同时扫几十个癌种,多重比较被放大。 一个基因在 33 个癌种里各做一次检验,纯靠运气也会撞出几个「显著」。跨癌种汇报务必做多重检验校正(如 BH 法),padj<0.05 只是常用惯例、非铁律
  • 相关不是因果。 免疫浸润相关、预后关联,都是观察到的共变,不能推出调控或驱动关系。措辞老实地停在「相关」「关联」。
  • 数据来源的坑要认。 TCGA 正常样本少、拼 GTEx 会引入批次效应;不同癌种样本量差异巨大(小样本癌种的结论天然更不稳);表达是 bulk 的平均值,掩盖了细胞异质性。这些都会左右结论,报告时该讲清就讲清。
  • 一致 ≠ 一样。 就算一个基因在多个癌种里都高表达,它在每种癌里的生物学角色也可能完全不同。泛癌看到的是统计上的共性,落到具体某种癌,还得回到那个癌种的背景里重新理解。

一句话收束:把泛癌分析当成「地图」,它告诉您值得往哪走;真正的发现,在您照着地图选定一个癌种、深入挖下去之后。

在平台上跑一遍

上面这四步,在百沐一下不用写代码也能做:说清您要分析的基因(比如「帮我对 TP53 做泛癌分析」),平台会自动从公共数据库取数、分癌种跑完表达、预后、免疫浸润这几步,把箱线图、森林图、相关性热图一并给您,并附上可复现的 R 代码。您要做的,是核对癌种选得对不对、把结果读成一条自己能讲的线索。想连自己的数据一起分析也可以,直接上传即可。

上手见 组学智能体使用指南,或直接开始:https://app.baimuyixia.com

相关