【问题标题】:How to improve performance of custom function with manual vectorisation in R如何通过 R 中的手动矢量化来提高自定义函数的性能
【发布时间】:2019-04-25 16:24:15
【问题描述】:

我有两个数据框:df1 提供给定符号的坐标,df2 提供开始和结束坐标。我需要获取 df2 中每个开始和结束坐标之间的符号序列。

例如:

set.seed(1)
df1 <- data.frame(POS = 1:10000000,
              REF = sample(c("A", "T", "G", "C"), 10000000, replace = T))

df2 <- data.frame(start = sample(1:5000000, 10, replace = T),
                 end = sample(5000001:10000000, 10, replace = T))

我尝试过使用 for 循环:

system.time( {                
df2$seq <- NA
for(i in 1:nrow(coords)){
  df2$seq[i] <- paste(ref$REF [ c( which(ref$POS == coords$start[i]) : which(ref$POS == coords$end[i]) ) ], collapse = "")
}
})

并使用手动矢量化:

mongoose <- function(from, to){
  string <- paste(
    ref$REF [ c( which(ref$POS == from) : which(ref$POS == to) ) ],
    collapse = "")
  return(string)
}

mongoose_vec <- Vectorize(mongoose, vectorize.args = c("from", "to"))

system.time({
  sequences <- mongoose_vec(from = df2$start, to = df2$end)
  })

但是,这两种方法的执行速度相似,并且速度不够快,因为我应用它们的数据集非常大。有人对如何提高性能有任何建议吗?

【问题讨论】:

    标签: r performance vectorization


    【解决方案1】:

    Vectorize 不会显着加快您的任务,因为它只会减少开销,但大部分计算都在循环本身内。

    您可以采取的一种方法是将ref 存储为长字符串并使用substr 函数。

    ref2 <- paste0(ref$REF, collapse="")
    system.time({
    sequences2 <- sapply(1:nrow(coords), function(i) {
      substr(ref2, coords$start[i], coords$end[i])
    })
    })
    
    user  system elapsed 
      0.135   0.010   0.145 
    

    您的原始代码:

    system.time({
      sequences <- mongoose_vec(from = coords$start, to = coords$end)
    })
    
       user  system elapsed 
      7.914   0.534   8.461 
    

    结果是一样的:

    identical(sequences, sequences2) 
    TRUE
    

    PS:我假设df1refdf2coords

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-03-13
      • 2017-10-17
      • 1970-01-01
      • 1970-01-01
      • 2013-12-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多