381_单细胞数据伪批量分析¶
一句话说明¶
伪批量(Pseudo-bulk)就是把同一类型细胞的reads合并成"一个样本",再用传统RNA-seq分析方法做差异分析——这样统计更可靠。
核心知识点¶
要点1:为什么要做伪批量¶
- 直接在单细胞层面做差异分析(如 FindMarkers)会把"细胞内重复"当成独立样本,严重高估统计显著性(p值偏小)
- 正确的生物学重复应该是"不同供体/样本",而不是"同一供体的不同细胞"
- 伪批量通过合并同类型细胞的reads,恢复到样本级别的统计单元
要点2:为什么"单细胞假重复"是个问题¶
- 例:1名患者提供10000个T细胞 ≠ 10000个独立生物学重复
- 这些细胞来自同一个人,共享遗传背景,是高度相关的伪重复(pseudoreplication)
- 正确做法:把这10000个T细胞合并成1个样本,多个患者才是真正的重复
要点3:伪批量分析流程¶
要点4:适用场景¶
- 多样本/多患者的单细胞研究(必须用)
- 寻找疾病 vs 健康的差异基因(临床相关分析)
- 时间点比较(治疗前后)
要点5:局限性¶
- 每种细胞类型至少需要3个独立样本,否则无统计效力
- 细胞数太少(<20个)的伪批量样本建议过滤掉
- 不适合单样本研究(单样本没有重复)
实战代码¶
伪批量分析(R,DESeq2)¶
library(Seurat) # 单细胞分析
library(DESeq2) # 差异分析(伪批量最佳搭配)
library(dplyr)
library(ggplot2)
# 假设 seurat_obj 已有:
# - cell_type: 细胞类型注释
# - sample_id: 每个细胞来自哪个供体/样本
# - condition: 疾病状态 (Disease/Control)
# ============================================================
# 步骤1:按"样本 + 细胞类型"分组,对reads计数求和
# ============================================================
# 创建"样本-细胞类型"组合的标识
seurat_obj$sample_celltype <- paste(
seurat_obj$sample_id, # 样本ID(如 P001, P002...)
seurat_obj$cell_type, # 细胞类型(如 T_cell, B_cell...)
sep = "_"
)
# 聚合reads:对每个"样本-细胞类型"组合的所有细胞求和
# 使用 AggregateExpression(Seurat v5专用函数)
pseudo_bulk <- AggregateExpression(
seurat_obj,
group.by = c("sample_id", "cell_type"), # 按样本+细胞类型分组
assays = "RNA",
slot = "counts", # 使用raw counts(DESeq2要求)
return.seurat = FALSE # 返回矩阵而非Seurat对象
)
pb_counts <- pseudo_bulk$RNA # 取RNA层
# 查看结果维度
cat("伪批量矩阵维度:", dim(pb_counts), "\n")
# 格式:行=基因,列="sample_id_cell_type"
# ============================================================
# 步骤2:只分析某一细胞类型(以T细胞为例)
# ============================================================
target_celltype <- "T_cell"
tcell_cols <- grepl(paste0("_", target_celltype, "$"), colnames(pb_counts))
tcell_pb <- pb_counts[, tcell_cols] # 只取T细胞列
# 构建样本元数据
tcell_meta <- data.frame(
col_name = colnames(tcell_pb)
) %>%
mutate(
sample_id = sub(paste0("_", target_celltype), "", col_name), # 提取样本ID
) %>%
left_join(
# 从Seurat对象提取样本级元数据(每个样本一行)
seurat_obj@meta.data %>%
group_by(sample_id, condition) %>%
summarise(.groups = "drop"),
by = "sample_id"
)
rownames(tcell_meta) <- tcell_meta$col_name
# 检查:过滤掉T细胞数量太少的伪批量样本
cell_counts <- table(seurat_obj$sample_id[seurat_obj$cell_type == target_celltype])
keep_samples <- names(cell_counts)[cell_counts >= 20] # 至少20个T细胞
tcell_pb <- tcell_pb[, rownames(tcell_meta)[tcell_meta$sample_id %in% keep_samples]]
tcell_meta <- tcell_meta[colnames(tcell_pb), ]
cat("保留样本数:", ncol(tcell_pb), "\n")
# ============================================================
# 步骤3:DESeq2 差异分析
# ============================================================
dds <- DESeqDataSetFromMatrix(
countData = tcell_pb, # 整数count矩阵(基因×伪批量样本)
colData = tcell_meta, # 样本元数据
design = ~ condition # 统计模型:按疾病状态比较
)
# 过滤低表达基因(加速分析,减少多重检验负担)
keep_genes <- rowSums(counts(dds) >= 10) >= 3 # 至少3个样本中有>=10个reads
dds <- dds[keep_genes, ]
# 运行 DESeq2
dds <- DESeq(dds)
# 提取结果(Disease vs Control)
res <- results(
dds,
contrast = c("condition", "Disease", "Control"),
alpha = 0.05 # FDR 阈值
)
res <- as.data.frame(res)
res <- res[order(res$pvalue), ] # 按 p 值排序
# 显著差异基因
sig_genes <- res[!is.na(res$padj) & res$padj < 0.05 & abs(res$log2FoldChange) > 1, ]
cat("显著差异基因数:", nrow(sig_genes), "\n")
# ============================================================
# 步骤4:可视化
# ============================================================
# 火山图
res$status <- "NS"
res$status[res$padj < 0.05 & res$log2FoldChange > 1] <- "Up"
res$status[res$padj < 0.05 & res$log2FoldChange < -1] <- "Down"
ggplot(res[!is.na(res$padj), ], aes(x = log2FoldChange, y = -log10(padj),
color = status)) +
geom_point(alpha = 0.6, size = 1) +
scale_color_manual(values = c("Up" = "red", "Down" = "blue", "NS" = "gray")) +
geom_hline(yintercept = -log10(0.05), linetype = "dashed") +
geom_vline(xintercept = c(-1, 1), linetype = "dashed") +
labs(title = paste("T细胞伪批量分析:Disease vs Control"),
x = "Log2 Fold Change", y = "-Log10 adj.p") +
theme_classic()
面试常问点¶
- 为什么Seurat的FindMarkers用的不是伪批量? FindMarkers把细胞当独立重复做Wilcoxon/t检验,在多样本研究中会假阳性增多;伪批量是更统计正确的方法
- 至少需要几个样本才能做伪批量? DESeq2建议每组至少3个,最好6+个(样本越多,统计效力越高)
- 伪批量和MAST、edgeR single-cell模式的区别? MAST等专门的scRNA-seq差异工具尝试在细胞层面纳入样本相关性(如随机效应),但计算更复杂;伪批量更简单且有充分的理论支持
速查表¶
| 分析目的 | 推荐方法 | 原因 |
|---|---|---|
| 多样本疾病比较 | 伪批量 + DESeq2 | 统计正确,控制假阳性 |
| 单样本探索 | FindMarkers(Wilcoxon) | 无样本重复时的替代 |
| 快速marker找寻 | FindMarkers | 速度快,适合探索 |
| 严格发表分析 | 伪批量 | 统计规范性要求 |