首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使函数运行得更快一些,可以使用apply、stringr、stringr和rbind。

使函数运行得更快一些,可以使用apply、stringr、stringr和rbind。
EN

Stack Overflow用户
提问于 2018-12-13 22:55:48
回答 1查看 90关注 0票数 2

背景:--我将为该代码的应用程序和编程背景提供背景。希望双方都能帮上忙。我做基因组计算工作。是的-只是另一个假装成计算机科学家的生物学家。我正在编写一个脚本,它将允许我根据人类基因组中的每一个位置集成一组数据集。这将转换为12列超过30亿行的数据。作为一个测试数据集,我正在使用酵母基因组构建我的分析管道,它将生成一个包含大约2500万行和12列的数据。

问题:我的当前代码运行良好,但速度非常慢。例如,我45分钟前就开始了我的管道,大约是酵母基因组的1/3。这意味着完成一个酵母样本可能需要135分钟,或者一个人体样本需要270小时.现在乘以我准备分析的90个人体样本,你就能看到我的问题了。我得加快速度。我将对此进行并行化,但即使这样,我仍然认为代码本身太笨重了。我需要帮助使我现有的功能更快。请不要告诉我,我需要并行它(这将得到一个反对票)。

示例数据:

代码语言:javascript
复制
chrom <- c("chr1", "chr1", "chr1", "chr1")
start <- c("0","1","2","6")
stop <- c("1","2","6","7")
sequence <- c("a", "t", "tcag", "a")
seqData <- data.frame(chrom, start, stop, sequence)

示例输出:

代码语言:javascript
复制
chrom_out <- c("chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1")
start_out <- c("0", "1", "2", "3", "4", "5", "6")
stop_out <- c("1", "2", "3", "4", "5", "6", "7")
sequence_out <- c("a", "t", "t", "c", "a", "g", "a")
out_seqdata <- data.frame(chrom_out, start_out, stop_out, sequence_out)

当前代码:

代码语言:javascript
复制
library(dplyr)
library(stringi)
library(stringr) 


wl = function(x){

  length<- stri_length(x["sequence"])
  if(length ==1){
    tmpseq<- x["sequence"]
    tmpstart <- as.numeric(x["start"])
    tmpstop <- as.numeric(x["stop"])
    tmpchrom <- x["chrom"]
    tmpdf <- data.frame(tmpseq, tmpstart, tmpstop, tmpchrom)
    colnames(tmpdf)<- c("tmpseq", "tmpstart", "tmpstop", "tmpchrom")
    print(tmpdf)
  }else{
    tmpseq<- strsplit(x["sequence"], "(?<=.{1})", perl = TRUE)
    tmpstart <- as.numeric(x["start"])+(1:length-1)
    tmpstop<- as.numeric(x["start"])+(1:length)
    tmpdf <- data.frame(tmpseq, tmpstart, tmpstop)
    tmpdf$tmpchrom <- x["chrom"]
    colnames(tmpdf)<- c("tmpseq", "tmpstart", "tmpstop", "tmpchrom")
    print(tmpdf)
  }
}

代码说明:我使用的用于迭代数据文件的每一行。数据框架是坐标列表和这些坐标的基因组序列。Chrom =染色体,start =染色体上的起始位置,stop =停止位置,序列是实际的序列。数据目前采用压缩格式,以第三行数据为例。我想扩大这个数据,使每个基因组字母成为自己的行,然后适当地调整坐标范围。函数w(从宽到长)执行此操作。它首先确定序列的字符串长度。如果长度等于1,则将该行返回为dataframe,而无需进一步操作;否则,它会将字符串拆分为单独的字符,确定每个字符的坐标,并返回此dataframe。结果是一个数据列表,然后重新绑定在一起,生成示例输出数据。

我需要什么:,我要把基因组块,创建一个列表,这样我就可以并行化这个列表了。这些数据块将产生一系列长度约为2500万行的数据。我也要并行化多个样本。并行化中的并行化。听起来是个让集群崩溃的好方法。我知道如何做到这一点(编写这段代码并使集群崩溃)。我需要帮助的是使实际的功能更快。使用我的当前函数处理2500万行仍然需要很长时间。任何想法都将不胜感激。请编辑我的功能或推荐一个新的方法-所有的想法都欢迎。我不知道更快的方法,除了增加更多的马力。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-12-13 23:04:58

您可以将所有操作向量化:

代码语言:javascript
复制
# Generate vector of start positions
# Goes from 0 (minimal position in given data) to maximum base position in chromosome
foo <- 0:max(as.numeric(as.character(seqData$start)))
# Split sequence into a character vector
bar <- unlist(strsplit(as.character(seqData$sequence), ""))
# Generate final data frame
data.frame(start = foo, end = foo + 1, seq = bar)
#   start end seq
# 1     0   1   a
# 2     1   2   t
# 3     2   3   t
# 4     3   4   c
# 5     4   5   a
# 6     5   6   g
# 7     6   7   a

您可以使用此代码一次迭代一条染色体。

自定义函数和易于并行的foreach循环可能如下所示:

代码语言:javascript
复制
wl <- function(data, chr) {
    startPos <- 0:max(as.numeric(as.character(data$start)))
    nucs     <- unlist(strsplit(as.character(data$sequence), ""))
    data.frame(chr, start = startPos, end = startPos + 1, seq = nucs)
}
library(foreach)
# use dopar for parallel computations 
foreach(i = unique(seqData$chr), .combine = rbind) %do% {
    wl(subset(seqData, chrom == i), i)
}

PS:我不会使用基因组坐标作为字符向量。另外,创建end列只是浪费空间,因为您知道它是由start中的1来定位的。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53771243

复制
相关文章

相似问题

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