FindVariableFeatures 函数总览与参数列表
做单细胞分析,第一步往往是筛选高变基因。为什么这步这么重要?说白了,不是每个基因都值得你花时间去分析。
一个细胞里测到的基因可能有上万个,但大部分基因的表达量都很“平淡”——所有细胞里都差不多。真正能帮你区分细胞类型、发现稀有亚群的,往往是那几百个“个性鲜明”的基因。FindVariableFeatures,就是帮我们把这类基因找出来的函数。
我个人习惯把它叫做「特征基因筛选器」。它输出的结果,直接决定了后续 PCA、聚类能否有效。我在项目中遇到过不少案例,因为筛选参数没调好,结果聚类出来一团模糊,换了一组参数才把稀有细胞群给“挖”出来。
函数的“长相”与基本用法
先看一下 FindVariableFeatures 的标准用例如下:
# 最简单的调用
seurat_obj <- FindVariableFeatures(seurat_obj)
# 手动指定参数
seurat_obj <- FindVariableFeatures(
seurat_obj,
selection.method = "vst",
nfeatures = 2000,
mean.cutoff = c(0.1, 8),
dispersion.cutoff = c(1, Inf)
)
嗯,这里要注意。当你只写 seurat_obj <- FindVariableFeatures(seurat_obj) 时,Seurat 用的是默认参数。对大多数 10x Genomics 数据,这个默认配置确实能工作。但我建议你不要直接“闭眼跑”——理解这些参数的意义,才能应对不同数据集的异常情况。
参数全貌一览表
下面这个表,我总结了所有核心参数。你把它当成一份「速查手册」就行:
| 参数名 | 类型 | 默认值 | 作用简述 |
|---|---|---|---|
selection.method |
字符型 | "vst" | 选择高变基因的算法:vst / mean.var.plot / disp |
nfeatures |
整型 | 2000 | 最终选出的高变基因数量 |
mean.cutoff |
数值向量 | c(0.1, 8) | 平均表达量的筛选区间(下限,上限) |
dispersion.cutoff |
数值向量 | c(1, Inf) | 离散度的筛选区间(下限,上限) |
binning.method |
字符型 | "equal_width" | 数据分箱方式:equal_width / equal_frequency |
num.bin |
整型 | 20 | 分箱数量,影响标准化过程 |
verbose |
逻辑型 | TRUE | 是否打印运行过程中的提示信息 |
三个选择方法到底怎么选?
这里我想重点聊一下 selection.method,因为它直接决定了筛选逻辑。Seurat 提供了三个选项:
- "vst"(默认):基于方差稳定化变换。它是目前最稳定的方法,能有效降低测序深度差异对基因方差的影响。我个人的首选。
- "mean.var.plot":基于平均表达量和方差的均质散点图。这个方法更“传统”,但容易出现因为批次效应导致的假阳性。
- "disp":基于离散度排序。计算最快,但不太稳定。如果你只是想快速跑一个初探结果,可以用它。
你可能会问:“vst 这么好,为什么不直接用它到底?”嗯,这里有个坑。vst 方法对内存消耗比较大,当你的数据量超过几万个细胞时,可能会比较慢。我曾经在一台 16GB 内存的笔记本上跑 6 万个细胞的 vst 筛选,结果卡了半小时…后来换成 mean.var.plot 才跑动。
nfeatures:选多少才够?
默认值是 2000。这其实是个经验值。为什么是 2000?
- SCTransform 等更先进的归一化方法,会直接默认 3000 或 5000。
- 如果你的细胞类型很复杂(比如包含多种罕见亚群),我建议增加到 3000-4000。
- 反之,如果你只关心主要细胞类型(比如 T 细胞 vs B 细胞),1000-1500 也许就够了。
分箱参数:binning 和 num.bin
这两个参数不太起眼,但很关键。它们控制的是数据在计算变异系数前如何“分组”。
- binning.method = "equal_width":按表达量的绝对数值等距分箱。适合数据分布比较均匀的情况。
- binning.method = "equal_frequency":按表达量的分位数等频分箱。适合数据长尾分布严重时使用。
- num.bin:分箱数量。默认 20。如果数据噪声大,可以适当增加到 30-40。
我记得刚开始做单细胞分析时,遇到过一个样品,它的表达量分布特别“拉胯”——大部分基因表达量极低,少数基因极高。用默认的 equal_width 分箱,结果高变基因列表里全是那几个高表达的管家基因。后来改成 equal_frequency,才真正找出了有细胞类型特异性的基因。
本章知识体系总览
下面这张 SVH 图,我把 FindVariableFeatures 的整个参数体系画成了一个决策流程图。你可以把它当作一个“参数调优的导航地图”:
小结:参数之间的“化学反应”
这几个参数不是独立工作的。举个例子:
- selection.method 决定了一开始的“方差计算逻辑”。
- nfeatures 是最终输出基因数量的“天花板”。
- mean.cutoff 和 dispersion.cutoff 是套在天花板上面的“双重筛选器”——只有同时满足两个条件的基因才能入选。
- binning 参数影响在不同表达量区间内,变异排名的公平性。分箱不合理,某些区域的基因可能被系统性低估。
我曾经在一个包含肿瘤浸润免疫细胞的项目中,发现默认参数筛出的高变基因里,有一半都是热休克蛋白家族(HSPs)这类应激相关基因。这其实掩盖了真正的免疫细胞亚群差异。后来我把 mean.cutoff 的上限从 8 降到 6,把 disp.cutoff 的下限从 1 提高到 1.5,才把那些真正有生物意义的基因筛选出来。
VariableFeatures(seurat_obj) 看看实际选出了多少基因。我见过很多人设置 nfeatures=2000,结果因为 cutoff 太严格,最后实际只选了不到 800 个。反过来,cutoff 太宽松也可能突破 nfeatures 的上限——当然,Seurat 会帮你截断,但截断时通常是按排名来的,可能会丢失一些你真正需要的基因。
参数调优不是一锤子买卖。我习惯的做法是:先用默认参数跑一次,然后用 VariableFeaturePlot 可视化检查选出的基因分布。如果发现大量基因聚集在低表达区域,或者高表达区域出现明显的截断现象,大概率是 cutoff 设置不合理。调整后再跑一次,直到分布看起来“自然”。
这一章我们把这些参数的结构理清了。后面几章,我会手把手带你实操,用真实数据集把每个参数的效果“看”出来。嗯,先消化完这张参数地图,我们后续再聊细节。