第一章:Scanpy简介——单细胞分析的Python利器

我第一次接触单细胞数据分析时,用的是 Seurat。那时候 Scanpy 还不太成气候。后来转 Python 生态,才发现这工具真香。说白了,Scanpy 就是单细胞领域的“pandas + scikit-learn”,一套基于 Python 的完整分析框架。

今天咱们聊聊它的来龙去脉、能干些什么,以及跟 Seurat 比到底谁更顺手。

1.1 发展历史:从科研工具到行业标准

Scanpy 诞生于 2017 年,由德国亥姆霍兹研究所的 Alex Wolf 和 Philipp Angerer 主导开发。它的底层依赖 AnnData 数据结构——你可以把它理解为一个“带注释的矩阵”,基因表达矩阵、细胞元数据、基因元数据全塞在一个对象里。

我个人习惯把技术演进分为三个阶段:

阶段 时间 主要变化
雏形期 2017-2018 基本功能:预处理、降维、聚类、标记基因
生态期 2019-2021 集成 scvelo(RNA 速率)、squidpy(空间转录组)
成熟期 2022 至今 1.9+ 版本,对接 Hugging Face、分布式计算

核心数据容器:AnnData。你只需要记住一个词——“.obs 存细胞信息,.var 存基因信息,.X 存表达矩阵”。

我记得 2020 年做一个项目,数据量 50 万个细胞,Seurat 直接内存崩溃。换 Scanpy 用 sc.pp.filter_cells + 稀疏矩阵,半小时搞定。从那以后我果断切到 Python 生态。

1.2 主要功能:一条流水线走到底

Scanpy 的功能覆盖了单细胞分析的完整流程。我把它总结成“七步法”:

  1. 数据读取:支持 h5ad、10X 格式、CSV、HDF5
  2. 质量控制:过滤低质量细胞和基因
  3. 标准化:总表达量归一化,log 转换
  4. 高度可变基因选择:降维前先筛选特征
  5. 降维:PCA、t-SNE、UMAP
  6. 聚类:Leiden 算法(默认)、Louvain
  7. 差异表达与注释:标记基因鉴定,自动/手动注释

举个最简单的入口例子:

import scanpy as sc

# 读取数据
adata = sc.read_10x_h5("filtered_feature_bc_matrix.h5")

# 基础质控
sc.pp.filter_cells(adata, min_genes=200)
sc.pp.filter_genes(adata, min_cells=3)

# 标准化与对数转换
sc.pp.normalize_total(adata, target_sum=1e4)
sc.pp.log1p(adata)

# 找高变基因
sc.pp.highly_variable_genes(adata, n_top_genes=2000)

# PCA + UMAP
sc.tl.pca(adata)
sc.pp.neighbors(adata)
sc.tl.umap(adata)

# 聚类
sc.tl.leiden(adata)

# 找标记基因
sc.tl.rank_genes_groups(adata, 'leiden')
print(adata.uns['rank_genes_groups']['names'][0:5])

快捷键:sc.pl.umap(adata, color='leiden') 能直接看聚类效果,比 Seurat 的 DimPlot 快一截。

我在项目中发现一个常见坑:很多人直接跑 sc.pp.filter_cells(min_genes=200) 不去看原始分布。其实应该先画个 sc.pl.violin(adata, 'n_genes_by_counts') 手动设阈值。硬编码 200 在一些低质量样本里会误杀太多细胞。

1.3 与 Seurat 的对比:没有银弹

这个问题每次讲座都有人问。我直接给你一张对比表:

维度 Scanpy Seurat
语言 Python R
数据容器 AnnData (h5ad) SeuratObject (rds)
内存效率 稀疏矩阵原生支持,适合大样本 全矩阵易溢出,>30w细胞需分批
扩展生态 scvelo, squidpy, celltypist Signac, Azimuth, DoubletFinder
可视化 Matplotlib/seaborn 基础,高度可定制 ggplot2 风格,内置交互性更强
社区活跃度 快速增长,学术界+工业界并重 老牌霸主,教程最丰富
学习曲线 需要 Python 基础,文档偏开发者风格 R 系语法,对生物学家友好

你想想看,如果你团队全是 R 用户,上 Scanpy 肯定吃力。反过来,如果项目数据量超过 30 万个细胞,或者你想把分析嵌入 Python 的机器学习流水线,Scanpy 明显更省心。

我曾经接手一个 Seurat 转 Scanpy 的项目,发现 NormalizeData 和 ScaleData 的默认参数不一样。Seurat 默认做全局缩放,Scanpy 默认只做对数化。一定不要直接套用同一种预处理策略。

1.4 如何选择?我的经验法则

  • 学生/教学场景:Seurat 教程多、图形化强,入门友好
  • 大规模数据(>30w cells):优先 Scanpy,内存控制更好
  • 需要对接下游机器学习/深度学习:Scanpy + Pytorch 无缝衔接
  • 全栈 R 生态:没必要硬转,Seurat 足够用
  • 空间转录组、RNA 速率分析:Scanpy 生态的 squidpy/scvelo 更成熟
Scanpy 单细胞分析流程框架 原始数据输入 质量控制(QC) 标准化 & 归一化 高变基因筛选 降维 (PCA/UMAP) Leiden 聚类 差异表达分析 细胞类型注释 结果导出与报告 降维到2D可视化

快速上手建议:先装pip install scanpy[leiden],数据用官方自带的sc.datasets.pbmc3k()跑一遍全流程,半小时就能看见 UMAP 图。

嗯,这就是 Scanpy 的全貌。它不是什么黑魔法,就是一个为单细胞而生的 Python 库。后面几章咱们会逐层拆解每个步骤背后的数学原理和实战技巧。你要是之前只用过 Seurat,也别慌——思维模型是相通的,只是换了一套 API 而已。