首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >R中向量的每个累积子集的优化计算

R中向量的每个累积子集的优化计算
EN

Stack Overflow用户
提问于 2017-09-19 05:25:30
回答 2查看 58关注 0票数 3

我收集了一组不同长度的DNA测序数据,从最长到最短。我想知道我可以在一个集合中包含的最大读取数,以便该集合的N50高于某个阈值t

对于任何给定的读取集,总数据量只是读取长度的累积之和。N50被定义为读取的长度,其中一半的数据包含在读取中,至少是那么长。

下面我有一个解决方案,但是对于非常大的阅读集,它是缓慢的。我尝试将其矢量化,但速度较慢(可能是因为我的阈值通常相对较大,因此下面的解决方案会在较早的时候停止计算)。

下面是一个有用的示例:

代码语言:javascript
复制
df = data.frame(l = 100:1) # read lengths
df$cs = cumsum(df$l) # getting the cumulative sum is easy and quick

t = 95 # let's imagine that this is my threshold N50

for(i in 1:nrow(df)){
    N50 = df$l[min(which(df$cs>df$cs[i]/2))]
    if(N50 < t){ break }
}

# the loop will have gone one too far, so I subtract one
number.of.reads = as.integer(i-1)

这在小数据集上很好,但我的实际数据更像是500万读取,长度从大约20万到1不等(较长的读取更少),我对10万的N50感兴趣,然后就会变得非常慢。

这个例子更接近现实。在我的台式机上需要15分钟。

代码语言:javascript
复制
l = ceiling(runif(100000, min = 0, max = 19999))
l = sort(l, decreasing = T)

df = data.frame(l = l)
df$cs = cumsum(df$l)

t = 18000

for(i in 1:nrow(df)){
    n = df$l[min(which(df$cs>df$cs[i]/2))]
    if(n < t){ break }
}

result = as.integer(i-1)

因此,我感兴趣的任何想法,提示,或诀窍,以显着优化这一点。看来这是可能的,但我没有主意了。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-09-19 14:42:34

随着ni的减少,您应该使用二进制搜索算法

代码语言:javascript
复制
binSearch <- function(min, max) {
  print(mid <- floor(mean(c(min, max))))
  if (mid == min) {
    if (df$l[min(which(df$cs>df$cs[min]/2))] < t) {
      return(min - 1)
    } else {
      return(max - 1)
    }
  }

  n = df$l[min(which(df$cs>df$cs[mid]/2))]
  if (n >= t) {
    return(binSearch(mid, max))
  } else {
    return(binSearch(min, mid))
  }
}

然后,打电话

代码语言:javascript
复制
binSearch(1, nrow(df))
票数 0
EN

Stack Overflow用户

发布于 2017-09-19 07:57:41

由于您的数据是按DNA/read长度排序的,所以您可以避免测试每一行。相反,您可以在每次迭代中迭代和测试有限数量的行(合理间距)(例如使用while() ),从而逐步接近您的解决方案。这应该会让事情变得更快。只要确保一旦接近解决方案,就不再迭代。

这是你的解决方案

代码语言:javascript
复制
set.seed(111)
l = ceiling(runif(100000, min = 0, max = 19999))
l = sort(l, decreasing = T)

df = data.frame(l = l)
df$cs = cumsum(df$l)

t = 18000

for(i in 1:nrow(df)){
  n = df$l[min(which(df$cs>df$cs[i]/2))]
  if(n < t){ break }
}

result = as.integer(i-1)
result 
# 21216, in ~29 seconds

而不是测试每一行,让我们设置一个范围

代码语言:javascript
复制
i1 <- 1
i2 <- nrow(df)
i.range <- as.integer(seq(i1, i2, length.out = 10))

现在,只测试这10行。通过重新定义范围,得到最接近的区域并“专注于”。当您不能增加粒度时停止。

代码语言:javascript
复制
while(sum(duplicated(i.range))==0){
  for(i in 1:length(i.range)){
    N50 = df$l[min(which(df$cs>df$cs[i.range[i]]/2))]
    if(N50 < t){ break }
  }

  #update i1 and i2
  i1 <- i.range[(i-1)]
  i2 <- i.range[i]
  i.range <- as.integer(seq(i1, i2, length.out = 10))

}

i.range <- seq(i1, i2, by=1)
for(i in i.range){
  N50 = df$l[min(which(df$cs>df$cs[i]/2))]
  if(N50 < t){ break }
}
result <- as.integer(i-1)
result 
#21216, in ~ 0.06 seconds

Same result in a fraction of the time.
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46292438

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档