You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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能正常生成随机结果。

解决方案

有两种方式可以避免这个问题:

  1. 提前将sample的结果赋值给变量,再传入子集化语句(即第一种正常情况的做法);
  2. 手动强制sample表达式提前求值,用括号包裹:
cells1 <- pbmc_small[, (sample(Cells(pbmc_small), 10))]
cells2 <- pbmc_small[, (sample(Cells(pbmc_small), 10))]

这样sample会在Seurat的子集化方法处理前完成求值,生成不同的随机细胞子集。

内容的提问来源于stack exchange,提问作者nico

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 22:10:29