单细胞转录组测序(scRNA-seq)是当前生物医学研究中最热门的技术之一。从肿瘤微环境解析到发育轨迹追踪,scRNA-seq 已经成为高水平论文的标配。本文用 Scanpy(Python) 带你走完单细胞分析的前半程------从数据读取到降维聚类。
1. 环境准备
# 推荐 Conda 创建独立环境
conda create -n scRNA python=3.11 -y
conda activate scRNA
# 安装核心包
pip install scanpy pandas numpy matplotlib seaborn
Scanpy 是基于 Python 的单细胞分析框架,属于 scverse 生态系统,在处理大规模数据集(百万级细胞)时比 R 语言的 Seurat 更有优势,且与深度学习工具(scVI、scANVI)整合更方便。
import scanpy as sc
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
# 全局设置
sc.settings.verbosity = 1
sc.settings.set_figure_params(dpi=100, frameon=False, figsize=(6, 4))
plt.rcParams['font.sans-serif'] = ['Arial']
2. 数据读取
10x Genomics 产出的数据通常是三个文件:barcodes.tsv、features.tsv、matrix.mtx(存放在同一目录下)。
# 读取 10x 数据(h5 格式更方便)
adata = sc.read_10x_h5("filtered_feature_bc_matrix.h5")
# 或读取 mtx 格式
# adata = sc.read_10x_mtx("filtered_feature_bc_matrix/")
# 查看基本信息
print(adata) # n_obs × n_vars
输出示例:
AnnData object with n_obs × n_vars
obs: 'n_genes_by_counts', 'total_counts', 'pct_counts_mt', ...
var: 'gene_ids', 'feature_types', 'n_cells', ...
3. 质量控制(QC)
QC 是单细胞分析中最关键的第一步。核心指标有三个:
| 指标 | 含义 | 常用过滤阈值 |
|---|---|---|
| n_genes_by_counts | 每个细胞检测到的基因数 | 200 < n_genes < 6000 |
| total_counts | 每个细胞的 UMI 总数 | 去除极端值 |
| pct_counts_mt | 线粒体基因比例 | < 10%~15% |
# 计算线粒体基因比例(人类线粒体基因以 MT- 开头)
adata.var['mt'] = adata.var_names.str.startswith('MT-')
# 计算核糖体基因比例(可选,辅助判断)
adata.var['ribo'] = adata.var_names.str.startswith(("RPS", "RPL"))
# 计算红细胞基因比例(可选,血液组织用)
adata.var['hb'] = adata.var_names.str.contains("^HB[^(P)]")
# 汇总 QC 指标到 obs
sc.pp.calculate_qc_metrics(
adata, qc_vars=['mt', 'ribo', 'hb'], percent_top=None, log1p=False, inplace=True
)
# 可视化 QC 指标(小提琴图)
qc_metrics = ['n_genes_by_counts', 'total_counts', 'pct_counts_mt']
sc.pl.violin(adata, qc_metrics, groupby=None, jitter=0.4, multi_panel=True)
# 散点图:基因数 vs UMI 数
sc.pl.scatter(adata, x='total_counts', y='pct_counts_mt', color='pct_counts_mt')
sc.pl.scatter(adata, x='total_counts', y='n_genes_by_counts', color='pct_counts_mt')
# 过滤低质量细胞
adata = adata[
(adata.obs['n_genes_by_counts'] > 200) &
(adata.obs['n_genes_by_counts'] < 6000) &
(adata.obs['pct_counts_mt'] < 10),
:].copy()
print(f"过滤后保留 {adata.n_obs} 个细胞")
4. 数据标准化
# 归一化:每个细胞总 count 归一化到 10000,然后 log1p 变换
sc.pp.normalize_total(adata, target_sum=1e4)
sc.pp.log1p(adata)
# 保存归一化后的数据(后续差异分析要用)
adata.raw = adata
# 识别高变基因(Highly Variable Genes)
sc.pp.highly_variable_genes(adata, n_top_genes=2000, flavor='seurat_v3', batch_key=None)
sc.pl.highly_variable_genes(adata)
# 仅保留高变基因进行后续分析
adata = adata[:, adata.var['highly_variable']].copy()
5. 降维与聚类
# 回归掉不需要的变异来源(如 total_counts 和 pct_counts_mt)
sc.pp.regress_out(adata, ['total_counts', 'pct_counts_mt'])
# 缩放数据(z-score 标准化)
sc.pp.scale(adata, max_value=10)
# PCA 降维
sc.tl.pca(adata, n_comps=50, svd_solver='arpack')
# 可视化 PCA 解释方差
sc.pl.pca_variance_ratio(adata, log=True, n_pcs=50)
# 邻域图 + UMAP 降维 + 聚类
sc.pp.neighbors(adata, n_neighbors=15, n_pcs=30)
sc.tl.umap(adata)
sc.tl.leiden(adata, resolution=0.8) # Leiden 算法(推荐)或用 louvain
# 可视化 UMAP
sc.pl.umap(adata, color=['leiden'], legend_loc='on data', title='UMAP (Leiden 0.8)')
# 多种聚类分辨率对比
for res in [0.4, 0.6, 0.8, 1.0, 1.2]:
sc.tl.leiden(adata, resolution=res, key_added=f'leiden_{res}')
sc.pl.umap(adata, color=['leiden_0.4', 'leiden_0.8', 'leiden_1.2'], ncols=3)
6. 结果解读
运行完后你会得到 UMAP 图,每个点代表一个细胞,不同颜色代表不同的聚类(Leiden 算法是目前最推荐的聚类方法,相比 Louvain 更稳定)。
resolution 参数控制聚类的粗细程度:值越大,聚类越细(cluster 数越多);值越小,聚类越粗。建议尝试多个值,选择生物学上最合理的。
下一步我们将覆盖:细胞注释、差异表达分析、富集分析等后半程流程。
更多单细胞分析教程和标准化分析服务,可参考 Run2AI 运智,支持 Scanpy(Python)和 Seurat(R)双工具链的全流程 AI 驱动分析,矢量图表直接用于论文发表。