免疫浸润分析:CIBERSORT / ssGSEA
跟完这篇,您能从一份 bulk 表达谱出发,用 CIBERSORT 或 ssGSEA 估出每个样本的免疫细胞构成,再把结果接到分组比较或关键基因上,出一张能讲清楚的箱线图、堆叠条形图或相关热图,并且知道这类估计能说到哪、不能说到哪。
这类方法在估什么
bulk RNA-seq 或芯片测到的,是一整块组织里所有细胞混在一起的平均表达。免疫浸润分析想回答的是:这块组织里,各类免疫细胞大致占多少、活跃到什么程度。
思路很朴素:不同免疫细胞各有一套标志基因,如果某类细胞在样本里多,它那套标志基因的整体表达就会被「顶」高。于是我们反过来,从混合表达谱去反推每类细胞的相对多少。这一步得到的不是真实细胞数,而是一个相对的比例或活性估计。
它常用来做三件事:
- 描述某种组织、某组病人的免疫「地貌」——哪几类细胞多、哪几类少。
- 比较两组之间(如高低表达组、有无突变组)某类免疫细胞的差异。
- 看某个关键基因的表达,和某类免疫细胞浸润是否同增同减。
CIBERSORT 与 ssGSEA:反卷积 vs 打分
两者都做免疫浸润,但底层是两套不同思路,结果的含义也不一样,别混着解读。
CIBERSORT 走「反卷积」:把混合表达谱当成各细胞类型表达谱按比例的叠加,用一份细胞特征矩阵(经典的是 LM22,覆盖 22 种免疫细胞亚群)作参照,用支持向量回归把比例解出来。输出是相对比例,一个样本内各类型加和约为 1,另外还给一个置换检验 P 值,衡量这次拟合可不可信。
ssGSEA(single-sample GSEA)走「打分」:对每个样本、每套免疫细胞标志基因集,按基因在该样本内的表达排名算一个富集分数。分数高,说明这套标志基因在该样本里整体偏高,对应细胞的浸润倾向更强。输出是相对活性得分,不代表比例、也不加和为 1。
| 维度 | CIBERSORT(反卷积) | ssGSEA(打分) |
|---|---|---|
| 思路 | 把混合谱拆回各细胞类型的比例 | 按标志基因集给每个样本打富集分 |
| 输出含义 | 相对比例,样本内加和约为 1 | 相对得分,不代表比例、不加和 |
| 依赖 | 一份细胞特征矩阵(如 LM22,22 种细胞) | 一套免疫细胞标志基因集 |
| 典型解读 | 「这个样本里 CD8 T 细胞约占 X%」 | 「A 组的 CD8 T 细胞浸润得分高于 B 组」 |
| 常见实现 | CIBERSORT / CIBERSORTx、immunedeconv | GSVA(method = "ssgsea") |
一句话记忆:要「占多少比例」用反卷积,要「哪组更高」用打分。 实际做时两种常一起跑,互相印证。
除这两者外,同类方法还有不少,思路各有侧重,这里给个速查表,本篇只展开前两者:
| 方法 | 输出 | 特点 |
|---|---|---|
| CIBERSORT / CIBERSORTx | 相对比例(CIBERSORTx 可给绝对量) | LM22 反卷积,最经典 |
| ssGSEA(GSVA) | 富集得分 | 依赖标志基因集,用途广 |
| ESTIMATE | 免疫/基质/纯度总分 | 不分细胞亚型,只给整体免疫评分 |
| xCell | 富集得分 | 覆盖细胞类型多 |
| MCP-counter | 丰度得分 | 同一细胞类型可跨样本比 |
| quanTIseq / EPIC | 绝对比例 | 给可跨样本比的绝对分数 |
第一步:先把输入表达谱准备对
方法再好,喂错数据也白搭。免疫浸润对输入有几条通行要求:
- 矩阵形状:行是基因、列是样本;行名用官方基因 symbol,好和特征矩阵、标志基因集对齐。
- 基因去重:同一 symbol 对应多探针/多行时,按惯例保留表达最高(或均值最大)的那一行。
- 样本间可比:尽量同一平台、同一流程处理,留意批次;跨平台混用前先想清楚可比性。
- 表达值类型:不同方法对「用 log 还是不用 log」的偏好不同,见下表。
| 方法 | 建议输入 | 空间 |
|---|---|---|
| CIBERSORT | TPM(芯片用归一化后的值) | 线性、非 log |
| ssGSEA | log2(TPM + 1) 或 TPM 均可 | 基于秩次,相对稳健 |
去重可以用这段标准写法:
# expr:基因(行) x 样本(列),行名是 symbol,可能有重复
expr <- expr[order(-rowMeans(expr)), ] # 按行均值从大到小排
expr <- expr[!duplicated(rownames(expr)), ] # 同名只留均值最大的第一行
这些是常用惯例、非铁律,具体按您的数据和所选实现的文档调整。表达矩阵怎么从测序数据一步步做出来,见 RNA-seq 分析全流程。
第二步:跑 CIBERSORT / ssGSEA
下面给两种方法的最小骨架,代码用来说明流程,不必当作可直接运行的完整脚本。
CIBERSORT(借 immunedeconv 包统一接口)。注意:CIBERSORT 的源码与 LM22 特征矩阵有使用许可,需从官网注册获取后再注册本地路径:
library(immunedeconv)
# 源码与 LM22 从 CIBERSORT 官网获取后,注册本地路径(需先注册账号)
set_cibersort_binary("./CIBERSORT.R")
set_cibersort_mat("./LM22.txt")
# expr_tpm:基因(symbol) x 样本 的 TPM 矩阵,线性空间
res <- deconvolute(expr_tpm, method = "cibersort")
# res:每种免疫细胞在各样本中的相对比例(每列样本加和约为 1)
ssGSEA(用 GSVA 包)。免疫细胞标志基因集可采用文献整理好的公开版本(如 Bindea、Charoentong 等):
library(GSVA)
# expr:基因 x 样本 矩阵(log2-TPM 可)
# gene_sets:各免疫细胞的标志基因集,named list
# 新版 GSVA(≥1.50):先建参数对象,再跑
par <- ssgseaParam(as.matrix(expr), gene_sets)
es <- gsva(par)
# es:每个样本在每套免疫细胞基因集上的富集得分
# 旧版写法:gsva(expr, gene_sets, method = "ssgsea")
跑完 CIBERSORT 后,按惯例可用置换检验 P(如 P < 0.05)筛掉拟合不佳的样本再往下分析——这是常用惯例、非铁律,按数据实际情况定。ssGSEA 没有这一步,它对每个样本都会给分。
第三步:和分组或关键基因关联出图
估出细胞构成只是中间产物,真正要讲的故事在关联这一步。常见有三种出法。
组间比较(箱线图 + Wilcoxon)
看某类免疫细胞在两组间是否不同,常用箱线图加非参数检验:
library(tidyverse)
# frac:样本 sample、分组 group,加上各细胞类型的比例(或得分)
frac_long <- frac %>%
pivot_longer(-c(sample, group), names_to = "cell", values_to = "value")
ggplot(frac_long, aes(group, value, fill = group)) +
geom_boxplot(outlier.size = 0.5) +
facet_wrap(~ cell, scales = "free_y") + # 每类细胞一格
ggpubr::stat_compare_means(method = "wilcox.test", label = "p.format")
多组比较、以及 Wilcoxon 之外何时该换检验,见 统计方法怎么选。多个细胞类型同时比时,务必对 P 值做多重检验校正,否则假阳性会很多。
与关键基因相关(Spearman)
看某个基因的表达和某类免疫细胞浸润是否同增同减,常用 Spearman 相关(对离群更稳、不要求正态):
# gene_expr:关键基因表达向量;score:某免疫细胞的得分或比例(样本顺序对齐)
cor.test(gene_expr, score, method = "spearman")
多个基因对多类细胞时,把两两相关系数算成矩阵,画成相关性热图,一眼看出哪对最强:
# genes_expr:样本 x 关键基因;cell_scores:样本 x 细胞类型(行样本已对齐)
M <- cor(genes_expr, cell_scores, method = "spearman")
pheatmap::pheatmap(M) # 行:基因 列:细胞类型,颜色=相关方向与强弱
整体免疫地貌(堆叠条形图)
想一眼看清每个样本的细胞构成,用堆叠条形图(更适合 CIBERSORT 的比例,加和约为 1):
# frac_long 同上:sample、cell、value
ggplot(frac_long, aes(sample, value, fill = cell)) +
geom_col(position = "stack") + # 每个样本一根,堆叠各细胞比例
theme(axis.text.x = element_blank()) # 样本多时隐藏样本名
结果怎么读、怎么写
图出好了,落到笔头。读和写时守住几点,结论才立得住:
-
先说清用的是哪种估计:写明方法(CIBERSORT 还是 ssGSEA)、参考(LM22 或哪套基因集)、输入是什么表达值,别人才能复现。
-
组间比较要报检验和校正:给出 Wilcoxon(或所换检验)的 P 值,并说明是否做了多重检验校正。
-
相关要同时报系数和方向:Spearman ρ 的大小与正负都写上,别只说「显著相关」。
-
一句话范式(可直接改用):
与低表达组相比,基因 X 高表达组的 CD8 T 细胞浸润得分显著更高(Wilcoxon p < 0.05);且 X 表达与 CD8 T 细胞得分呈正相关(Spearman ρ = 0.4,p < 0.001)。
(句中数字仅为示例格式,请换成您自己的真实结果。)
边界:这是估计,不是细胞计数
这一步最容易出问题,写结论前请守住这几条线:
- 是估计,不是实测。 结果高度依赖所选的参考矩阵或标志基因集,换一套参照,数值甚至排序都可能变。它替代不了流式、免疫组化或单细胞这类直接测量。
- 相对,不是绝对。 CIBERSORT 给的是样本内相对比例,跨样本比较某一类型的绝对量要谨慎;ssGSEA 的得分只在同一基因集内、跨样本比才有意义,不同细胞类型之间的分值不能直接横比。
- 注意参照的适用范围。 像 LM22 这类特征矩阵主要基于外周血免疫细胞,用到实体瘤或其它组织时可能不完全贴合,解读要留余地。
- 低丰度细胞噪声大。 占比很低的细胞类型,估计波动大,别在它上面下太重的结论。
- 别当细胞计数报。 描述结果时说「浸润得分更高」「估计比例更高」,而不是「多了 N 个细胞」。有条件时,用另一种方法或独立证据(如单细胞、免疫组化)交叉验证,结论会稳得多。
在平台上跑一遍
在百沐一下,您不用自己配 R 环境、找特征矩阵或对齐基因集:上传表达矩阵,说清「做免疫浸润、按分组比较」,智能体会挑合适的方法把 CIBERSORT/ssGSEA 跑完,出好箱线图、堆叠条形图或相关热图,并把上面这些边界一并提示给您,同时附可复现的 R 代码。想先了解它怎么理解您的数据和目的,见 组学智能体,或直接开始:https://app.baimuyixia.com。