从PBMC数据实战出发:手把手教你用Scanpy完成细胞类型注释全流程(含Marker基因字典与聚类验证)
从PBMC数据实战出发:手把手教你用Scanpy完成细胞类型注释全流程
第一次接触单细胞转录组数据时,看着UMAP图上那些彩色的点簇,最让人困惑的莫过于——这些数字编号的聚类究竟对应什么细胞类型?去年我刚接手一个PBMC(外周血单个核细胞)项目时,就曾为这个问题辗转反侧。直到系统掌握了Scanpy的注释方法论,才发现原来从聚类到注释有一套标准化的"解题思路"。本文将用68K PBMC精简数据集,带你完整走通从原始数据到生物学解释的全流程。
1. 环境准备与数据加载
工欲善其事,必先利其器。我们先配置好分析环境并理解数据的基本结构:
import scanpy as sc import pandas as pd from matplotlib.pyplot import rc_context # 设置全局参数 sc.set_figure_params(dpi=100, color_map='viridis_r') sc.settings.verbosity = 3 # 显示详细日志加载Scanpy内置的PBMC精简数据集(含约700个细胞)。这个预处理好的数据集特别适合教学演示:
pbmc = sc.datasets.pbmc68k_reduced() print(pbmc)你会看到类似这样的输出:
AnnData object with n_obs × n_vars = 700 × 765 obs: 'bulk_labels', 'n_genes', 'percent_mito', 'n_counts', 'S_score', 'G2M_score', 'phase', 'louvain', 'clusters' var: 'n_cells', 'highly_variable', 'means', 'dispersions', 'dispersions_norm' uns: 'bulk_labels_colors', 'clusters_colors', 'louvain', 'louvain_colors', 'neighbors', 'pca', 'rank_genes_groups' obsm: 'X_pca', 'X_umap' varm: 'PCs'关键数据结构说明:
obs:细胞级注释(如聚类结果)var:基因级注释(如高变基因标记)obsm:细胞维度矩阵(如PCA/UMAP坐标)uns:非结构化数据(如配色方案)
提示:实际项目中,原始数据需先经过质控、归一化、高变基因筛选等预处理步骤。本文使用预处理数据是为了聚焦注释环节。
2. 细胞聚类与可视化
注释的前提是获得可靠的细胞聚类。Scanpy支持多种聚类算法,我们对比最常用的两种:
2.1 Leiden聚类实战
sc.tl.leiden(pbmc, key_added='leiden_clusters', resolution=0.5)参数解析:
resolution:控制聚类粒度(值越大簇越多)key_added:指定结果存储字段名
2.2 Louvain聚类对比
sc.tl.louvain(pbmc, key_added='louvain_clusters', resolution=0.5)可视化对比两种聚类结果:
with rc_context({'figure.figsize': (10, 4)}): fig, (ax1, ax2) = plt.subplots(1, 2) sc.pl.umap(pbmc, color='leiden_clusters', ax=ax1, title='Leiden', show=False) sc.pl.umap(pbmc, color='louvain_clusters', ax=ax2, title='Louvain', show=False)常见问题解答:
| 问题 | 解决方案 |
|---|---|
| 聚类数量不合适 | 调整resolution参数(0.1-2.0尝试) |
| 可视化重叠严重 | 尝试sc.tl.umap时调整min_dist和spread |
| 计算速度慢 | 预处理时适当减少高变基因数量 |
3. Marker基因词典构建策略
注释的核心是建立聚类与已知细胞类型的映射关系,这依赖于准确的marker基因词典。以下是构建专业词典的方法论:
3.1 权威数据源参考
推荐结合多个数据库交叉验证:
- CellMarker 2.0:涵盖人类和小鼠的157,581个marker
- PanglaoDB:包含单细胞验证的marker
- 文献报道:关注最新单细胞研究中的特异marker
3.2 PBMC典型marker词典
基于文献整理的PBMC常见marker参考:
marker_genes_dict = { 'CD4 T细胞': ['CD3D', 'CD3E', 'CD4'], 'CD8 T细胞': ['CD3D', 'CD3E', 'CD8A'], 'B细胞': ['CD79A', 'MS4A1', 'CD19'], 'NK细胞': ['GNLY', 'NKG7', 'CD56'], '单核细胞': ['CD14', 'LYZ', 'FCGR3A'], '树突状细胞': ['FCER1A', 'CST3', 'CLEC9A'], '血小板': ['PPBP', 'PF4'], '造血干细胞': ['CD34', 'PROM1'] }3.3 词典优化技巧
- 特异性检验:用
sc.pl.dotplot验证基因是否确实在目标簇高表达 - 冗余处理:移除在多个类型中表达的基因(如线粒体基因)
- 动态补充:通过差异表达分析发现新的候选marker
4. 多维度验证聚类质量
注释前必须确认聚类结果的生物学合理性。以下是三种核心验证方法:
4.1 Dotplot交叉验证
sc.pl.dotplot( pbmc, marker_genes_dict, groupby='leiden_clusters', dendrogram=True, standard_scale='var', # 按基因标准化 swap_axes=True, # 转置矩阵 figsize=(8, 4) )解读要点:
- 点大小:表达该基因的细胞比例
- 点颜色:标准化后的平均表达量
- 树状图:显示簇间相似性
4.2 差异表达基因验证
通过差异分析验证注释合理性:
# 使用Wilcoxon检验找各簇差异基因 sc.tl.rank_genes_groups( pbmc, groupby='leiden_clusters', method='wilcoxon', pts=True # 计算表达比例 ) # 可视化前5差异基因 sc.pl.rank_genes_groups_dotplot( pbmc, n_genes=5, values_to_plot='logfoldchanges', cmap='bwr', vmin=-4, vmax=4 )4.3 整合可视化技术
组合多种图形进行立体验证:
fig = plt.figure(figsize=(15, 5)) gs = fig.add_gridspec(1, 3) # UMAP展示空间分布 ax1 = fig.add_subplot(gs[0, 0]) sc.pl.umap(pbmc, color='leiden_clusters', ax=ax1, show=False, title='Clusters') # 小提琴图展示关键marker ax2 = fig.add_subplot(gs[0, 1]) sc.pl.violin(pbmc, ['CD3D', 'CD79A'], groupby='leiden_clusters', ax=ax2, show=False) # 热图展示表达模式 ax3 = fig.add_subplot(gs[0, 2]) sc.pl.heatmap(pbmc, marker_genes_dict, groupby='leiden_clusters', ax=ax3, show=False)5. 细胞类型注释实战
通过前述验证后,即可建立聚类编号到细胞类型的映射:
5.1 手动注释流程
# 建立映射字典 cluster2celltype = { '0': 'CD4 T细胞', '1': 'CD8 T细胞', '2': 'B细胞', '3': 'NK细胞', '4': '单核细胞', '5': '树突状细胞' } # 添加到obs中 pbmc.obs['cell_type'] = pbmc.obs['leiden_clusters'].map(cluster2celltype).astype('category') # 可视化结果 sc.pl.umap( pbmc, color='cell_type', legend_loc='on data', legend_fontsize=8, frameon=False, title='Annotated Cell Types' )5.2 半自动注释工具
对于大型数据集,推荐使用自动化工具辅助:
- SingleR:基于参考数据集自动注释
- CellAssign:利用细胞类型标记概率模型
- SCINA:基于已知marker的自动注释
Scanpy整合SingleR的示例:
# 需要先安装SingleR import anndata2ri import rpy2.robjects as ro from rpy2.robjects.packages import importr anndata2ri.activate() singleR = importr('SingleR') # 使用HumanPrimaryCellAtlasData作为参考 hpca = ro.r('HumanPrimaryCellAtlasData::HumanPrimaryCellAtlasData()') singler_results = singleR.SingleR( ro.r('as.SingleCellExperiment')(pbmc), ref=hpca, labels=hpca.rx2('label.main') ) # 将结果添加回AnnData pbmc.obs['singler_labels'] = ro.conversion.rpy2py(singler_results.rx2('labels'))5.3 注释质量评估
完成注释后需检查:
- 内部一致性:同一类型细胞是否聚集在一起
- 标记特异性:marker基因是否在对应类型特异表达
- 生物学合理性:各类型比例是否符合组织特性(如PBMC中T细胞应占60-80%)
评估代码示例:
# 计算各类型占比 celltype_counts = pbmc.obs['cell_type'].value_counts(normalize=True) print(celltype_counts) # 可视化关键marker表达 sc.pl.stacked_violin( pbmc, marker_genes_dict, groupby='cell_type', swap_axes=True, figsize=(8, 6) )6. 进阶技巧与问题排查
在实际项目中,你可能会遇到这些典型情况:
6.1 混合细胞簇处理
当某个簇同时表达多种细胞类型的marker时:
- 检查是否聚类分辨率过低(尝试提高resolution)
- 考虑是否存在双细胞(检查
sc.pp.scrublet) - 可能是过渡状态细胞(需拟时序分析)
6.2 未知细胞簇应对
对无法明确注释的簇:
- 进行通路富集分析(如
sc.tl.gsea) - 比对更多数据库(如CellPhoneDB)
- 暂时标记为"Unknown"继续观察
6.3 批次效应识别
当注释结果与预期严重不符时:
- 检查
pbmc.obs中是否有批次变量 - 运行
sc.pl.umap(pbmc, color='batch')可视化 - 考虑使用
sc.external.pp.bbknn进行批次校正
# 批次效应检测示例 if 'batch' in pbmc.obs: sc.pl.umap( pbmc, color=['cell_type', 'batch'], frameon=False, wspace=0.5 )7. 完整流程封装与复现
为方便复现,以下是整合所有关键步骤的函数:
def annotate_pbmc(adata, resolution=0.5): """PBMC注释全流程封装""" # 聚类 sc.tl.leiden(adata, resolution=resolution, key_added='clusters') # 差异分析 sc.tl.rank_genes_groups(adata, 'clusters', method='wilcoxon') # 注释 markers = { 'T细胞': ['CD3D', 'CD3E'], 'B细胞': ['CD79A', 'MS4A1'], 'NK细胞': ['GNLY', 'NKG7'], '单核细胞': ['CD14', 'LYZ'], '树突细胞': ['FCER1A', 'CST3'] } # 可视化验证 sc.pl.dotplot(adata, markers, 'clusters', dendrogram=True) # 手动映射 adata.obs['cell_type'] = adata.obs['clusters'].map({ '0': 'T细胞', '1': 'B细胞', '2': 'NK细胞', '3': '单核细胞', '4': '树突细胞' }) return adata使用方式:
pbmc = annotate_pbmc(pbmc) sc.pl.umap(pbmc, color='cell_type')