Skip to content

读取 10x 表达矩阵:建立带样本信息的 Seurat 对象 ​

10x 单细胞分析入门 · 第 06 篇

这一节只做导入:确认行列方向、建立对象、加入样本信息,再保存检查点。先把输入解释清楚,后面的过滤和聚类才有可追溯的起点。

需要完成环境自检与数据下载。终端工作目录为 ~/sc-course,输入位于 data/raw/filtered_gene_bc_matrices/hg19/。

先运行完整脚本 ​

bash
cd ~/sc-course
Rscript scripts/01-import.R "$PWD" > logs/01-import.log 2>&1
echo $?
cat logs/01-import.log
ls -lh results/01-*

应得到 01-imported.rds、导入摘要和逐细胞元数据表。退出码非零时先读日志,不要跳到下一节,使用别的目录里碰巧存在的 RDS 继续。

下文拆解这个脚本。想交互练习时,在 R 中从头执行;不要在 Bash 里直接输入 R 代码。

读入稀疏矩阵 ​

r
library(Seurat)
project <- normalizePath("~/sc-course", mustWork = TRUE)
input <- file.path(project, "data/raw/filtered_gene_bc_matrices/hg19")
counts <- Read10X(data.dir = input)
class(counts)
dim(counts)
head(rownames(counts))
head(colnames(counts))
stopifnot(!anyDuplicated(colnames(counts)))

本例原始矩阵是 32,738 行、2,700 列。行是基因,列是条形码。大量零值由稀疏矩阵结构保存,不要为了看前几行就执行 as.matrix(counts) 把整个对象展开。查看局部可以用:

r
counts[1:5, 1:4]

Read10X 默认使用基因名称列并处理重复名称。记录数据版本后再解释名称;本例不能与另一个参考的 Ensembl ID 列按当前位置拼接。

新数据如果包含 Gene Expression 和 Antibody Capture 等特征,Read10X 可能返回列表。这时先 names(counts),再选 counts[["Gene Expression"]] 建 RNA 对象。本教程脚本会对意外的列表停止,避免把多模态输入默默当成单一 RNA。

建立对象,分清两次筛选 ​

r
pbmc <- CreateSeuratObject(
  counts = counts,
  project = "pbmc3k",
  min.cells = 3,
  min.features = 200
)
dim(pbmc)
head(pbmc[[]])

min.cells = 3 过滤只在很少细胞中检出的基因;min.features = 200 是创建对象时对细胞的初筛。二者分别作用于基因和细胞,不要都解释成“过滤低质量细胞”。

nCount_RNA 是每个细胞在该 assay 的计数总和,nFeature_RNA 是非零基因数。它们不是 FASTQ 的 reads 数。初筛后剩下多少基因,以本次 01-import-summary.csv 为准,不拿“约三千细胞”当作所有维度的预期。

本次 R 4.3.3 / Seurat 5.0.1 实测:矩阵为 32,738 × 2,700,建对象后为 13,714 × 2,700。脚本日志中的 Feature names cannot have underscores 是 Seurat 将特征名中的下划线替换成短横线的提示;记录这一步名称变化,不必回去修改原始矩阵文件。

添加能够追溯来源的字段 ​

r
pbmc$sample_id <- "pbmc3k"
pbmc$donor_id <- "healthy_donor_1"
pbmc$reference <- "hg19_10x_cellranger_1.1.0"
table(pbmc$sample_id)
table(pbmc$donor_id)
stopifnot(identical(rownames(pbmc[[]]), colnames(pbmc)))

这里的来源信息与练习包 configs/samples.tsv 一致。真实项目应从正式样本表读取,不要批量给所有细胞套同一个供体编号。

把 CSV 元数据加入对象时,先按条形码匹配,不能默认文件当前行序与对象列序相同。例如:

r
meta <- pbmc[[]]
meta <- meta[match(colnames(pbmc), rownames(meta)), , drop = FALSE]
stopifnot(!anyNA(rownames(meta)))
stopifnot(identical(rownames(meta), colnames(pbmc)))

此处拿对象自身的元数据演示对齐。换成外部文件时,还需检查匹配失败、重复条形码与样本命名规则。条形码只有在限定实验或样本后才有意义,不是全球唯一 ID。

保存检查点,再重新打开 ​

r
saveRDS(pbmc, file.path(project, "results/01-imported.rds"))
reloaded <- readRDS(file.path(project, "results/01-imported.rds"))
stopifnot(identical(dim(pbmc), dim(reloaded)))
stopifnot(identical(colnames(pbmc), colnames(reloaded)))

RDS 保存对象,不保存整台机器的环境。版本信息由脚本另存到 logs/01-import-session.txt,两者一起保留。原始矩阵留在 data/raw/,后续只改对象,不直接编辑原始 TSV。

这个阶段最容易看错的结果 ​

现象判断与处理
对象基因数比 32,738 少检查 min.cells 初筛记录,不先认定文件损坏
列数与报告不一致核对样本、raw/filtered、是否拆过样本,再看 min.features
一个基因都对不上常见 symbol检查使用了哪个特征列、物种与参考,不先把表达值改成零
多个样本出现同名条形码合并前加可追溯的样本前缀,保留原始 ID 对照

练习:把 min.cells 暂改为 5,另存为不同文件,观察改变的是行数还是列数。完成后仍使用原始脚本产物进入质控。

接口依据:Read10X、CreateSeuratObject。