【问题标题】:Efficiently construct GRanges/IRanges from Rle vector从 Rle 向量有效地构造 Granges/IRanges
【发布时间】:2017-01-06 11:14:24
【问题描述】:

我有一个运行长度编码的向量,按顺序表示基因组上每个位置的某个值。作为一个玩具示例,假设我只有一条长度为 10 的染色体,那么我将有一个看起来像这样的向量

library(GenomicRanges)

set.seed(1)
toyData = Rle(sample(1:3,10,replace=TRUE))

我想将其强制转换为 Granges 对象。我能想到的最好的是

gr = GRanges('toyChr',IRanges(cumsum(c(0,runLength(toyData)[-nrun(toyData)])),
                              width=runLength(toyData)),
             toyData = runValue(toyData))

这可行,但速度很慢。有没有更快的方法来构造相同的对象?

【问题讨论】:

  • 您可以使用start(toyData)-1 来获取间隔的开始,但它不会提高速度。
  • @NicE 感谢您的提示,即使它不是更快,它也更清晰简洁。
  • start(toyData)-1>
  • @user1356855,您会遇到哪些典型的染色体长度?此外,在您的实际应用程序中,3 是否足够变化(例如,您可以拥有sample(1:15,10^8,replace=TRUE))吗?
  • @JosephWood 是的,与基因组数据一起存储的值通常是实数,所以 3 是不够的......但我几乎可以接受任何答案。最长的基因组:例如 247,249,719? Chr1 人类...

标签: r bioinformatics bioconductor run-length-encoding iranges


【解决方案1】:

正如@TheUnfunCat 指出的那样,OP 的解决方案非常可靠。下面的解决方案只比原始解决方案快一点。我几乎尝试了base R 的所有组合,但无法击败S4Vectors 包中的Rle 的效率,因此我求助于Rcpp。这是主要功能:

GenomeRcpp <- function(v) {
    x <- WhichDiffZero(v)
    m <- v[c(1L,x+1L)]
    s <- c(0L,x)
    e <- c(x,length(v))-1L
    GRanges('toyChr',IRanges(start = s, end = e), toyData = m)
}

WhichDiffZeroRcpp 函数,它与base R 中的which(diff(v) != 0) 几乎完全相同。很多功劳归于@G.Grothendieck

#include <Rcpp.h>
using namespace Rcpp;

// [[Rcpp::export]]
IntegerVector WhichDiffZero(IntegerVector x) {
    int nx = x.size()-1;
    std::vector<int> y;
    y.reserve(nx);
    for(int i = 0; i < nx; i++) {
        if (x[i] != x[i+1]) y.push_back(i+1);
    }
    return wrap(y);
}

以下是一些基准:

set.seed(437)
testData <- do.call(c,lapply(1:10^5, function(x) rep(sample(1:50, 1), sample(1:30, 1))))

microbenchmark(GenomeRcpp(testData), GenomeOrig(testData))
Unit: milliseconds
                expr      min       lq     mean   median       uq      max neval cld
GenomeRcpp(testData) 20.30118 22.45121 26.59644 24.62041 27.28459 198.9773   100   a
GenomeOrig(testData) 25.11047 27.12811 31.73180 28.96914 32.16538 225.1727   100   a

identical(GenomeRcpp(testData), GenomeOrig(testData))
[1] TRUE

在过去的几天里,我断断续续地处理这个问题,但我绝对不满意。我希望有人会采用我所做的(因为这是一种不同的方法)并创造出更好的东西。

【讨论】:

  • 这可能意味着 OP 元数据包含非矢量化数据?在 pandas 中可以使用“向量”中的对象,不知道 R...
  • 我不得不承认,我也不完全满意。看起来 GRanges 对象与 Rle 向量(对于一个染色体)非常相似,因此构建步骤应该基本上是即时的。相反,它是我的代码中最慢的部分。显然,我不太了解内部原理,无法知道为什么这是错误的/如何使其更快。 Rcpp 替代方案虽然很简洁,但确实提供了一些额外的速度。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-01-21
  • 2012-03-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-07
相关资源
最近更新 更多