2. 单细胞转录组数据简介与批次问题归纳总结

说实话,刚接触单细胞转录组的人,第一反应往往是——“这玩意儿数据量也太大了吧?”

单细胞转录组测序(scRNA-seq),说白了就是在单个细胞分辨率下,看每个细胞里哪些基因在表达。听起来挺简单,但背后涉及到的实验、测序、数据处理,一环扣一环。我刚开始跑第一个单细胞项目时,还以为是像 bulk RNA-seq 那样直接扔进 DESeq2 就完事了。结果一跑出来,UMAP 图上全是黑漆漆的簇,根本分不清是生物学差异还是批次效应。

今天我们就来捋清楚单细胞数据的基本结构,以及最让人头疼的「批次效应」到底是个什么鬼。

2.1 单细胞转录组数据长什么样?

一个典型的 scRNA-seq 实验,最终会生成一个巨大的矩阵。矩阵的行是基因(大约两万多个),列是细胞(几千到几十万)。矩阵里的每个数值,代表某个基因在某个细胞中检测到的转录本数——通常用 UMI 计数。

为什么用 UMI?我曾在一次项目里用过传统 read 计数,结果两个相同表达的基因,因为 PCR 扩增偏差,计数直接差了三倍。后来换成 UMI 才回归正常。UMI(Unique Molecular Identifier)相当于每个转录本的“身份证号”,能消除 PCR 重复带来的偏差。

实用习惯:拿到原始数据后,我第一个动作永远是检查 UMI 占比。UMI 比例低于 60% 的样本,大概率扩增过深,后面纠偏会非常麻烦。

看一个典型的数据矩阵示例:

                 Cell1   Cell2   Cell3   Cell4
Gene_ACTB           120       3     450      21
Gene_GAPDH         2300      56    1200      89
Gene_MALAT1         12       0      23       1
...

每一列是一个细胞,每一行是一个基因。数值是整数,0 代表该基因在当前细胞中没有被检测到。单细胞数据特别稀疏(sparse),一般 80%~95% 的数值是 0。

处理这种稀疏矩阵,我习惯用稀疏格式存储(比如 scipy.sparse.csr_matrix),内存能省 5~10 倍。不然几十万细胞的数据,光加载就能把 128GB 内存吃掉。

2.2 数据预处理管线

拿到 count 矩阵后,通常要走几步预处理:

  • 质控过滤:去除死细胞、双细胞、空液滴。常用指标是基因数、UMI 总数、线粒体基因占比。
  • 标准化:让不同细胞的表达量可比。常见做法是每细胞总 UMI 缩放到 10000,再取 log1p。
  • 特征选择:挑出高变基因(highly variable genes),一般挑 2000~5000 个就够了。我遇到过有人用全部基因做降维,UMAP 跑了两小时还不收敛。
  • 降维:PCA 做主成分分析,然后可以接 UMAP/t-SNE 做可视化。
  • 聚类与注释:用 Louvain/Leiden 算法分群,再根据 marker 基因标注细胞类型。

但这一套流程里,有一个最大的暗坑——批次效应。

2.3 批次效应:从哪来?

批次效应的本质,就是非生物学因素引入的系统性差异。同一个细胞类型,在不同批次里测出来表达谱可能有明显偏移。

我记得有一次做人类外周血样本,早上一批、下午一批,结果早上的 T 细胞和下午的 T 细胞在 UMAP 上直接分成了两堆。后来排查才发现,早上用的试剂盒批号跟下午不一样。

常见批次效应来源:

来源典型表现真实案例
试剂批次反转录酶、建库试剂质量差异两个批次的试剂,UMI 中位数相差 30%
操作者差异不同实验人员加样、裂解手法不同某实验室两个学生做同一组织,细胞回收率差 2 倍
测序深度不同文库测序 reads 数不同一批 5 万 reads/细胞,另一批 2 万
测序平台HiSeq vs NovaSeq,读长、错误率不同两个平台对低表达基因的检出率差 15%
时间/环境实验日期、湿度、温度等环境因素冬夏两批同一组织,线粒体占比差 3%

看了这个表你就明白,批次效应其实很难完全避免。我们能做的,只能是在实验设计阶段就考虑进来——比如相同条件的样本交叉分配到不同批次,而不是一锅端。

2.4 批次效应对下游分析的影响

如果不做批次校正,下游分析会得出错误结论。最典型的三种情况:

  • 错误聚类:本来相同的细胞类型,被批次分开,导致你以为找到了「新亚型」。
  • 差异表达假阳性:同一个细胞类型,在两个批次间检出几百个差异基因,其实都是实验噪音。
  • 轨迹推断失真:拟时序分析会把批次本身的差异误判为分化路径的中间状态。

我见过一篇预印本,作者在同一个样本上跑了两次测序,然后用常规数据流程分析,结果两次跑出来居然说是「不同发育阶段」——说白了就是批次效应没处理好。

避坑指南:我曾经犯过一次错——把同一个个体的肿瘤和正常组织分开两个批次测,然后想通过比较找肿瘤标志物。正常批次和肿瘤批次的差异有一部分是批次效应,差点把一批 RNA 降解导致的低表达基因当成肿瘤抑制基因。后来我强行塞了十个对照样本再分析,才没出丑。

2.5 批次问题在 GNN 框架中的定位

既然单细胞数据天然有批次问题,那我们课程里为什么要用 GNN 来做质控?因为传统方法(如 Harmony、ComBat、Seurat 的 CCA 整合)本质上是全局线性变换,但很多批次效应是非线性的、局部的。GNN 可以直接在图结构上学习和修正这种局部偏移。

接下来的章节我们会一步步搭建 GNN 模型,但首先得把批次问题的画像弄清楚。

单细胞数据批次问题来源与影响 单细胞表达矩阵 实验批次差异 试剂/平台差异 操作者/时间差异 测序深度差异 错误聚类 差异表达假阳性 轨迹推断失真 GNN 思路:在图结构中学习并修正局部、非线性的批次效应

2.6 如何记录和标注批次信息?

在实际项目中,批次信息一定要在进模型之前就整理好。我个人习惯用 pandas.DataFrame 维护一个 metadata 表格:

cell_barcode    batch    sample_id    tissue    condition
AAACCCAAG-1     B01      S1           Tumor     Treatment
AAACCCACA-1     B02      S2           Normal    Control
AAACCCATT-1     B01      S3           Tumor     Treatment
...

bacth 列就是我们的目标变量。GNN 做无监督或自监督学习时,可以利用 batch 信息构建对比损失,迫使不同批次的相似细胞互相靠近。

还有一种常见做法:把 batch 当作节点特征中的 one-hot 向量一起喂给模型。不过要注意,如果模型太浅,可能学不到非线性校正。

2.7 章节小结

今天我们把单细胞数据底层的「计数矩阵」结构捋了一遍,也弄清楚了批次效应的来源和危害。说到最后你会发现,batch effect 就像一个幽灵,实验设计再小心也难免留下痕迹。而我们接下来要做的,就是用 GNN 这把新武器去捉住它。