第4章 细胞过滤策略:阈值设定与实操要点
过滤细胞,说白了就是扔掉那些“不合格”的细胞。你可能会问:凭什么判断一个细胞合不合格?
我从单细胞数据分析第一天起,最头疼的就是这一步。阈值设得太松,垃圾细胞进来,下游降维聚类直接跑偏;设得太严,稀有的亚群被误杀,后面找新细胞类型就彻底没戏。所以这一章,我把我这些年踩过的坑、总结的经验,统统摊开来讲。
4.1 三个核心指标:UMI总数、检测基因数、线粒体比例
判断一个细胞的质量好不好,主要看这三个数:
- UMI 总数:每个细胞捕获到的独特 mRNA 分子数。太高可能是双细胞(多个细胞粘在一起被当作一个),太低可能是细胞破裂或RNA降解。
- 检测基因数:每个细胞里至少检测到1个UMI的基因种类数。同理,太高可能是双细胞,太低可能是空液滴。
- 线粒体比例:线粒体基因UMI占全部UMI的百分比。比例高通常意味着细胞膜受损,mRNA泄漏,只剩线粒体内RNA还残留。
我当年做小鼠大脑皮层数据时,有一批细胞线粒体比例飙到30%以上,一开始以为是某种细胞亚型的特征,后来发现是样本处理时过度吹打导致细胞膜破损。你想想看,这种垃圾细胞如果混进降维,会硬生生拉出一个“高线粒体亚群”,特别容易误导人。
# 用Seurat计算这三个指标(示例)
pbmc[["percent.mt"]] <- PercentageFeatureSet(pbmc, pattern = "^MT-")
# 查看分布
VlnPlot(pbmc, features = c("nCount_RNA", "nFeature_RNA", "percent.mt"), ncol = 3)
4.2 阈值怎么定?——没有统一标准,但有通用公理
我知道你很想要一个万能的阈值公式。抱歉,没有。
阈值高度依赖组织类型、建库方法、测序深度。举个例子:10x 平台的人外周血 PBMC,一般 UMI 总数下限 500~1000,基因数下限 200~500,线粒体比例上限 5%~10%。但如果是肿瘤组织,RNA降解多,线粒体比例15% 的细胞可能仍然有生物学意义。
我的习惯是三步走:
- 先看原始分布图——画小提琴图和散点图,直观感受异常尾巴在哪。
- 设定保守的初筛阈值——用中位数加减若干个MAD(绝对中位差),而不是死板的固定数。
- 结合下游反馈迭代——跑一轮聚类后检查“中间群”是不是由低质量细胞驱动,再回来调阈值。
tips:我个人习惯用 MAD 替代标准差。UMI 分布常常有长尾,标准差会被极端值拉大,而 MAD 更稳健。代码:
lower <- median(nCount_RNA) - 3 * mad(nCount_RNA)
upper <- median(nCount_RNA) + 3 * mad(nCount_RNA)
4.3 常见坑与避雷指南
⚠️ 注意:不要同时设置上下限太紧。
我曾经有一个数据设定 UMI 总数上限 5000,结果丢弃了一群真实的髓系细胞(它们天然有多聚体 RNA)。后来发现那些细胞只是体积大、RNA 多,根本不是双细胞。正确做法是:先用 DoubletFinder 等软件检测双细胞,再把 UMI 上限放宽到 99% 分位数。
另一个经典错误:线粒体比例只设上限,不设下限。极少数情况(比如细胞质被完全抽空)下线粒体比例会接近 100%,但更多情况是线粒体比例 <1% 的细胞也有问题?其实是那些空液滴,几乎没有捕获到基因,线粒体基因自然也没几个,比例反而低。所以建议设一个更合理的条件:
# 合理的过滤条件(R伪代码)
keep_cells <- nCount_RNA > 500 &
nFeature_RNA > 200 &
percent.mt < 25
核心逻辑:三个指标要联动判断,不能只看单个指标。例如:一个细胞 UMI 总数很高但基因数也很高,并且线粒体比例正常,那很可能是正常的“高表达”细胞。但一个细胞 UMI 总数很低、基因数很低、线粒体比例却很高,这基本就是坏死细胞无疑。
4.4 不同场景的推荐阈值参考
| 组织/样本类型 | UMI总数下限 | UMI总数上限 | 检测基因数下限 | 线粒体比例上限 |
|---|---|---|---|---|
| 人PBMC(10x) | 500 | ~8000 | 200 | 10% |
| 小鼠脑组织(10x) | 400 | ~6000 | 150 | 15% |
| 肿瘤组织(snRNA-seq) | 300 | ~10000 | 100 | 20% |
| 空间转录组(Visium) | 1000 | ~15000 | 300 | 10% |
你看表格里的空间转录组,要求更高,因为每个 spot 包含多个细胞,UMI 总数天然更高。我遇到过空间数据用 PBMC 的阈值去过滤,结果一大半 spot 被清掉。所以一定要按实际平台调整。
4.5 可视化检查三件套
不要只信数字,一定要用图看一眼。我每次跑完过滤都会画下面三张图:
- 小提琴图:过滤前 vs 过滤后,看分布变化。
- UMI vs 基因数散点图:正常细胞应呈明显的正相关,如果出现低UMI但高基因数的点,可能是空液滴污染。
- 线粒体比例 vs UMI 散点图:线粒体比例高的细胞往往会聚集在低UMI区域,如果高UMI的细胞也有高线粒体比例,要警惕双细胞。
嗯,这里要注意:散点图的颜色可以用密度或类别来标记,否则几十万个点叠在一起根本看不清。
# Seurat散点图示例
FeatureScatter(pbmc, feature1 = "nCount_RNA", feature2 = "nFeature_RNA")
FeatureScatter(pbmc, feature1 = "nCount_RNA", feature2 = "percent.mt")
4.6 本章核心流程一览
下面这张图把整个细胞过滤的逻辑串起来了,你过滤之前一定在心里过一遍这个流程。
4.7 实战中的一点坚持
我从不把阈值写死成固定数值放在 pipeline 里。每个数据集我都会手动画图,看分布尾巴的位置。有些文章喜欢把阈值设定成“行业标准”,比如线粒体 < 5% 就是好,但我在坏死的脑组织切片中看到正常细胞都有 10% 以上,你一刀切下去,真正有用的细胞全死了。
另一个容易忽略的点:过滤完细胞之后,记得看一眼过滤掉的细胞有什么特征。用聚类后的细胞类型注释跟过滤掉的低质量细胞做对比,有时候会发现某种细胞只有高线粒体比例的状态(比如肝细胞在分离时更容易损伤)。这时候可能需要保留它们,但在下游差异分析中特殊处理。
经验之谈:一次过滤不要干掉超过30%的细胞。如果超过30%,大概率是你的样本质量不行,或者阈值太激进。先回去排除建库批次效应、组织解离方案的问题,再来调过滤参数。
好了,这一章就讲到这里。拿起你的数据,打开 Seurat 或 Scanpy,按照这个流程跑一遍,你会发现自己对数据的理解立刻不一样了。