跳到正文
百沐一下百沐一下
本节目录

单细胞质控三指标怎么设阈值

跟完这篇,您能针对自己的单细胞数据,看着分布把 nFeature_RNA、nCount_RNA、线粒体比例三条质控线定下来,滤掉低质量细胞和双细胞,又不至于把真实细胞群一起滤掉。

单细胞下游的聚类、注释、差异,都建立在「留下来的每个细胞都是一个健康的、单个的细胞」这个前提上。质控就是把不满足这个前提的液滴挑出去。整篇按这条线走:

  1. 读入数据,算出三个质控指标(含线粒体比例);
  2. 画分布图,看着自己的分布定三条阈值线;
  3. 用专门方法补处理双细胞与空液滴;
  4. 过滤,再回头检查有没有滤过头。

三个指标各反映什么

先弄清这三个数分别在说什么,才谈得上怎么卡:

指标含义太低说明太高说明
nFeature_RNA这个细胞里检测到的基因数空液滴、破损细胞、低质量疑似双细胞(两个细胞挤进一个液滴)
nCount_RNA这个细胞里的 UMI 总数(总转录本数)建库效率低、细胞将死疑似双细胞或超大细胞
percent.mt线粒体基因占总表达的百分比——细胞膜破裂、胞质 mRNA 漏出、细胞将死

三者背后其实是同一件事的不同侧面:

  • nFeature_RNA 和 nCount_RNA 高度相关,一般一起看。两头都要留意:太低多半是没装进完整细胞,太高常是一个液滴里裹了两个细胞。
  • 线粒体比例是「细胞死没死」的信号灯。细胞破裂时,胞质里的 mRNA 先漏出去,线粒体因为有膜包着相对留存,于是线粒体转录本的占比被动升高。所以线粒体比例高,通常代表这是个正在死亡或已受损的细胞。

读入数据、把线粒体比例算出来

nFeature_RNA 和 nCount_RNA 在 Seurat 建对象时会自动算好,线粒体比例要自己按基因名前缀统计。先把矩阵读进来、建立对象:

library(Seurat)

# 读入 10x 的三件套(barcodes / features / matrix 同放一个目录)
counts <- Read10X(data.dir = "filtered_feature_bc_matrix/")
# 若拿到的是 .h5,改用 Read10X_h5("filtered_feature_bc_matrix.h5")

# 建对象时先做一道最粗的过滤:
#   min.cells    —— 基因至少在这么多细胞里出现,才保留
#   min.features —— 细胞至少测到这么多基因,才保留
# 3 和 200 是 Seurat 教程常用起点,属于惯例,按数据调、不是铁律
seu <- CreateSeuratObject(
  counts       = counts,
  project      = "my_sample",
  min.cells    = 3,
  min.features = 200
)

再按基因名前缀算线粒体比例。人类线粒体基因以 MT- 开头,小鼠是 mt-别搞混物种

# 人类:以 MT- 开头的基因即线粒体基因
seu[["percent.mt"]] <- PercentageFeatureSet(seu, pattern = "^MT-")

# 小鼠请改成小写前缀
# seu[["percent.mt"]] <- PercentageFeatureSet(seu, pattern = "^mt-")

算完 percent.mt 会作为一列存进对象的 meta.data,和 nFeature_RNA、nCount_RNA 并列,后面一起看分布、一起做过滤。

提示:如果画出来 percent.mt 几乎全是 0,多半是前缀写错了(物种不对,或参考基因组里线粒体基因用了别的命名)。先回去核对基因名,别急着往下走。

看分布、按分布定阈值

**最关键的一条:阈值要看着自己数据的分布定,不要照抄别人教程里的数字。**同样是「线粒体 < 10%」,放在 PBMC 上很合理,放在心肌、肝脏这类线粒体本就丰富的组织上就会把好细胞误杀。做法是先画三张小提琴图,看清分布再下刀:

VlnPlot(seu,
        features = c("nFeature_RNA", "nCount_RNA", "percent.mt"),
        ncol = 3, pt.size = 0)

# 配合散点图看两两关系,帮助判断上界
FeatureScatter(seu, "nCount_RNA", "percent.mt")
FeatureScatter(seu, "nCount_RNA", "nFeature_RNA")

看图时按这个思路找拐点:

  1. 主群体在哪:小提琴的「肚子」是绝大多数正常细胞所在区间,阈值应落在肚子之外的稀疏尾巴上,而不是切进主群体。
  2. 下界(去空液滴、碎片):nFeature_RNA 在低端往往有一小撮离群点,把它们和主群分开的那条缝,就是下界的候选位置。
  3. 上界(防双细胞):nFeature_RNA / nCount_RNA 特别高的一小撮,疑似双细胞。上界可以先松一点,把真正的双细胞交给下一节的专门方法处理,避免误伤真实的大细胞。
  4. 线粒体上界:看 percent.mt 小提琴的主群体延伸到哪,再往上留一点余量设界。

一组常被引用的起点值(源自 Seurat 官方 PBMC 教程,仅供参照,不是标准答案):

指标PBMC 教程用的起点说明
nFeature_RNA 下界> 200低于此多为空液滴 / 碎片
nFeature_RNA 上界< 2500仅 PBMC 情形,别硬套
percent.mt 上界< 5免疫细胞可用,其它组织常需放宽

这些都是常用惯例、不是铁律。线粒体阈值尤其要因组织而异——同一条 < 10% 换个组织就可能太严或太松:

组织 / 样本类型线粒体比例常用上界为什么
PBMC、外周血免疫细胞< 5%〜10%代谢平缓,线粒体占比本就低
多数培养细胞系、常规实体组织< 10%〜20%折中区间,看尾巴切
心肌、骨骼肌、肝、肾< 20% 甚至更高线粒体天生丰富,卡太严会误杀好细胞

单核 vs 单细胞、新鲜 vs 冻存样本也会整体平移分布,同一套阈值未必能跨样本通用。一个稳妥的习惯:阈值大致在看分布时定好就别反复微调到「结果好看」,并把最终数字写进方法学,保证可复现。

处理双细胞与空液滴

nFeature 的上界只能挡住最粗的双细胞。下面两类问题需要专门的方法,别指望三条阈值线包办。

双细胞(doublet)——两个细胞进了同一个液滴,被当成一个「表达谱混合」的细胞,容易在聚类里冒充「中间态」新群,是假发现的高发来源。常用工具的共同思路都是:造一批人工双细胞当参照,再看每个真实细胞长得有多像双细胞。

工具语言特点
DoubletFinderR与 Seurat 流程衔接顺,需先扫 pK 参数
scDblFinderR(Bioconductor)较新、较快,一步打分
ScrubletPythonscanpy 生态常用

这类方法要在标准降维聚类跑完之后做:

# 前置:NormalizeData → FindVariableFeatures → ScaleData →
#       RunPCA → RunUMAP → FindClusters 已跑完
library(DoubletFinder)

# 预期双细胞数 = 双细胞率 × 细胞数
# 10x 的经验规律:装载越多,双细胞率越高(约每千个细胞增加不到 1%),
# 具体比率请以试剂 / 仪器说明为准
nExp <- round(0.075 * ncol(seu))   # 例:约 7.5%,按实际细胞数换算

DoubletFinder 还需要先用 paramSweep 系列函数扫出最优 pK 再正式运行,且函数名(是否带 _v3 后缀)随包版本变化。这里只给到思路和关键参数,具体调用请对照您所装版本的官方文档,不要照抄固定的函数签名。

空液滴(empty droplet)——液滴里没有细胞、只有环境游离 RNA(ambient RNA)。如果您用的是 CellRanger 输出的 filtered 矩阵,这一步 CellRanger 已经替您做过初筛;若从 raw(未过滤)矩阵起步,可用 DropletUtils 包的 emptyDrops() 区分真细胞与空液滴。环境 RNA 的污染另有 SoupX、DecontX 等工具校正,属于进阶步骤,按需再引入。

过滤,并检查有没有滤过头

阈值定好后用一行 subset() 过滤。三条线用 & 串起来(下面的数字只是示例,请换成您自己看分布定的值):

seu.filt <- subset(
  seu,
  subset = nFeature_RNA > 200 &
           nFeature_RNA < 2500 &
           percent.mt   < 10
)

**过滤最怕滤过头——把某个真实细胞群整片切掉却不自知。**过滤完一定要回头对一次账:

  1. 看留了多少:细胞数掉太多要警惕。

    ncol(seu)        # 过滤前
    ncol(seu.filt)   # 过滤后
    
  2. 重画小提琴图:确认尾巴被切掉、主群体完好无损。

    VlnPlot(seu.filt,
            features = c("nFeature_RNA", "nCount_RNA", "percent.mt"),
            ncol = 3, pt.size = 0)
    
  3. 分样本、分群体核对损耗是否均匀:如果某一个样本或某一群细胞被过滤掉了大半,往往不是「它们都是坏细胞」,而是阈值对这部分太严——比如把一个线粒体天然偏高的细胞类型整片误杀。这种不均匀的损耗,是需要回头放宽阈值的信号。

判断标准没有统一数字,但可以记住方向:宁可先松一点、多留一些边缘细胞,也别一刀切得太狠——低质量细胞在后续聚类里通常会自成一群、容易识别,而被误删的真实细胞群则再也找不回来了。过滤是可以迭代的:看完聚类结果,若发现某群明显是残余低质量细胞,再回来收紧对应指标即可。

在平台上跑一遍

百沐一下做这一步不用写代码:上传单细胞矩阵后,平台会自动算好 nFeature_RNA、nCount_RNA 与线粒体比例,画出三张分布图供您看着定阈值,并给出双细胞检测;您只需说清组织类型和大致意图,它会把过滤前后的细胞数与分布一并列出来让您确认没有滤过头。到 https://app.baimuyixia.com 传一份数据就能试跑,也可先看 组学智能体怎么用 了解交互方式。

相关