单细胞学习(13)—— Seurat → Scanpy 分析流程
下面是一份从 Seurat 分析流程转到Scanpy 分析流程的简要笔记,涵盖了从数据读入到细胞注释的主要环节,并附上常用函数的Seurat vs. Scanpy 对照表。该笔记既可作为工作流程指南,也能在两个分析平台之间快速切换和比较。
Seurat → Scanpy 分析流程笔记
1. 数据读入
Seurat 中的数据读入(回顾)
-
常规 10x 数据:
library(Seurat) seurat_obj <- Read10X("filtered_feature_bc_matrix/") seurat_obj <- CreateSeuratObject(counts = seurat_obj, project = "scRNA")
-
RDS 文件读入:
seurat_obj <- readRDS("seurat_obj.rds")
Scanpy 中的数据读入
- 读入 10x 过滤矩阵(推荐)
import scanpy as sc adata = sc.read_10x_mtx( "filtered_feature_bc_matrix", var_names='gene_symbols', cache=True )
- 如果有 H5 文件(如
filtered_feature_bc_matrix.h5
):adata = sc.read_10x_h5("filtered_feature_bc_matrix.h5")
- 若是从 Seurat 对象(.Rds)转换,推荐 SeuratDisk 将其转为 H5AD 后再读入:
# R 端: library(SeuratDisk) SaveH5Seurat(seurat_obj, filename="seurat.h5Seurat") Convert("seurat.h5Seurat", dest="h5ad", overwrite=TRUE)
# Python 端: import scanpy as sc adata = sc.read_h5ad("seurat.h5ad")
2. 数据预处理 / 质控(QC)
在 Scanpy 中,你可以类似 Seurat 那样进行 QC 过滤。
Seurat 中的常规 QC
seurat_obj <- subset(seurat_obj, subset = nFeature_RNA > 200 & nFeature_RNA < 6000 & percent.mt < 10)
Scanpy 中的常规 QC
# 过滤低基因表达细胞
sc.pp.filter_cells(adata, min_genes=200)
# 过滤低表达基因
sc.pp.filter_genes(adata, min_cells=3)
# (可选)对于线粒体基因的过滤:
# 1. 计算线粒体基因比例
adata.var['mt'] = adata.var_names.str.startswith('MT-')
adata.obs['percent_mt'] = (
np.sum(
adata[:, adata.var['mt']].X, axis=1
)
/ np.sum(adata.X, axis=1)
) * 100
# 2. 根据线粒体基因比例进行过滤
adata = adata[adata.obs['percent_mt'] < 10, :]
3. 归一化与高变基因选择
Seurat
# 归一化
seurat_obj <- NormalizeData(seurat_obj)
# 查找高变基因
seurat_obj <- FindVariableFeatures(seurat_obj, selection.method="vst", nfeatures=2000)
Scanpy
# Total-count normalize (与 Seurat 的 NormalizeData 相似)
sc.pp.normalize_total(adata, target_sum=1e4)
# 取 log
sc.pp.log1p(adata)
# 查找高变基因(与 Seurat 策略相似)
sc.pp.highly_variable_genes(
adata,
flavor='seurat', # 使用Seurat VST算法
n_top_genes=2000
)
# 过滤数据,仅保留高变基因
adata = adata[:, adata.var['highly_variable']]
4. 降维与聚类
Seurat
# PCA
seurat_obj <- RunPCA(seurat_obj, npcs=50)
# 邻接图/邻居查找
seurat_obj <- FindNeighbors(seurat_obj, dims=1:30)
# 聚类
seurat_obj <- FindClusters(seurat_obj, resolution=0.5)
# UMAP
seurat_obj <- RunUMAP(seurat_obj, dims=1:30)
Scanpy
# PCA
sc.pp.pca(adata, n_comps=50)
# 邻接图
sc.pp.neighbors(adata, n_neighbors=10, n_pcs=30)
# 聚类(Leiden 算法)
sc.tl.leiden(adata, resolution=0.5)
# UMAP
sc.tl.umap(adata)
注: Seurat 使用 Louvain / SLM 聚类,Scanpy 中
sc.tl.leiden
是一种改进版的社区检测算法,效果与 Seurat 类似或更佳。
5. 不同分辨率下的聚类遍历
Seurat 可以直接传递一个 resolution.range
,如:
resolution.range <- c(0.1, 0.2, 0.3, 0.5)
FindClusters(seurat_obj, resolution = resolution.range)
Scanpy 中要手动遍历:
resolutions = [0.1, 0.2, 0.3, 0.5]
for res in resolutions:
sc.tl.leiden(adata, resolution=res, key_added=f'leiden_{res}')
sc.pl.umap(adata, color=f'leiden_{res}')
若要保存多个分辨率结果的 UMAP 图到同一个 PDF,可参考:
from matplotlib.backends.backend_pdf import PdfPages
pdf_path = "UMAP_by_resolution.pdf"
with PdfPages(pdf_path) as pdf:
for res in resolutions:
sc.tl.leiden(adata, resolution=res, key_added=f'leiden_{res}')
fig = sc.pl.umap(adata, color=f'leiden_{res}', show=False, return_fig=True)
pdf.savefig(fig)
plt.close(fig)
6. 差异基因分析与可视化
Seurat
# FindAllMarkers
markers <- FindAllMarkers(seurat_obj, test.use="wilcox")
可视化:
FeaturePlot(seurat_obj, features="CD3E", cols=c("gray", "red"))
DotPlot(seurat_obj, features=c("CD3E", "NKG7"), group.by="seurat_clusters")
Scanpy
# 差异基因分析
sc.tl.rank_genes_groups(adata, groupby="leiden", method="wilcoxon")
# 查看结果
sc.pl.rank_genes_groups(adata, n_genes=5, sharey=False)
可视化 Marker 基因:
# UMAP feature plot(类似 Seurat FeaturePlot)
sc.pl.umap(adata, color=["CD3E"], cmap="Reds")
# DotPlot(类似 Seurat DotPlot)
marker_genes = ["CD3E","NKG7","CD68","KRT19"]
sc.pl.dotplot(adata, var_names=marker_genes, groupby="leiden", cmap="Reds")
7. 细胞注释
在 Seurat 中,一般通过 Idents
或 AddMetaData
给细胞添加类型标签;在 Scanpy 中,你可以修改 adata.obs
列添加注释:
# 假设你对各群集根据 Marker 基因进行了人工判定
celltype_dict = {
"0": "Epithelial",
"1": "T Cells",
"2": "NK Cells",
# ...
}
# 假设分辨率=0.5时存储在 leiden_0.5
adata.obs["celltype"] = adata.obs["leiden_0.5"].map(celltype_dict)
# 再次绘制UMAP,颜色按 celltype
sc.pl.umap(adata, color="celltype")
Seurat vs. Scanpy 主要函数对照表
分析步骤 | Seurat ® | Scanpy (Python) |
---|---|---|
数据读入 | Read10X() / CreateSeuratObject() | sc.read_10x_mtx() / sc.read_10x_h5() |
质控 (QC) | subset() | sc.pp.filter_cells() / sc.pp.filter_genes() |
线粒体基因过滤 | PercentageFeatureSet(... pattern = "^MT-") | 手动提取后过滤 (见 adata.obs['percent_mt'] ) |
归一化 | NormalizeData() | sc.pp.normalize_total() + sc.pp.log1p() |
高变基因 | FindVariableFeatures() | sc.pp.highly_variable_genes() |
PCA | RunPCA() | sc.pp.pca() |
邻居查找 | FindNeighbors() | sc.pp.neighbors() |
聚类 | FindClusters() | sc.tl.leiden() |
UMAP/t-SNE | RunUMAP() / RunTSNE() | sc.tl.umap() / sc.tl.tsne() |
差异基因 | FindAllMarkers() / FindMarkers() | sc.tl.rank_genes_groups() |
FeaturePlot | FeaturePlot() | sc.pl.umap(..., color='GENE') |
DotPlot | DotPlot() | sc.pl.dotplot() |
细胞类型注释 | Idents() / AddMetaData() | adata.obs['celltype'] = ... |
保存对象 | saveRDS() | adata.write("xxx.h5ad") |
8. 小结
- 数据读入:如果是 10x 的过滤矩阵,Seurat 用
Read10X()
,Scanpy 用sc.read_10x_mtx()
/sc.read_10x_h5()
;若已在 Seurat 中整合好,可先用 SeuratDisk 转换为.h5ad
。 - 质控与预处理:二者均可进行基于基因数、细胞数、线粒体基因比例等过滤。Scanpy 常需手动计算线粒体比例。
- 高变基因、PCA、聚类、UMAP 等流程在 Scanpy 中与 Seurat 非常相似,只是函数名称与参数略有不同。
- 差异基因分析:Seurat 中常用
FindAllMarkers()
,Scanpy 中则是sc.tl.rank_genes_groups()
. - 可视化:Seurat 提供
FeaturePlot()
、DotPlot()
等函数;Scanpy 对应sc.pl.umap(...)
和sc.pl.dotplot()
。 - 细胞注释:在 Scanpy 中,直接修改
adata.obs["celltype"]
,并用sc.pl.umap(color="celltype")
可视化。
总体而言,Seurat 与 Scanpy 在单细胞分析思路上高度相似,只是实现细节、函数名和可视化风格略有区别。若你已有完备的 Seurat 分析经验,迁移到 Scanpy 通常是逻辑和函数名的平移,很快能上手。
参考命令与提示
- 如果有大规模数据(>10 万细胞),Scanpy 的处理速度与内存占用通常较 Seurat 更有优势。
- 若仍需 Seurat 强大的可视化与整合包(如
SeuratWrappers
),可在小规模数据或特定分析环节中继续使用 R + Seurat。 - 混合使用:在 R 中做部分分析后,将结果(如细胞注释)输出为
.csv
,或使用SeuratDisk
生成.h5ad
以在 Python 端进一步扩展(如scanpy
,squidpy
,cellchat
Python 版等)。
以上为 Seurat → Scanpy 的主要流程笔记,涵盖从数据读入、质量控制、归一化、高变基因选择、聚类及可视化、差异基因分析、到细胞注释的完整思路。