跳转至

免疫浸润分析(CIBERSORT/xCell/MCP-counter/TIMER)

一句话概述

免疫浸润分析是利用CIBERSORT、xCell、MCP-counter、TIMER等计算方法,从肿瘤或组织的bulk RNA-seq/微阵列表达数据中估计免疫细胞组成比例或丰度的生物信息学分析方法,是肿瘤免疫微环境研究和免疫治疗应答预测的核心分析手段。


核心知识点表格

知识点说明
CIBERSORT基于线性支持向量回归(ν-SVR)的免疫反卷积方法
CIBERSORTxCIBERSORT升级版,支持scRNA-seq参考和批次校正
xCell基于ssGSEA+校正的64种细胞类型评估方法
MCP-counter基于转录标记物的8+2种细胞绝对丰度评估
TIMER基于反卷积的6种免疫细胞推断方法
TIMER2.0/TIMER3整合多种方法的免疫浸润分析平台(TIMER3已于2025年发布)
ESTIMATE基质评分+免疫评分+肿瘤纯度估计
反卷积Deconvolution,从混合信号分解出各组分比例
参考矩阵Signature matrix,已知细胞类型的基因表达参考
LM22CIBERSORT使用的22种免疫细胞参考矩阵
免疫评分定量衡量肿瘤免疫微环境状态的指标
免疫亚型基于免疫浸润模式的肿瘤分子分型

各步骤详解

第一步:免疫浸润分析原理与方法分类

白话解释: 一块肿瘤组织里不只有癌细胞,还混杂着各种免疫细胞(T细胞、巨噬细胞等)、成纤维细胞、内皮细胞等。当我们对这块组织做RNA-seq时,测到的是所有细胞的混合信号。免疫浸润分析就是从这个"混合液"中"分离"出各种免疫细胞的比例或丰度,像从鸡尾酒中分析出各种成分的含量。

技术细节:

方法分类:

类别方法原理输出
反卷积CIBERSORTν-SVR回归22种细胞相对比例(和=1)
反卷积TIMER约束线性回归6种免疫细胞比例
反卷积quanTIseq约束回归+校正10种细胞绝对比例
打分xCellssGSEA+校正64种细胞相对丰度
打分MCP-counter标记基因均值10种细胞绝对丰度
打分ESTIMATEssGSEA免疫/基质/纯度分数
打分ssGSEA单样本GSEA自定义细胞活性分数
打分EPIC约束最小二乘细胞比例

各方法输出的细胞类型数量: - CIBERSORT/LM22:22种(含T细胞亚群、B细胞、NK细胞、巨噬细胞极化等) - xCell:64种(最全面,含基质细胞、干细胞等) - MCP-counter:10种(8种免疫+2种基质) - TIMER:6种(B细胞、CD4+ T、CD8+ T、中性粒细胞、巨噬细胞、树突细胞) - quanTIseq:10种(含Tregs) - EPIC:6种

第二步:CIBERSORT分析

白话解释: CIBERSORT用22种已知免疫细胞的基因表达"指纹"(LM22参考矩阵)作为模板,然后用机器学习方法(支持向量回归)去"解方程"——算出要把这些模板按什么比例混合,才能最好地重现样本的表达谱。

技术细节: 数学模型:M × f = b - M: 参考矩阵 (基因 × 细胞类型) - f: 各细胞类型比例 (未知,待求解) - b: 混合样本表达 (观测值)

CIBERSORT使用ν-SVR而非普通线性回归的原因: - SVR对异常值鲁棒 - 自动执行特征选择(不是所有基因都有用) - ν参数控制误差容忍度

# ===== CIBERSORT/CIBERSORTx R实现 =====
# 方法1:使用IOBR包(整合多种方法)
# remotes::install_github("IOBR/IOBR")  # 从GitHub安装,不在Bioconductor上
library(IOBR)

# 准备表达矩阵(基因symbol为行名,TPM/FPKM值)
expr_matrix <- as.matrix(read.csv("expression_tpm.csv", row.names = 1))

# CIBERSORT分析
cibersort_result <- deconvo_tme(
  eset = expr_matrix,
  method = "cibersort",
  arrays = FALSE,           # FALSE=RNA-seq, TRUE=microarray
  perm = 1000              # 置换次数
)
head(cibersort_result)

# 方法2:使用immunedeconv包
# 注意:immunedeconv 不在 CRAN 上,需从 GitHub 安装
# remotes::install_github("omnideconv/immunedeconv")
library(immunedeconv)

# CIBERSORT(需要先在 https://cibersort.stanford.edu 注册获取学术许可,
#   下载 CIBERSORT.R 脚本和 LM22.txt 参考矩阵,然后设置路径:)
# set_cibersort_binary("/path/to/CIBERSORT.R")
# set_cibersort_mat("/path/to/LM22.txt")
# cibersort_res <- deconvolute(expr_matrix, "cibersort")

# CIBERSORT absolute mode
# cibersort_abs <- deconvolute(expr_matrix, "cibersort_abs")

# 方法3:手动实现CIBERSORT(使用e1071包的SVR)
library(e1071)
library(preprocessCore)

# 读取LM22参考矩阵
lm22 <- read.table("LM22.txt", header = TRUE, sep = "\t", row.names = 1)

# 找共有基因
common_genes <- intersect(rownames(expr_matrix), rownames(lm22))
expr_sub <- expr_matrix[common_genes, ]
lm22_sub <- lm22[common_genes, ]

# 分位数归一化
expr_norm <- normalize.quantiles(as.matrix(expr_sub))
rownames(expr_norm) <- common_genes
colnames(expr_norm) <- colnames(expr_sub)

# 对每个样本做SVR反卷积
cibersort_proportions <- matrix(NA, ncol(expr_norm), ncol(lm22_sub))
colnames(cibersort_proportions) <- colnames(lm22_sub)
rownames(cibersort_proportions) <- colnames(expr_norm)

for (i in 1:ncol(expr_norm)) {
  # ν-SVR
  svr_model <- svm(x = as.matrix(lm22_sub), y = expr_norm[, i],
                   type = "nu-regression", kernel = "linear", nu = 0.5)
  coefs <- t(svr_model$coefs) %*% svr_model$SV
  coefs[coefs < 0] <- 0  # 非负约束
  coefs <- coefs / sum(coefs)  # 归一化到和为1
  cibersort_proportions[i, ] <- coefs
}

第三步:xCell分析

白话解释: xCell的思路不同于CIBERSORT——它不做"反卷积",而是用ssGSEA打分法给每种细胞类型打分。但它比单纯的ssGSEA多了一步"补偿"校正,类似于流式细胞仪中的荧光补偿,去掉不同细胞类型之间基因重叠导致的"串色"。

# ===== xCell分析 =====
# 注意:xCell 不在 CRAN 上,需从 GitHub 安装
# devtools::install_github("dviraran/xCell")
# 也可使用升级版 xCell2(已正式收录于Bioconductor):
# BiocManager::install("xCell2")
# 或从GitHub安装开发版:devtools::install_github("AlmogAngel/xCell2")
library(xCell)

# 运行xCell(输入为TPM或归一化后的微阵列数据)
xcell_result <- xCellAnalysis(expr_matrix)
dim(xcell_result)  # 67种细胞/特征 × 样本数

# 查看结果
head(xcell_result[, 1:5])
# 结果包含64种细胞类型 + ImmuneScore + StromaScore + MicroenvironmentScore

# 提取特定细胞类型
immune_cells <- c("B-cells", "CD4+ T-cells", "CD8+ T-cells",
                  "NK cells", "Macrophages M1", "Macrophages M2",
                  "Tregs", "Dendritic cells")
xcell_immune <- xcell_result[immune_cells, ]

# 使用immunedeconv统一接口
xcell_res <- deconvolute(expr_matrix, "xcell")

# 可视化
library(pheatmap)
annotation_col <- data.frame(
  Group = sample_info$Group,
  row.names = colnames(xcell_immune)
)
pheatmap(xcell_immune,
         annotation_col = annotation_col,
         scale = "row",
         clustering_distance_rows = "correlation",
         main = "xCell Immune Infiltration")

第四步:MCP-counter分析

白话解释: MCP-counter最简单直接——对每种细胞类型,找到只在这种细胞中高表达的"特征基因"(transcriptomic markers),然后用这些基因的表达均值代表该细胞的丰度。它不是比例而是"丰度估计",更接近绝对量。

# ===== MCP-counter =====
# 注意:MCPcounter 不在 CRAN 上,需从 GitHub 安装
# devtools::install_github("ebecht/MCPcounter", ref = "master", subdir = "Source")
library(MCPcounter)

# 运行MCP-counter
mcp_result <- MCPcounter.estimate(
  expression = expr_matrix,
  featuresType = "HUGO_symbols",  # 基因名类型
  # 需联网下载;或提前下载到本地后改用本地路径
  genes = read.table(curl("http://raw.githubusercontent.com/ebecht/MCPcounter/master/Signatures/genes.txt"),
                     sep = "\t", stringsAsFactors = FALSE, header = TRUE,
                     colClasses = "character", check.names = FALSE)
)

dim(mcp_result)  # 10种细胞类型 × 样本数
rownames(mcp_result)
# [1] "T cells"          "CD8 T cells"      "Cytotoxic lymphocytes"
# [4] "B lineage"        "NK cells"         "Monocytic lineage"
# [7] "Myeloid dendritic cells" "Neutrophils"  "Endothelial cells"
# [10] "Fibroblasts"

# 或使用immunedeconv
mcp_res <- deconvolute(expr_matrix, "mcp_counter")

# 可视化
library(ggplot2)
library(tidyr)

mcp_long <- as.data.frame(t(mcp_result))
mcp_long$Sample <- rownames(mcp_long)
mcp_long$Group <- sample_info$Group
mcp_long <- pivot_longer(mcp_long, cols = -c(Sample, Group),
                          names_to = "CellType", values_to = "Score")

ggplot(mcp_long, aes(x = CellType, y = Score, fill = Group)) +
  geom_boxplot() +
  coord_flip() +
  theme_classic() +
  labs(title = "MCP-counter Immune Infiltration", y = "MCP-counter Score")

第五步:TIMER/TIMER2.0分析

白话解释: TIMER最初是一个在线平台。TIMER2.0(http://timer.cistrome.org/)整合了6种反卷积方法,目前仍可访问。最新版 TIMER3(https://compbio.cn/timer3/,2025年发表于NAR, Vol.53, W1, W534-W541)进一步整合了15种算法(含人和小鼠),新增了免疫治疗应答预测模块(整合32个免疫治疗RNA-seq数据集)和基因签名分析功能(GO:BP/KEGG/HALLMARK),推荐使用最新版。

# ===== TIMER (R实现) =====
# 使用immunedeconv包
timer_res <- deconvolute(expr_matrix, "timer",
                          indications = rep("brca", ncol(expr_matrix)))
# TIMER需要指定肿瘤类型(indication)

# ===== EPIC =====
# install.packages("remotes")
# remotes::install_github("GfellerLab/EPIC")  # 从GitHub安装,不在CRAN上
library(EPIC)
epic_res <- EPIC(bulk = expr_matrix)
epic_proportions <- epic_res$cellFractions

# ===== quanTIseq =====
quantiseq_res <- deconvolute(expr_matrix, "quantiseq",
                              tumor = TRUE,  # 是否含肿瘤细胞
                              arrays = FALSE)

# ===== 多方法整合比较(immunedeconv一站式) =====
library(immunedeconv)

# 运行所有方法
methods <- c("xcell", "mcp_counter", "epic", "quantiseq")
all_results <- list()
for (method in methods) {
  all_results[[method]] <- deconvolute(expr_matrix, method)
}

# 比较不同方法对同一细胞类型的估计
# 例如CD8 T cells
cd8_comparison <- data.frame(
  xCell = as.numeric(all_results$xcell["CD8+ T-cells", -1]),
  MCP = as.numeric(all_results$mcp_counter["CD8+ T-cells", -1]),
  EPIC = as.numeric(all_results$epic["CD8+ T-cells", -1]),
  quanTIseq = as.numeric(all_results$quantiseq["CD8+ T-cells", -1])
)
# 计算方法间相关性
cor(cd8_comparison, use = "complete.obs", method = "spearman")

第六步:ESTIMATE分析

白话解释: ESTIMATE用一组免疫相关基因和一组基质相关基因做ssGSEA打分,给出三个分数:免疫评分(免疫细胞多少)、基质评分(基质细胞多少)和肿瘤纯度估计。常用于评估肿瘤微环境的整体免疫状态。

# ===== ESTIMATE =====
library(estimate)

# 准备输入文件
write.table(data.frame(Gene = rownames(expr_matrix), expr_matrix),
            "expr_for_estimate.txt", sep = "\t", quote = FALSE, row.names = FALSE)

# 过滤共同基因
filterCommonGenes(input.f = "expr_for_estimate.txt",
                  output.f = "expr_filtered.gct", id = "GeneSymbol")

# 计算ESTIMATE分数
estimateScore(input.ds = "expr_filtered.gct",
              output.ds = "estimate_scores.gct",
              platform = "illumina")

# 读取结果
estimate_scores <- read.table("estimate_scores.gct", skip = 2, header = TRUE, sep = "\t")
rownames(estimate_scores) <- estimate_scores[, 1]
estimate_scores <- estimate_scores[, -c(1, 2)]

# 提取三个分数
stromal_score <- as.numeric(estimate_scores["StromalScore", ])
immune_score <- as.numeric(estimate_scores["ImmuneScore", ])
estimate_total <- as.numeric(estimate_scores["ESTIMATEScore", ])

# 计算肿瘤纯度
tumor_purity <- cos(0.6049872018 + 0.0001467884 * estimate_total)

# 可视化
plot_data <- data.frame(
  ImmuneScore = immune_score,
  StromalScore = stromal_score,
  TumorPurity = tumor_purity,
  Group = sample_info$Group
)

ggplot(plot_data, aes(x = Group, y = ImmuneScore, fill = Group)) +
  geom_boxplot() +
  stat_compare_means() +
  theme_classic() +
  labs(title = "ESTIMATE Immune Score")

第七步:免疫浸润与临床关联分析

白话解释: 估计出免疫浸润后,最有价值的分析是看免疫浸润程度与患者的临床结局(生存时间、治疗反应)有什么关系——高免疫浸润的患者预后是更好还是更差?这对免疫治疗的患者分层有重要意义。

# ===== 生存分析 =====
library(survival)
library(survminer)

# 对每种细胞类型做KM生存分析
cell_types <- rownames(cibersort_proportions_t)  # 转置后行为细胞类型
surv_results <- list()

for (ct in cell_types) {
  scores <- cibersort_proportions[, ct]
  group <- ifelse(scores > median(scores), "High", "Low")

  surv_data <- data.frame(
    time = clinical$OS_time,
    status = clinical$OS_status,
    group = factor(group, levels = c("Low", "High"))
  )

  fit <- survfit(Surv(time, status) ~ group, data = surv_data)
  cox <- coxph(Surv(time, status) ~ group, data = surv_data)
  p <- summary(cox)$coefficients[, "Pr(>|z|)"]
  hr <- exp(coef(cox))

  surv_results[[ct]] <- list(fit = fit, p = p, hr = hr)
}

# 筛选显著的细胞类型
sig_cells <- names(which(sapply(surv_results, function(x) x$p) < 0.05))

# 绘制显著的KM曲线
for (ct in sig_cells) {
  print(ggsurvplot(surv_results[[ct]]$fit,
                   data = data.frame(time = clinical$OS_time,
                                     status = clinical$OS_status),
                   pval = TRUE, risk.table = TRUE,
                   title = ct))
}

# ===== 免疫浸润与免疫治疗反应 =====
# 比较responder vs non-responder的免疫浸润差异
responders <- sample_info$Response == "Responder"
for (ct in colnames(cibersort_proportions)) {
  p <- wilcox.test(cibersort_proportions[responders, ct],
                   cibersort_proportions[!responders, ct])$p.value
  if (p < 0.05) {
    cat(ct, ": P =", p, "\n")
  }
}

# ===== 免疫亚型分类 =====
# 基于免疫浸润模式对肿瘤做分子分型
library(ConsensusClusterPlus)

# 使用多种免疫细胞评分做聚类
immune_matrix <- t(cibersort_proportions)  # 行=细胞类型, 列=样本
results_cc <- ConsensusClusterPlus(
  d = immune_matrix,
  maxK = 6,
  reps = 1000,
  pItem = 0.8,
  pFeature = 1,
  clusterAlg = "km",
  distance = "euclidean",
  seed = 42
)

# 选择最佳K值(通常看CDF和delta area)
# 假设K=3最佳
immune_subtypes <- results_cc[[3]]$consensusClass
sample_info$ImmuneSubtype <- paste0("IS", immune_subtypes)

# 比较免疫亚型的生存差异
fit_subtype <- survfit(Surv(OS_time, OS_status) ~ ImmuneSubtype, data = sample_info)
ggsurvplot(fit_subtype, pval = TRUE, risk.table = TRUE)

第八步:免疫浸润综合可视化

# ===== 综合可视化 =====
library(ggplot2)
library(tidyr)
library(ComplexHeatmap)

# 1. 堆积柱状图(CIBERSORT比例)
cib_long <- as.data.frame(cibersort_proportions)
cib_long$Sample <- rownames(cib_long)
cib_long <- pivot_longer(cib_long, -Sample, names_to = "CellType", values_to = "Proportion")

# 按某细胞排序
sample_order <- rownames(cibersort_proportions)[order(cibersort_proportions[, "T cells CD8"])]
cib_long$Sample <- factor(cib_long$Sample, levels = sample_order)

ggplot(cib_long, aes(x = Sample, y = Proportion, fill = CellType)) +
  geom_bar(stat = "identity") +
  theme_classic() +
  theme(axis.text.x = element_blank(), axis.ticks.x = element_blank()) +
  labs(title = "CIBERSORT Immune Cell Composition")

# 2. 相关性热图(细胞类型间相关性)
cell_cor <- cor(cibersort_proportions, method = "spearman")
pheatmap(cell_cor,
         color = colorRampPalette(c("blue", "white", "red"))(100),
         main = "Cell Type Correlation")

# 3. 小提琴图(分组比较)
library(ggpubr)
for (ct in c("T cells CD8", "Macrophages M2", "T cells regulatory Tregs")) {
  p <- ggviolin(data.frame(score = cibersort_proportions[, ct],
                           group = sample_info$Group),
                x = "group", y = "score", fill = "group",
                add = "boxplot", add.params = list(fill = "white")) +
    stat_compare_means() +
    labs(title = ct, y = "CIBERSORT Proportion")
  print(p)
}

# 4. 棒棒糖图(多方法结果汇总)
# 比较Disease vs Control, 所有方法所有细胞

实战命令(可复制)

完整免疫浸润分析流程

# ============================================
# 免疫浸润综合分析流程
# ============================================

# 1. 环境准备
install.packages(c("ggpubr", "pheatmap", "survival", "survminer"))
# immunedeconv 和 IOBR 需从 GitHub 安装(不在 CRAN/Bioconductor 上)
# install.packages("remotes")  # 如未安装
remotes::install_github("omnideconv/immunedeconv")
remotes::install_github("IOBR/IOBR")
# 注意:使用 CIBERSORT 方法需额外在 https://cibersort.stanford.edu 注册获取许可
library(immunedeconv); library(IOBR); library(ggpubr)
library(pheatmap); library(survival); library(survminer)

# 2. 读取数据(TPM矩阵,行=基因symbol,列=样本)
expr <- as.matrix(read.csv("expr_tpm.csv", row.names = 1))
clinical <- read.csv("clinical_data.csv")

# 3. 多方法免疫浸润分析
# CIBERSORT (通过IOBR)
cib <- deconvo_tme(expr, method = "cibersort", arrays = FALSE, perm = 100)
# xCell
xcell <- xCellAnalysis(expr)
# MCP-counter
mcp <- MCPcounter::MCPcounter.estimate(expr, featuresType = "HUGO_symbols")
# EPIC
epic <- EPIC::EPIC(bulk = expr)$cellFractions
# quanTIseq
quant <- deconvolute(expr, "quantiseq", tumor = TRUE)

# 4. 组间差异分析
group <- clinical$Group
for (ct in colnames(cib)[-c(1:2)]) {
  p <- wilcox.test(cib[group == "Tumor", ct], cib[group == "Normal", ct])$p.value
  if (p < 0.05) cat(ct, "P =", formatC(p, digits = 3), "\n")
}

# 5. 生存分析
for (ct in colnames(cib)[-c(1:2)]) {
  med <- median(cib[, ct])
  grp <- ifelse(cib[, ct] > med, "High", "Low")
  cox <- coxph(Surv(clinical$OS_time, clinical$OS_status) ~ grp)
  p <- summary(cox)$coefficients[, 5]
  if (p < 0.05) cat(ct, ": HR =", round(exp(coef(cox)), 2), ", P =", round(p, 4), "\n")
}

# 6. 可视化输出
pdf("immune_infiltration_results.pdf", width = 12, height = 8)
pheatmap(xcell[c("CD8+ T-cells", "CD4+ T-cells", "B-cells", "NK cells",
                  "Macrophages M1", "Macrophages M2", "Tregs"), ],
         scale = "row", annotation_col = data.frame(Group = group))
dev.off()

面试常问点

Q1: CIBERSORT和MCP-counter的核心区别是什么?

A: (1) 算法:CIBERSORT用ν-SVR反卷积(解方程),MCP-counter用标记基因表达均值(直接读数);(2) 输出:CIBERSORT输出相对比例(和为1),MCP-counter输出绝对丰度(可跨样本比较绝对量);(3) 细胞类型数:CIBERSORT 22种,MCP-counter 10种;(4) 对肿瘤纯度的敏感性:CIBERSORT受肿瘤纯度影响大(纯度高时免疫比例被压缩),MCP-counter相对不受影响;(5) 适用性:CIBERSORT需要参考矩阵,MCP-counter只需要标记基因列表。

Q2: 为什么不同方法的结果可能不一致?如何处理?

A: 不一致原因:(1) 方法原理不同(反卷积 vs 打分);(2) 细胞类型定义不同(如"T cells CD4"定义的基因集不同);(3) 参考数据不同(LM22 vs 自定义signature);(4) 输出含义不同(比例 vs 绝对量 vs 活性分数)。处理策略:报告多种方法结果,以一致性结论为重点。对于关键发现,用至少2-3种方法交叉验证。TIMER3平台(https://compbio.cn/timer3/)整合15种算法,方便做多方法比较。

Q3: CIBERSORT的P值代表什么?如何使用?

A: CIBERSORT对每个样本输出一个P值(通过置换检验),表示该样本的反卷积结果是否可信——P值<0.05说明混合信号确实可以由LM22参考矩阵重建,反卷积结果可信。P>0.05的样本应被排除或谨慎解读(可能含有大量不在参考中的细胞类型)。注意:这个P值不是组间比较的P值。

Q4: 这些方法能检测到哪些免疫细胞的极化状态?

A: CIBERSORT LM22可以区分:M1 vs M2巨噬细胞、naive vs memory vs activated T细胞、resting vs activated NK细胞、resting vs activated mast细胞。xCell更进一步可以区分Th1/Th2。但需注意:极化状态的区分依赖于参考基因集的质量,在体内真实状态可能是连续谱而非离散分类。M1/M2的简单二分法本身就有争议。

Q5: RNA-seq数据做免疫浸润分析前需要什么处理?

A: (1) 需要基因水平的表达矩阵(不是isoform水平);(2) 使用TPM或FPKM(不同方法有不同推荐:CIBERSORT推荐TPM,xCell支持TPM/FPKM);(3) 行名必须是Gene Symbol(不是ENSEMBL ID);(4) 不需要做log变换(大多数方法在内部处理);(5) 不需要做差异分析——免疫浸润分析用完整表达矩阵。

Q6: 如何验证免疫浸润分析结果的准确性?

A: 金标准验证:(1) 免疫组化(IHC)/免疫荧光:标记特定细胞(如CD8、CD68),与计算估计比较;(2) 流式细胞术:对配对样本做流式计数,验证比例一致性;(3) 单细胞RNA-seq:直接数各细胞类型数量。计算验证:(4) 使用已知组成的模拟混合数据测试方法精度;(5) 多方法一致性检验。

Q7: 免疫浸润分析在临床中有什么应用?

A: (1) 免疫治疗预测:高CD8+ T、高PD-L1、高TMB与免疫检查点抑制剂(ICI)反应相关;(2) 预后分层:Immunoscore(CD3+CD8+组合)已用于结直肠癌预后评估;(3) 肿瘤分型:免疫"热"vs"冷"肿瘤分型指导治疗策略;(4) 伴随诊断:指导联合治疗方案选择;(5) 新抗原研究:评估免疫浸润与新抗原负荷的关系。


易错点

1. 使用counts数据而不是TPM/FPKM

问题: 大多数免疫浸润方法需要归一化后的表达值(TPM),直接使用raw counts会导致结果不准。 解决: 确认输入数据类型。CIBERSORT/xCell/MCP-counter推荐使用TPM。如果只有counts,先转换为TPM:TPM = (counts/gene_length) / sum(counts/gene_length) * 10^6。

2. 基因ID不统一

问题: 表达矩阵用ENSEMBL ID或Entrez ID,而方法内部使用Gene Symbol,导致大量基因无法匹配,结果不可靠。 解决: 统一转换为HGNC Gene Symbol。注意一对多映射的处理(取均值或最大值)。检查匹配率应>90%。

3. CIBERSORT结果中P值不显著的样本不过滤

问题: P>0.05的样本反卷积质量差(参考矩阵无法解释其表达),纳入分析会增加噪声。 解决: 对CIBERSORT结果严格按P<0.05过滤。如果大量样本P不显著,可能说明样本中含有参考矩阵未覆盖的细胞类型(如癌细胞占比太高)。

4. 直接比较不同方法的绝对数值

问题: CIBERSORT输出比例0.1,MCP-counter输出分数500,不能说MCP估计的多。 解决: 不同方法的输出尺度和含义不同,不能直接比较数值。只能在同一方法内比较不同样本/组间的差异方向和显著性。

5. 忽略肿瘤纯度的影响

问题: 肿瘤纯度高的样本,免疫细胞相对比例天然被压缩,可能导致高纯度肿瘤的免疫浸润被低估。 解决: 分析时考虑纯度作为混杂变量(在回归中加入ESTIMATE纯度分数),或使用CIBERSORTx的absolute mode,或使用不受纯度影响的方法(如MCP-counter)。


补充知识

方法选择指南

你需要什么:
├── 22种免疫细胞详细比例 → CIBERSORT
├── 64种细胞类型全面覆盖 → xCell
├── 快速简单的绝对丰度估计 → MCP-counter
├── 统计严格的比例估计 → quanTIseq / EPIC
├── 肿瘤纯度和整体免疫状态 → ESTIMATE
├── 多方法比较 → TIMER3 在线平台(15种算法)
└── 自定义细胞标记 → ssGSEA / GSVA

在线分析平台

  • TIMER3: https://compbio.cn/timer3/ (2025年最新版,整合15种算法,含免疫治疗模块)
  • TIMER2.0: http://timer.cistrome.org/ (仍可访问,整合6种方法)
  • CIBERSORTx: https://cibersortx.stanford.edu/ (需注册获取学术许可;支持网页版和Docker本地运行,无官方R包)
  • GEPIA2: http://gepia2.cancer-pku.cn/ (TCGA数据分析,仍在运行)
  • ImmuCellAI: https://guolab.wchscu.cn/ImmuCellAI/ (免疫细胞丰度推断,24种免疫细胞含18种T细胞亚群;旧地址 http://bioinfo.life.hust.edu.cn/ImmuCellAI/ 可能已迁移)

免疫浸润相关生物标志物

标志物来源临床应用
ImmunoscoreCD3/CD8 IHC结直肠癌预后
TMBWES/PanelICI疗效预测
PD-L1IHCICI适应症选择
MSI-HPCR/IHCICI适应症
TILsH&E评估乳腺癌预后
TIDE score计算模型ICI反应预测