377_单细胞批量注释自动化
一句话说明
自动注释就是用已知的参考图谱或机器学习模型,自动判断"每个细胞是什么类型",省去手动查marker基因的大量时间。
核心知识点
要点1:手动注释 vs 自动注释
- 手动注释:UMAP上看cluster→查文献marker基因→人工判断细胞类型
- 优点:专家经验,可信度高
- 缺点:耗时,主观性强,难以处理几十个cluster
- 自动注释:用参考数据集训练的分类器预测细胞类型
- 优点:快速、可重现、可扩展
- 缺点:参考数据集不匹配时准确率下降
要点2:主流自动注释工具
| 工具 | 方法 | 参考来源 | 特点 |
|---|
| SingleR | 相关性打分 | 体外、内置数据库 | 不需要训练,快速 |
| sctype | 标记基因打分 | 自定义标记基因表 | 无需参考数据集 |
| Azimuth | 监督学习 | 人类参考图谱 | 适合人类常见组织 |
| CellTypist | 逻辑回归 | 可训练自定义 | 速度快,模型丰富 |
| scANVI | 深度学习VAE | scRNA-seq参考 | 与批次校正结合 |
要点3:SingleR 工作原理
- 对每个测试细胞,与参考数据集中所有细胞做相关性计算
- 找到最相似的参考细胞,取其细胞类型标签
- 经过多轮"精细调优"(fine-tuning)消除歧义
- 输出置信度分数(score),score高=注释可信
要点4:scType 工作原理(轻量级)
- 不需要参考数据集,只需要marker基因表(Excel即可)
- 计算每个cluster中marker基因的加权表达分数
- 选分数最高的细胞类型作为注释
- 适合有自己领域marker基因知识的研究者
要点5:注释质量控制
- 置信度阈值:低置信度(如SingleR的
pruned.labels 为NA)的细胞标记为"未定义" - 与手动核对:对自动注释结果,用已知marker基因做交叉验证
- Marker基因验证:
DotPlot 或 FeaturePlot 展示各类型的marker表达
实战代码
SingleR 自动注释
library(SingleR) # 自动细胞类型注释
library(Seurat) # 单细胞分析
library(celldex) # 内置参考数据集
# ============================================================
# 方法A:使用内置参考数据集(免下载,适合快速注释)
# ============================================================
# 加载 HumanPrimaryCellAtlasData(人类原代细胞图谱)
ref_hpca <- HumanPrimaryCellAtlasData() # 自动下载参考数据
# 其他可选参考:
# ref_blueprint <- BlueprintEncodeData() # BLUEPRINT免疫细胞
# ref_monaco <- MonacoImmuneData() # 免疫细胞精细分类
# 提取测试数据的表达矩阵(使用log-normalized counts)
test_matrix <- GetAssayData(seurat_obj, layer = "data") # Seurat v5用layer
# 运行 SingleR 注释
singler_results <- SingleR(
test = test_matrix, # 测试数据矩阵(基因×细胞)
ref = ref_hpca, # 参考数据集
labels = ref_hpca$label.main, # 使用粗粒度标签(也可用label.fine精细标签)
num.threads = 4 # 4线程加速
)
# 查看注释结果统计
table(singler_results$labels)
# 将注释结果整合回 Seurat 对象
seurat_obj$SingleR_labels <- singler_results$labels
seurat_obj$SingleR_scores <- apply(singler_results$scores, 1, max) # 最高置信度得分
# 过滤低置信度注释(pruned.labels为NA表示注释不可靠)
seurat_obj$SingleR_pruned <- singler_results$pruned.labels
# 可视化注释结果
DimPlot(
seurat_obj,
group.by = "SingleR_labels", # 按SingleR标签着色
reduction = "umap",
label = TRUE,
repel = TRUE,
pt.size = 0.5
) + ggtitle("SingleR 自动注释结果")
# ============================================================
# 方法B:scType(只需marker基因表,无需参考数据集)
# ============================================================
# 安装 sctype(GitHub包)
if (!require("sctype")) devtools::install_github("IanevskiAleksandr/sc-type/R")
source("https://raw.githubusercontent.com/IanevskiAleksandr/sc-type/master/R/sctype_score_.R")
# 下载内置marker数据库(也可自定义)
db_url <- "https://raw.githubusercontent.com/IanevskiAleksandr/sc-type/master/ScTypeDB_full.xlsx"
download.file(db_url, "ScTypeDB_full.xlsx", quiet = TRUE)
# 加载marker基因(选择组织类型)
library(openxlsx)
gs_list <- gene_sets_prepare("ScTypeDB_full.xlsx",
tissue_type = "Immune system") # 选择组织类型
# 计算每个细胞对各类型的得分
es.max <- sctype_score(
scRNAseqData = seurat_obj[["RNA"]]@scale.data, # 使用scaled data
scaled = TRUE,
gs = gs_list$gs_positive, # 正向marker基因
gs2 = gs_list$gs_negative # 负向marker基因
)
# 按cluster汇总得分,选最高得分的细胞类型
cL_results <- do.call("rbind", lapply(unique(seurat_obj@meta.data$seurat_clusters), function(cl) {
es.max.cl <- sort(rowSums(es.max[, rownames(seurat_obj@meta.data[seurat_obj@meta.data$seurat_clusters == cl, ])]),
decreasing = TRUE)
data.frame(cluster = cl, type = names(es.max.cl[1]),
scores = es.max.cl[1], ncells = sum(seurat_obj@meta.data$seurat_clusters == cl))
}))
# 添加到 Seurat 对象
seurat_obj@meta.data$customclassif <- ""
for (j in unique(cL_results$cluster)) {
cl_type <- cL_results[cL_results$cluster == j, ]
seurat_obj@meta.data$customclassif[seurat_obj@meta.data$seurat_clusters == j] <- cl_type$type[1]
}
CellTypist 自动注释(Python)
import celltypist # 轻量级自动注释工具
import scanpy as sc
# 加载预处理好的 AnnData
adata = sc.read_h5ad("preprocessed.h5ad")
# 下载预训练模型(人类免疫细胞)
celltypist.models.download_models(
model="Immune_All_Low.pkl", # 低粒度免疫细胞模型
force_update=False # 已下载则不重复下载
)
# 自动注释(over_clustering=True:先细粒度聚类再注释)
predictions = celltypist.annotate(
adata,
model="Immune_All_Low.pkl", # 指定模型
majority_voting=True, # 对每个cluster投票取多数标签
over_clustering="leiden" # 使用已有的leiden聚类结果
)
# 整合注释结果
adata = predictions.to_adata() # 将预测结果写回 adata
print(adata.obs["majority_voting"].value_counts()) # 查看各类型细胞数
# 可视化
sc.pl.umap(adata, color="majority_voting",
legend_loc="on data", # 标签显示在图上
title="CellTypist 自动注释",
save="_celltypist.pdf")
面试常问点
- SingleR和CellTypist哪个更准? 取决于参考数据集;SingleR用相关性更保守,CellTypist用逻辑回归对大规模数据更快
- 自动注释结果如何验证? 用
DotPlot 检查各细胞类型的已知marker基因表达是否符合预期 - 遇到低置信度细胞怎么办? SingleR的
pruned.labels 为NA的细胞标为"Unknown",可能是稀有细胞类型或双细胞
速查表
| 场景 | 推荐工具 | 优势 |
|---|
| 快速初步注释 | SingleR | 无需训练,内置参考 |
| 只有marker基因表 | scType | 无需参考数据集 |
| 人类免疫细胞 | Azimuth/CellTypist | 专门优化 |
| 与批次校正整合 | scANVI | 深度学习,同时解决两个问题 |