做单细胞转录组分析,两大主流框架你必须知道:Scanpy(Python) 和 Seurat(R)。到底选哪个?这篇帮你做一份全面的深度对比。
核心对比
| 维度 | Scanpy (Python) | Seurat (R) |
|---|---|---|
| 语言 | Python | R |
| 生态 | PyPI, scverse | Bioconductor, CRAN |
| 大数据 | AnnData + zarr 支持百万级 | Seurat v5 支持 on-disk |
| 可视化 | matplotlib,灵活但需调参 | ggplot2 风格,出版级 |
| 学习曲线 | 中等(需 Python 基础) | 中等(需 R 基础) |
| 社区 | 增长快,深度学习整合好 | 更成熟,教程更多 |
| 速度 | 原生高性能,稀疏矩阵优化 | Seurat v5 大幅提升 |
| 扩展性 | scverse 生态系统 | 丰富的插件生态 |
代码对比:同一任务的两种写法
数据读取
# Scanpy
import scanpy as sc
adata = sc.read_10x_h5('filtered_feature_bc_matrix.h5')
# Seurat
data <- Read10X(data.dir = "filtered_feature_bc_matrix/")
obj <- CreateSeuratObject(counts = data)
QC 过滤
# Scanpy
adata.var['mt'] = adata.var_names.str.startswith('MT-')
sc.pp.calculate_qc_metrics(adata, qc_vars=['mt'], inplace=True)
adata = adata[adata.obs['pct_counts_mt'] < 10, :]
adata = adata[
(adata.obs['n_genes_by_counts'] > 200) &
(adata.obs['n_genes_by_counts'] < 6000),
:
].copy()
# Seurat
obj[["percent.mt"]] <- PercentageFeatureSet(obj, "^MT-")
obj <- subset(obj, nFeature_RNA > 200 &
nFeature_RNA < 6000 &
percent.mt < 10)
标准化 + 降维
# Scanpy
sc.pp.normalize_total(adata, target_sum=1e4)
sc.pp.log1p(adata)
sc.pp.highly_variable_genes(adata, n_top_genes=2000)
adata = adata[:, adata.var['highly_variable']].copy()
sc.pp.scale(adata)
sc.tl.pca(adata)
sc.pp.neighbors(adata, n_pcs=30)
sc.tl.umap(adata)
sc.tl.leiden(adata, resolution=0.8)
# Seurat
obj <- SCTransform(obj)
obj <- RunPCA(obj)
obj <- FindNeighbors(obj, dims = 1:30)
obj <- RunUMAP(obj, dims = 1:30)
obj <- FindClusters(obj, resolution = 0.8)
差异表达分析
# Scanpy
sc.tl.rank_genes_groups(
adata,
groupby='leiden',
groups=['1'],
reference='2',
method='wilcoxon'
)
result = sc.get.rank_genes_groups_df(adata, group='1')
# Seurat
markers <- FindMarkers(obj, ident.1 = 1, ident.2 = 2,
min.pct = 0.25, logfc.threshold = 0.25)
富集分析
# Scanpy(配合 gseapy)
import gseapy as gp
enr = gp.enrichr(gene_list=up_genes,
gene_sets='GO_Biological_Process_2023',
organism='Human')
# Seurat(配合 clusterProfiler)
library(clusterProfiler)
ego <- enrichGO(gene = up_genes, OrgDb = org.Hs.eg.db,
keyType = "SYMBOL", ont = "BP")
可视化
# Scanpy:UMAP 图
sc.pl.umap(adata, color='cell_type', legend_loc='on data')
# Seurat:UMAP 图
DimPlot(obj, reduction = "umap", label = TRUE, repel = TRUE)
内存与性能对比
在处理大规模数据时,两者的差异更明显:
| 数据规模 | Scanpy | Seurat v5 |
|---|---|---|
| < 5 万细胞 | 差不多 | 差不多 |
| 5-50 万细胞 | Scanpy 更快 | 需要 on-disk 模式 |
| > 50 万细胞 | Scanpy + zarr 优势明显 | 系统资源要求高 |
# Scanpy 处理大数据:使用 zarr 后端(支持磁盘存储)
adata = sc.read_10x_h5("large_data.h5")
adata = adata[adata.obs['pct_counts_mt'] < 5, :] # 先粗过滤减少内存
# 使用 backed mode 只读模式
adata = sc.read_h5ad('large_data.h5ad', backed='r')
生态系统对比
Scanpy(scverse 生态)
scanpy → 核心分析框架
scvi-tools → 深度学习单细胞分析(scVI, scANVI)
cellrank → RNA velocity + 轨迹推断
mudata → 多模态数据管理
celltypist → AI 细胞注释
squidpy → 空间转录组分析
Seurat 生态
Seurat → 核心分析框架
SingleR → 细胞注释
Monocle3 → 拟时序分析
CellChat → 细胞通讯分析
Harmony → 批次效应校正
SCENIC → 转录因子调控
clusterProfiler → 富集分析(R 生态最强)
什么时候选 Scanpy?
-
你更熟悉 Python,团队有 Python 开发经验
-
数据量特别大(百万级细胞),需要高效的内存管理
-
需要和深度学习工具整合(scVI、scANVI、CellRank 等)
-
需要自定义复杂的分析流程,Python 生态更灵活
-
做空间转录组分析,Squidpy 生态更完善
什么时候选 Seurat?
-
你或团队已经熟悉 R 语言
-
需要用到丰富的 R 生态包(如 clusterProfiler 做富集分析,比 Python 方案更成熟)
-
论文需要复现已发表的分析流程(很多论文用 Seurat)
-
分析流程相对标准化,Seurat 的"一键式"API 更高效
我的建议
如果从零开始学单细胞分析,两个都值得学。 但考虑到当前趋势:
-
Python 的上升势头更猛------scverse 生态发展迅速,深度学习整合是未来方向
-
Seurat 的资源更丰富------教程多、论文代码多,遇到问题更容易找到答案
-
核心分析逻辑是相通的------QC→标准化→降维→聚类→注释,掌握一个后切换另一个并不难
如果你只学一个,先学 Scanpy。 理由:
-
Python 作为通用编程语言,用途远不止生信分析
-
scverse 生态的成长速度已经超过 Seurat
-
大数据和深度学习是未来趋势,Python 在这方面有明显优势
不论你选择哪个框架,如果你需要专业的分析服务,Run2AI 运智 同时支持 Scanpy(Python)和 Seurat(R)两种技术栈,帮你用最趁手的工具完成分析。