Pipeline Detail
10x 单细胞基础降维聚类
面向 10x Genomics scRNA-seq 数据的综合分析流程,覆盖分析类型选择、Cell Ranger 预处理、Seurat v5/Scanpy 质控、整合、聚类、注释和下游解释。
Metadata
流程元数据
先看应用场景、输入输出和工具依赖,再进入正文命令细节。
Difficulty
入门
Scenario
单细胞分析
Estimated Time
0.5-1 天
Tools
Inputs
Outputs
Workflow DAG
流程图
用步骤节点快速理解这个分析从原始数据到结果报告的流转关系。
实验设计与类型判断
Cell Ranger 定量
细胞/基因质控
双细胞与环境 RNA 评估
SCTransform/NormalizeData
多样本整合
PCA/邻接图/UMAP/聚类
Marker 与细胞类型注释
差异/通路/拟时序/通讯
Protocol
流程文档
正文保留 Markdown 排版、代码语言标识和表格样式,适合边学边复现。
10x 单细胞 RNA-seq 综合分析流程
一、单细胞分析的主要类型
单细胞分析不是单一流程,而是一组围绕细胞异质性的问题框架。建项目前先判断研究问题属于哪一类,这会直接影响质控阈值、整合策略和下游统计方法。
| 类型 | 典型问题 | 推荐方法 | 关键输出 |
|---|---|---|---|
| 基础细胞图谱 | 样本里有哪些细胞群?比例如何? | Seurat v5 或 Scanpy 标准聚类流程 | UMAP、cluster、marker genes、细胞类型注释 |
| 多样本/多批次整合 | 不同样本、批次、处理组能否放在同一空间比较? | Seurat IntegrateLayers、Harmony、RPCA、scVI | integrated embedding、整合后聚类 |
| 组间差异表达 | 某类细胞在处理组与对照组中哪些基因改变? | pseudobulk 优先,其次 cell-level DE | cell type-specific DEG |
| 细胞比例变化 | 疾病或处理是否改变某类细胞占比? | proportion test、Dirichlet-multinomial、Milo | 细胞组成差异 |
| 发育轨迹/拟时序 | 细胞是否存在连续分化路径? | Monocle3、Slingshot、Palantir | trajectory、pseudotime、branch markers |
| 细胞通讯 | 细胞群之间可能通过哪些配体受体互作? | CellChat、NicheNet、LIANA | ligand-receptor network |
| 自动注释/参考映射 | 新数据如何映射到已有 atlas? | Azimuth、SingleR、CellTypist、scArches | predicted cell type labels |
| 多组学/空间扩展 | RNA + ATAC、CITE-seq 或空间转录组如何联合解释? | Seurat WNN、Signac、Scanpy/Squidpy | multi-modal embedding、空间特征 |
二、最佳实践选择
推荐主流程
对 10x Genomics 3' 或 5' scRNA-seq 项目,MVP 阶段建议采用:
Cell Ranger count生成表达矩阵和官方 QC 报告。Seurat v5 + SCTransform作为主分析流程。- 多样本项目使用 Seurat v5
IntegrateLayers,优先试RPCAIntegration或HarmonyIntegration。 - 大规模数据、跨平台 atlas 或 Python 团队可并行使用
Scanpy + scVI。 - 差异表达建议按样本聚合做 pseudobulk,避免把细胞当作完全独立重复。
为什么这样选
- Seurat v5 文档覆盖质控、归一化、聚类、整合和参考映射,适合快速建立可复用分析模板。
- SCTransform 对测序深度差异更稳,适合多样本项目的归一化和高变基因建模。
- RPCA/Harmony 通常比强行 CCA 更保守,较不容易抹掉真实生物差异。
- Scanpy 适合 Python 工作流和大规模 AnnData 生态,后续可以接 scVI、CellTypist、Squidpy 等工具。
三、整体流程图
flowchart TD
A[实验设计与样本信息] --> B[Cell Ranger count]
B --> C[读取 filtered_feature_bc_matrix]
C --> D[细胞与基因质控]
D --> E[双细胞 doublet 评估]
E --> F[环境 RNA / 低质量细胞检查]
F --> G[SCTransform 或 NormalizeData]
G --> H[高变基因 / PCA]
H --> I{是否多样本或多批次?}
I -- 是 --> J[IntegrateLayers / Harmony / scVI]
I -- 否 --> K[FindNeighbors]
J --> K
K --> L[FindClusters]
L --> M[UMAP / t-SNE 可视化]
M --> N[Marker gene 鉴定]
N --> O[细胞类型注释]
O --> P[差异表达 / 富集 / 拟时序 / 通讯]
四、输入文件与目录建议
single_cell_project/
├── 00_metadata/
│ └── sample_info.csv
├── 01_fastq/
│ ├── sampleA/
│ └── sampleB/
├── 02_cellranger/
│ ├── sampleA/outs/
│ └── sampleB/outs/
├── 03_seurat/
│ ├── rds/
│ ├── tables/
│ └── plots/
├── 04_annotation/
├── 05_downstream/
└── reports/
sample_info.csv 至少包含:
| 字段 | 说明 |
|---|---|
sample_id | 样本 ID,必须与 Cell Ranger 输出目录一致 |
condition | 实验分组,如 control、treatment |
batch | 建库批次或测序批次 |
tissue | 组织来源 |
fastq_dir | FASTQ 所在目录 |
五、Cell Ranger 预处理
Cell Ranger 负责把 FASTQ 转换为基因表达矩阵。它的输出是后续 Seurat/Scanpy 分析的入口。
cellranger count --id=sampleA --transcriptome=/ref/refdata-gex-GRCh38-2024-A --fastqs=/data/fastq/sampleA --sample=sampleA --localcores=24 --localmem=128
多样本可写成循环:
REF=/ref/refdata-gex-GRCh38-2024-A
FASTQ_ROOT=/data/fastq
OUT_ROOT=02_cellranger
for sample in sampleA sampleB sampleC
do
cellranger count --id=${sample} --transcriptome=${REF} --fastqs=${FASTQ_ROOT}/${sample} --sample=${sample} --localcores=24 --localmem=128
mv ${sample} ${OUT_ROOT}/
done
重点检查 outs/web_summary.html:
| 指标 | 解释 | 风险信号 |
|---|---|---|
| Estimated Number of Cells | 估计捕获细胞数 | 明显低于上样预期 |
| Mean Reads per Cell | 单细胞平均 reads 数 | 过低会影响基因检出 |
| Median Genes per Cell | 每个细胞检测基因数中位数 | 过低提示低质量或细胞破裂 |
| Fraction Reads in Cells | reads 落入有效细胞 barcode 的比例 | 过低提示背景 RNA 或空液滴多 |
| Sequencing Saturation | 测序饱和度 | 过低可考虑补测 |
六、Seurat v5 主分析流程
1. 读取数据并创建对象
library(Seurat)
library(dplyr)
library(ggplot2)
library(patchwork)
sample_info <- read.csv("00_metadata/sample_info.csv")
seurat_list <- lapply(seq_len(nrow(sample_info)), function(i) {
sample_id <- sample_info$sample_id[i]
matrix_dir <- file.path("02_cellranger", sample_id, "outs", "filtered_feature_bc_matrix")
counts <- Read10X(data.dir = matrix_dir)
obj <- CreateSeuratObject(
counts = counts,
project = sample_id,
min.cells = 3,
min.features = 200
)
obj$sample_id <- sample_id
obj$condition <- sample_info$condition[i]
obj$batch <- sample_info$batch[i]
obj$tissue <- sample_info$tissue[i]
obj[["percent.mt"]] <- PercentageFeatureSet(obj, pattern = "^MT-")
obj[["percent.ribo"]] <- PercentageFeatureSet(obj, pattern = "^RP[SL]")
obj
})
names(seurat_list) <- sample_info$sample_id
2. 质控阈值设置
常用 QC 指标:
| 指标 | 含义 | 常见处理 |
|---|---|---|
nFeature_RNA | 每个细胞检测到的基因数 | 过低为空液滴或低质量,过高可能是 doublet |
nCount_RNA | 每个细胞 UMI 总数 | 极高可能是 doublet,极低可能低质量 |
percent.mt | 线粒体基因比例 | 高比例通常提示细胞应激或破裂 |
percent.ribo | 核糖体基因比例 | 可辅助判断细胞状态 |
阈值不要机械套用,应先画图再定:
qc_plot <- VlnPlot(
seurat_list[[1]],
features = c("nFeature_RNA", "nCount_RNA", "percent.mt"),
ncol = 3,
pt.size = 0.1
)
ggsave("03_seurat/plots/qc_violin_sampleA.pdf", qc_plot, width = 12, height = 4)
初始经验阈值:
filter_one <- function(obj) {
subset(
obj,
subset =
nFeature_RNA > 300 &
nFeature_RNA < 6000 &
nCount_RNA > 500 &
percent.mt < 15
)
}
seurat_list <- lapply(seurat_list, filter_one)
经验解释:
- PBMC 等免疫细胞常用
percent.mt < 10-15。 - 肿瘤、组织样本或冷冻样本线粒体比例可能更高,需要结合分布决定。
- 神经元、肌肉、肝脏等组织的基因数范围可能显著不同,不能直接照搬 PBMC 阈值。
3. 双细胞和环境 RNA
双细胞 doublet 会导致两个细胞类型的 marker 同时出现,影响聚类和注释。建议至少做一次 doublet 评估。
可选工具:
| 工具 | 生态 | 说明 |
|---|---|---|
| DoubletFinder | R/Seurat | Seurat 用户常用 |
| scDblFinder | Bioconductor | 自动化程度高 |
| Scrublet | Python | Scanpy 工作流常用 |
示意代码:
# DoubletFinder 参数需要根据数据量和预期 doublet rate 调整。
# MVP 阶段建议先标记 doublet,再比较去除前后的 UMAP 和 marker 表。
环境 RNA 可用 SoupX、DecontX 等工具评估。若样本有明显红细胞、上皮裂解或坏死背景,建议在正式分析前处理。
4. SCTransform 归一化
seurat_list <- lapply(seurat_list, function(obj) {
SCTransform(
obj,
vars.to.regress = "percent.mt",
verbose = FALSE
)
})
如果是单样本初步探索,也可以使用经典 LogNormalize:
obj <- NormalizeData(obj)
obj <- FindVariableFeatures(obj, selection.method = "vst", nfeatures = 2000)
obj <- ScaleData(obj, vars.to.regress = c("percent.mt"))
5. 多样本整合
Seurat v5 推荐使用 layer-based integration。示例:
combined <- merge(
seurat_list[[1]],
y = seurat_list[-1],
add.cell.ids = names(seurat_list)
)
combined[["RNA"]] <- split(combined[["RNA"]], f = combined$sample_id)
combined <- NormalizeData(combined)
combined <- FindVariableFeatures(combined)
combined <- ScaleData(combined)
combined <- RunPCA(combined)
combined <- IntegrateLayers(
object = combined,
method = RPCAIntegration,
orig.reduction = "pca",
new.reduction = "integrated.rpca",
verbose = FALSE
)
方法选择建议:
| 方法 | 适用场景 | 风险 |
|---|---|---|
| RPCAIntegration | 同平台、多样本、差异较温和 | 可能保留部分批次效应 |
| HarmonyIntegration | 批次变量明确、速度快 | 参数不当可能过校正 |
| CCAIntegration | 细胞类型共享度较高 | 数据差异大时可能过度混合 |
| scVIIntegration | 大规模、复杂批次、Python 环境成熟 | 依赖环境更重 |
6. 降维、邻接图和聚类
combined <- FindNeighbors(combined, reduction = "integrated.rpca", dims = 1:30)
combined <- FindClusters(combined, resolution = 0.4)
combined <- FindClusters(combined, resolution = 0.8)
combined <- RunUMAP(combined, reduction = "integrated.rpca", dims = 1:30)
p1 <- DimPlot(combined, group.by = "sample_id")
p2 <- DimPlot(combined, group.by = "seurat_clusters", label = TRUE)
ggsave("03_seurat/plots/umap_sample_cluster.pdf", p1 + p2, width = 12, height = 5)
分辨率选择建议:
0.2-0.4:粗粒度细胞类型。0.6-1.0:常规探索。>1.2:寻找细胞亚群,但要警惕过度切分。
7. Marker gene 鉴定
combined <- PrepSCTFindMarkers(combined)
markers <- FindAllMarkers(
combined,
only.pos = TRUE,
min.pct = 0.25,
logfc.threshold = 0.25
)
write.csv(markers, "03_seurat/tables/all_cluster_markers.csv", row.names = FALSE)
常见免疫细胞 marker 示例:
| 细胞类型 | 常用 marker |
|---|---|
| T cells | CD3D, CD3E, TRAC |
| CD4 T | IL7R, CCR7, LTB |
| CD8 T | CD8A, CD8B, GZMK |
| NK cells | NKG7, GNLY, KLRD1 |
| B cells | MS4A1, CD79A, CD74 |
| Plasma cells | MZB1, JCHAIN, IGHG1 |
| Monocytes | LYZ, S100A8, S100A9 |
| Dendritic cells | FCER1A, CST3, CLEC10A |
| Platelets | PPBP, PF4 |
8. 细胞类型注释
推荐组合:
- 手动 marker 注释:最可靠,但需要领域知识。
- 参考数据库自动注释:SingleR、CellTypist、Azimuth。
- 回看样本来源和文献 marker:避免把技术 cluster 误判为新细胞类型。
手动注释示例:
new_ids <- c(
"0" = "CD4 T cells",
"1" = "CD14 Monocytes",
"2" = "B cells",
"3" = "CD8 T cells",
"4" = "NK cells"
)
combined$celltype <- plyr::mapvalues(
x = combined$seurat_clusters,
from = names(new_ids),
to = as.vector(new_ids)
)
DimPlot(combined, group.by = "celltype", label = TRUE)
ggsave("03_seurat/plots/umap_celltype.pdf", width = 8, height = 6)
9. 组间差异表达:优先 pseudobulk
单细胞中每个细胞不是完全独立生物学重复。如果有多个样本,建议按 sample_id + celltype 聚合,再用 DESeq2/edgeR 做差异分析。
counts_by_celltype <- AggregateExpression(
combined,
group.by = c("celltype", "sample_id"),
assays = "RNA",
slot = "counts",
return.seurat = FALSE
)
后续思路:
- 对每个 cell type 提取 sample-level count matrix。
- 构建
condition设计矩阵。 - 用 DESeq2 做
~ condition。 - 分别输出每类细胞的 DEG 和富集结果。
10. 下游分析选择
| 下游方向 | 推荐工具 | 适合问题 |
|---|---|---|
| 通路富集 | clusterProfiler、fgsea、GSEApy | DEG 指向哪些通路 |
| 拟时序 | Monocle3、Slingshot、Palantir | 发育、分化、状态转换 |
| RNA velocity | scVelo、velocyto | 细胞状态变化方向 |
| 细胞通讯 | CellChat、NicheNet、LIANA | 哪些细胞群可能相互作用 |
| CNV 推断 | inferCNV、copyKAT | 肿瘤单细胞恶性细胞识别 |
| TCR/BCR | scRepertoire、immunarch | 克隆扩增和免疫受体谱 |
七、Scanpy 备用流程
Python 团队或大规模数据可使用 Scanpy:
import scanpy as sc
adata = sc.read_10x_mtx(
"02_cellranger/sampleA/outs/filtered_feature_bc_matrix",
var_names="gene_symbols",
cache=True,
)
adata.var["mt"] = adata.var_names.str.startswith("MT-")
sc.pp.calculate_qc_metrics(adata, qc_vars=["mt"], inplace=True)
adata = adata[
(adata.obs["n_genes_by_counts"] > 300)
& (adata.obs["n_genes_by_counts"] < 6000)
& (adata.obs["pct_counts_mt"] < 15),
:
]
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]
sc.pp.scale(adata, max_value=10)
sc.tl.pca(adata)
sc.pp.neighbors(adata, n_pcs=30)
sc.tl.leiden(adata, resolution=0.8)
sc.tl.umap(adata)
sc.tl.rank_genes_groups(adata, "leiden", method="wilcoxon")
adata.write("03_scanpy/sampleA_processed.h5ad")
八、关键质控图
建议每个项目至少输出:
- Cell Ranger
web_summary.html - 每个样本的
nFeature_RNA/nCount_RNA/percent.mt小提琴图 - QC 前后细胞数统计表
- UMAP 按
sample_id着色 - UMAP 按
condition着色 - UMAP 按
cluster和celltype着色 - 每个 cluster 的 top marker 热图
- 注释后的细胞比例堆叠图
细胞比例图示例:
prop_df <- combined@meta.data |>
dplyr::count(sample_id, condition, celltype) |>
dplyr::group_by(sample_id) |>
dplyr::mutate(prop = n / sum(n))
ggplot(prop_df, aes(x = sample_id, y = prop, fill = celltype)) +
geom_col(width = 0.8) +
facet_grid(. ~ condition, scales = "free_x", space = "free_x") +
theme_bw() +
labs(x = "Sample", y = "Cell proportion")
九、常见问题与排查
| 问题 | 可能原因 | 处理建议 |
|---|---|---|
| 细胞数远低于预期 | 细胞活性差、上样不足、组织解离失败 | 查看 Cell Ranger summary,回看实验记录 |
| 线粒体比例整体偏高 | 细胞破裂、组织应激、冷冻样本 | 分样本设阈值,不要一刀切 |
| UMAP 按样本分开 | 批次效应或真实组间差异 | 先判断 marker,再尝试 RPCA/Harmony |
| 聚类过碎 | resolution 太高,PC 太多 | 降低 resolution,检查 clustree |
| marker 不清晰 | 低质量细胞、doublet、注释层级不合适 | 去 doublet,重新聚类或合并相近 cluster |
| 差异基因过多 | 把细胞当重复、批次未控制 | 使用 pseudobulk,设计矩阵加入批次 |
十、主要输出
filtered_feature_bc_matrix- Seurat
.rds或 Scanpy.h5ad - QC summary table
- UMAP/t-SNE 图
- cluster marker gene 表
- 细胞类型注释表
- 每个样本/组别的细胞比例表
- cell type-specific DEG
- 富集分析结果
- 可选:拟时序、通讯、RNA velocity、CNV 推断结果
十一、参考资料
- Seurat v5 官方 Getting Started:标准无监督聚类流程包含 QC、过滤、高变基因、降维、图聚类和 marker 鉴定。
- Seurat v5 Integration 官方文档:
IntegrateLayers支持 CCA、RPCA、Harmony、FastMNN、scVI 等整合方法。 - Scanpy 官方 preprocessing and clustering tutorial:提供 Python 生态的过滤、归一化、HVG、PCA、neighbors、Leiden、UMAP 和 marker 流程。
- 10x Genomics Cell Ranger 文档:用于从 FASTQ 生成表达矩阵和
web_summary.html质控报告。