← 返回 Tessera
Toy4.6 万 行 × 125.3 MB无缺失数据 2026-08-18

pbmc5k_donor4_cluster_de

同一位真实 PBMC donor 中三个目标 cluster 相对共同参考 cluster 的完整差异表达结果——火山图、marker 表和基因集合交集图的练习数据。

10x Genomics 5k Human PBMCs Donor 4(Cell Ranger 9.0.0) · 收录于 2026-08-18

下载 CSV · 5.3 MB
数据预览6
result_idcomparisontarget_clusterreference_clustern_targetn_referencegeneavg_log2fcpct_targetpct_referencep_valuep_adj
cluster_0_vs_3::B2Mcluster_0_vs_303746580B2M-2.680.94511.07e-2042.73e-200
cluster_0_vs_3::RPL41cluster_0_vs_303746580RPL41-2.880.7612.93e-2037.49e-199
cluster_0_vs_3::RPL30cluster_0_vs_303746580RPL30-2.430.82712.57e-2006.56e-196
cluster_0_vs_3::FAUcluster_0_vs_303746580FAU-2.380.7280.9984.20e-1981.07e-193
cluster_0_vs_3::RPL10cluster_0_vs_303746580RPL10-2.640.8750.9975.49e-1981.40e-193
cluster_0_vs_3::RPS10cluster_0_vs_303746580RPS10-3.40.5820.9954.03e-1971.03e-192
变量12
字符型3整数4双精度5
类型
#变量类型缺失统计
1result_idkeycomparison 与 gene 组成的稳定唯一键字符型不同值 45578cluster_0_vs_3::B2M · cluster_0_vs_3::RPL41 · cluster_0_vs_3::RPL30 · cluster_0_vs_3::FAU · cluster_0_vs_3::RPL10 · cluster_0_vs_3::RPS10 · cluster_0_vs_3::RPS29 · cluster_0_vs_3::HLA-B
2comparisoncluster_0_vs_3 / cluster_1_vs_3 / cluster_2_vs_3字符型不同值 3cluster_1_vs_3 · cluster_2_vs_3 · cluster_0_vs_3
3target_cluster整数min 0q1 中位 1均值 1.02q3 max 2
4reference_cluster整数min 3q1 中位 3均值 3q3 max 3
5n_target整数min 619.0q1 中位 648.0均值 669.3q3 max 746.0
6n_reference整数min 580.0q1 中位 580.0均值 580.0q3 max 580.0
7gene字符型不同值 17097B2M · RPL41 · RPL30 · FAU · RPL10 · RPS10 · RPS29 · HLA-B
8avg_log2fc正值表示目标 cluster 高表达,负值表示参考 cluster 3 高表达双精度min -10.4q1 中位 0.106均值 0.119q3 max 11.7
9pct_target目标 cluster 中检测到该基因的细胞比例双精度min 0q1 中位 0.083均值 0.188q3 max 1
10pct_reference参考 cluster 3 中检测到该基因的细胞比例双精度min 0q1 中位 0.1均值 0.203q3 max 1
11p_value双精度min 1.5e-228q1 中位 0.00682均值 0.155q3 max 1
12p_adjSeurat Wilcoxon 检验经 Bonferroni 校正的 P 值双精度min 3.8e-224q1 中位 1均值 0.672q3 max 1
载入已写好列类型
library(readr)

pbmc5k_donor4_cluster_de <- read_csv(
  "https://assets.evanzhou.org/tessera/csv/pbmc5k_donor4_cluster_de.csv",
  col_types = cols(
    result_id         = col_character(),
    comparison        = col_character(),
    target_cluster    = col_integer(),
    reference_cluster = col_integer(),
    n_target          = col_integer(),
    n_reference       = col_integer(),
    gene              = col_character(),
    avg_log2fc        = col_double(),
    pct_target        = col_double(),
    pct_reference     = col_double(),
    p_value           = col_double(),
    p_adj             = col_double()
  )
)
URLhttps://assets.evanzhou.org/tessera/csv/pbmc5k_donor4_cluster_de.csv

来源

原始数据是 10x Genomics 发布的 5k Human PBMCs, Donor 4。生成脚本直接读取下载目录中的 barcodes.tsv.gzfeatures.tsv.gzmatrix.mtx.gz,不依赖临时 Seurat 对象或手工整理的 marker 表。

脚本完整复现 pbmc5k_donor4_embeddings 的 QC、LogNormalize、2,000 个高变基因、PCA、邻居图和 Louvain 聚类。随后固定 Cluster 3 为共同参考,分别运行 Cluster 0 vs 3、Cluster 1 vs 3 和 Cluster 2 vs 3 的双向 Wilcoxon 差异表达检验。选择 0、1、2、3 是因为它们是当前固定流程中细胞数最多的四个 cluster,规则明确且避免根据差异结果事后挑组。

比较方向

三个比较共享同一个参考组,因此方向可以直接比较:avg_log2fc > 0 始终表示目标 cluster 相对 Cluster 3 高表达,avg_log2fc < 0 始终表示 Cluster 3 高表达。火山图使用每个比较的全部结果;Venn 图应从三个比较中用同一阈值筛选正向 marker,例如 p_adj < 0.05avg_log2fc >= 0.25pct_target >= 0.10,再计算基因集合交集。

解释边界

数据只有一位 donor。检验把细胞作为观测单位,适合 marker 探索和绘图练习,但不提供供者层面的生物学重复,不能解释为可推广到人群的差异表达证据。Cluster 编号也是无监督标签,不等同于已注释细胞类型。

适用图形

图形结构 用途
火山图 同时展示效应方向、效应大小与校正后显著性
Venn 图 比较三个目标 cluster 相对共同参考组的上调 marker 交集
Marker 排名表 按效应值或校正后 P 值查看代表性基因
MA 图 检查效应大小与平均表达水平的关系(需在扩展版本中加入平均表达列)
生成脚本R · 129
# Build Tessera's PBMC cluster differential-expression toy directly from a
# 10x Genomics filtered feature-barcode matrix directory:
#   barcodes.tsv.gz · features.tsv.gz · matrix.mtx.gz
#
# Usage:
#   Rscript --vanilla pbmc5k_donor4_cluster_de.R <10x-directory> [output.csv]
#
# Clusters 0, 1 and 2 are compared independently with the same reference,
# cluster 3. The upstream QC, normalization, PCA and Louvain clustering are
# intentionally identical to pbmc5k_donor4_embeddings.R.

args <- commandArgs(trailingOnly = TRUE)
if (length(args) < 1L) {
  stop("Provide the 10x filtered feature-barcode matrix directory", call. = FALSE)
}

input <- args[[1L]]
output <- if (length(args) >= 2L) args[[2L]] else "pbmc5k_donor4_cluster_de.csv"
required_files <- c("barcodes.tsv.gz", "features.tsv.gz", "matrix.mtx.gz")
missing_files <- required_files[!file.exists(file.path(input, required_files))]
if (length(missing_files)) {
  stop("Missing 10x files: ", paste(missing_files, collapse = ", "), call. = FALSE)
}

set.seed(1)
counts <- Seurat::Read10X(
  data.dir = input,
  gene.column = 2,
  cell.column = 1,
  unique.features = TRUE,
  strip.suffix = FALSE
)
pbmc <- Seurat::CreateSeuratObject(
  counts = counts,
  project = "pbmc5k_donor4",
  min.cells = 3,
  min.features = 40
)

pbmc[["percent_mito"]] <- Seurat::PercentageFeatureSet(pbmc, pattern = "^MT-")
pbmc <- subset(
  pbmc,
  subset = nCount_RNA >= 500 & nCount_RNA <= 15000 &
    nFeature_RNA >= 200 & nFeature_RNA <= 5000 & percent_mito < 10
)
pbmc <- Seurat::NormalizeData(
  pbmc,
  normalization.method = "LogNormalize",
  scale.factor = 10000,
  verbose = FALSE
)
pbmc <- Seurat::FindVariableFeatures(
  pbmc,
  selection.method = "vst",
  nfeatures = 2000,
  verbose = FALSE
)
pbmc <- Seurat::ScaleData(
  pbmc,
  features = Seurat::VariableFeatures(pbmc),
  verbose = FALSE
)
pbmc <- Seurat::RunPCA(
  pbmc,
  features = Seurat::VariableFeatures(pbmc),
  npcs = 30,
  seed.use = 1,
  verbose = FALSE
)
pbmc <- Seurat::FindNeighbors(
  pbmc,
  reduction = "pca",
  dims = 1:20,
  k.param = 20,
  verbose = FALSE
)
pbmc <- Seurat::FindClusters(
  pbmc,
  resolution = 0.8,
  algorithm = 1,
  random.seed = 1,
  verbose = FALSE
)
SeuratObject::Idents(pbmc) <- "seurat_clusters"

target_clusters <- c("0", "1", "2")
reference_cluster <- "3"
cluster_counts <- table(SeuratObject::Idents(pbmc))
required_clusters <- c(target_clusters, reference_cluster)
if (!all(required_clusters %in% names(cluster_counts))) {
  stop("Expected clusters 0, 1, 2 and 3 were not reproduced", call. = FALSE)
}

results <- lapply(target_clusters, function(target_cluster) {
  markers <- Seurat::FindMarkers(
    pbmc,
    ident.1 = target_cluster,
    ident.2 = reference_cluster,
    assay = "RNA",
    slot = "data",
    test.use = "wilcox",
    logfc.threshold = 0,
    min.pct = 0.01,
    only.pos = FALSE,
    verbose = FALSE
  )
  markers$gene <- rownames(markers)
  comparison <- paste0("cluster_", target_cluster, "_vs_", reference_cluster)
  data.frame(
    result_id = paste(comparison, markers$gene, sep = "::"),
    comparison = comparison,
    target_cluster = as.integer(target_cluster),
    reference_cluster = as.integer(reference_cluster),
    n_target = unname(cluster_counts[[target_cluster]]),
    n_reference = unname(cluster_counts[[reference_cluster]]),
    gene = markers$gene,
    avg_log2fc = markers$avg_log2FC,
    pct_target = markers$pct.1,
    pct_reference = markers$pct.2,
    p_value = markers$p_val,
    p_adj = markers$p_val_adj,
    row.names = NULL,
    check.names = FALSE
  )
})

frozen <- do.call(rbind, results)
frozen <- frozen[order(frozen$target_cluster, frozen$p_adj, -abs(frozen$avg_log2fc), frozen$gene), ]
write.csv(frozen, output, row.names = FALSE)

表中统计由 scripts/profile_dataset.py 于 2026-08-18 数出。