Seurat对象子集化时sample函数的异常行为求助
Seurat包子集化时
sample函数重复输出的问题解析 问题现象
使用R语言Seurat包处理单细胞对象时,遇到如下异常:
- 提前生成随机细胞ID,再通过
[]子集化,能得到不同的细胞集合,符合预期; - 直接在
[]子集化语句中调用sample函数,多次执行得到的子集完全相同,且不受随机种子影响。
复现步骤
1. 预生成随机ID子集(正常情况)
library(Seurat) set.seed(12345) ten_cells_id <- sample(Cells(pbmc_small), 10) other_ten_ids <- sample(Cells(pbmc_small), 10) and_other_ten <- sample(Cells(pbmc_small), 10)
执行子集化后查看细胞标签,三组结果各不相同:
> Cells(pbmc_small[, ten_cells_id]) [1] "CATGAGACACGGGA" "CGTAGCCTGTATGC" "ACTCGCACGAAAGT" "CTAGGTGATGGTTG" "TTACGTACGTTCAG" "CATGGCCTGTGCAT" [7] "ACAGGTACTGGTGT" "AATGTTGACAGTCA" "GATAGAGAAGGGTG" "CATTACACCAACTG" > Cells(pbmc_small[, other_ten_ids]) [1] "GGCATATGCTTATC" "ACAGGTACTGGTGT" "CATCAGGATGCACA" "ATGCCAGAACGACT" "GAGTTGTGGTAGCT" "GGCATATGGGGAGT" [7] "AGAGATGATCTCGC" "GAACCTGATGAACC" "GATATAACACGCAT" "CATGAGACACGGGA" > Cells(pbmc_small[, and_other_ten]) [1] "GGGTAACTCTAGTG" "TTTAGCTGTACTCT" "TACATCACGCTAAC" "CTAAACCTGTGCAT" "ATACCACTCTAAGC" "CATGCGCTAGTCAC" [7] "GATAGAGAAGGGTG" "ATTACCTGCCTTAT" "GCGCATCTTGCTCC" "ACAGGTACTGGTGT"
2. 直接在子集化中调用sample(异常情况)
cells1 <- pbmc_small[, sample(Cells(pbmc_small), 10)] cells2 <- pbmc_small[, sample(Cells(pbmc_small), 10)] cells3 <- pbmc_small[, sample(Cells(pbmc_small), 10)] Cells(cells1) Cells(cells2) Cells(cells3)
三次执行结果完全一致:
> Cells(cells1) [1] "GATAGAGATCACGA" "GGCATATGCTTATC" "ATGCCAGAACGACT" "AGATATACCCGTAA" "TACAATGATGCTAG" "CATGAGACACGGGA" [7] "GCACTAGACCTTTA" "CGTAGCCTGTATGC" "TTACCATGAATCGC" "ATAAGTTGGTACGT" > Cells(cells2) [1] "GATAGAGATCACGA" "GGCATATGCTTATC" "ATGCCAGAACGACT" "AGATATACCCGTAA" "TACAATGATGCTAG" "CATGAGACACGGGA" [7] "GCACTAGACCTTTA" "CGTAGCCTGTATGC" "TTACCATGAATCGC" "ATAAGTTGGTACGT" > Cells(cells3) [1] "GATAGAGATCACGA" "GGCATATGCTTATC" "ATGCCAGAACGACT" "AGATATACCCGTAA" "TACAATGATGCTAG" "CATGAGACACGGGA" [7] "GCACTAGACCTTTA" "CGTAGCCTGTATGC" "TTACCATGAATCGC" "ATAAGTTGGTACGT"
原因分析
问题根源在于Seurat包重载了R原生的[]运算符(即实现了[.Seurat方法):
- Seurat的子集化方法在处理列(细胞)索引时,会对输入的表达式做额外的验证与标准化处理(比如转换为匹配细胞名的字符向量/逻辑向量);
- 当直接传入
sample(Cells(pbmc_small),10)这类动态表达式时,sample函数的求值时机被延迟到Seurat内部处理流程中,该流程可能重置了随机种子,或由于内部状态固定,导致每次sample调用都使用相同的随机初始状态,最终生成完全一致的结果; - 提前将
sample结果赋值给变量时,变量存储的是已生成的固定字符向量,子集化时直接使用该向量,自然不会触发上述问题。
而普通向量的[]是R原生实现,不会做额外处理,因此直接调用sample能正常生成随机结果。
解决方案
有两种方式可以避免这个问题:
- 提前将
sample的结果赋值给变量,再传入子集化语句(即第一种正常情况的做法); - 手动强制
sample表达式提前求值,用括号包裹:
cells1 <- pbmc_small[, (sample(Cells(pbmc_small), 10))] cells2 <- pbmc_small[, (sample(Cells(pbmc_small), 10))]
这样sample会在Seurat的子集化方法处理前完成求值,生成不同的随机细胞子集。
内容的提问来源于stack exchange,提问作者nico
相关产品推荐
相关产品推荐

