从间隔列表中模拟随机位置

fug*_*ugu 2 simulation r bioinformatics bioconductor genomicranges

我试图在R中开发一个函数来输出给定间隔列表中的随机位置.

我的间隔文件(14,600行)是制表符分隔bed文件(chromosome start end name),如下所示:

1      4953    16204   1
1      16284   16612   1
1      16805   17086   1
1      18561   18757   1
1      18758   19040   1
1      19120   19445   1
Run Code Online (Sandbox Code Playgroud)

目前我的函数将N在这些间隔内生成随机位置.

sim_dat <- bpSim(N=10)
head(sim_dat)
Run Code Online (Sandbox Code Playgroud)
  seqnames    start      end width strand
1       1 22686939 22686939     1      *
2       1 14467770 14467770     1      *
3       2 10955472 10955472     1      *
4        X   823201   823201     1      *
5        6 10421738 10421738     1      *
6       17 21827745 21827745     1      *
Run Code Online (Sandbox Code Playgroud)
library(GenomicRanges)
library(rtracklayer)

bpSim <- function(intervals="intervals.bed", N=100, write=F) {
  intFile <- import.bed(intervals)
  space <- sum(width(intFile))
  positions <- sample(c(1:space), N)
  cat("Simulating", N, "breakpoints", sep = " ", "\n")
  new_b <- GRanges(
    seqnames = as.character(rep(seqnames(intFile), width(intFile))),
    ranges = IRanges(start = unlist(mapply(seq, from = start(intFile), to = end(intFile))), width = 1)
  )
  bedOut <- new_b[positions]
  if (write) {
    export.bed(new_b[positions], "simulatedBPs.bed")
  }
  remove(new_b)
  return(data.frame(bedOut))
}
Run Code Online (Sandbox Code Playgroud)

这是有效的,但是由于我对GenomicRanges软件包不是特别熟悉,所以我更喜欢将它们整合在一起.我更希望能够使用base R或package 重新编写它tidyverse,以便我可以调整它,例如,允许用户指定染色体.

它也需要很长时间 - 即使对于N=10:

system.time(sim_dat <- bpSim(N=10))
Simulating 10 breakpoints 
   user  system elapsed 
 10.689   3.267  13.970 
Run Code Online (Sandbox Code Playgroud)

最终,我试图模拟基因组中的随机位置,因此需要为每个数据模拟数百次N.

我非常感谢任何关于如何做的建议:

  • 减少运行时间
  • 不需要 GenomicRanges

另外 - 如果有人知道任何已经执行此操作的软件包,我宁愿使用现有的软件包而不是重新发明轮子.

caw*_*5cv 6

对于范围不同的长度,我假设您希望这些随机选择的位置与段的长度成比例.换句话说,基于范围内的实际碱基对,选择是均匀的.否则,您将过度表示小范围(较高的标记密度)和不足的大范围(较低的标记密度).

这是一个data.table解决方案,可以立即完成一千个站点,并在我的机器上大约10秒钟内完成一百万个随机站点.它随机采样您想要的站点数量,首先采样行(按每行的范围大小加权),然后在该范围内均匀采样.

library(data.table)

nSites <- 1e4

bed <- data.table(chromosome=1, start=c(100,1050,3600,4000,9050), end=c(1000,3000,3700,8000,20000))

# calculate size of range
bed[, size := 1 + end-start]

# Randomly sample bed file rows, proportional to the length of each range
simulated.sites <- bed[sample(.N, size=nSites, replace=TRUE, prob=bed$size)]

# Randomly sample uniformly within each chosen range
simulated.sites[, position := sample(start:end, size=1), by=1:dim(simulated.sites)[1]]

# Remove extra columns and format as needed
simulated.sites[, start  := position]
simulated.sites[, end := position]
simulated.sites[, c("size", "position") := NULL]
Run Code Online (Sandbox Code Playgroud)

这从一个表开始,例如:

 chromosome start   end  size
          1   100  1000   901
          1  1050  3000  1951
          1  3600  3700   101
          1  4000  8000  4001
          1  9050 20000 10951
Run Code Online (Sandbox Code Playgroud)

输出如下:

       chromosome start   end
    1:          1 10309 10309
    2:          1  4578  4578
    3:          1  1984  1984
    4:          1 14703 14703
    5:          1 10090 10090
   ---
 9996:          1  1601  1601
 9997:          1  5317  5317
 9998:          1 18918 18918
 9999:          1  1154  1154
10000:          1  7343  7343
Run Code Online (Sandbox Code Playgroud)