use*_*855 7 r bioinformatics run-length-encoding bioconductor iranges
我有一个运行长度编码的向量,按顺序表示基因组上每个位置的一些值.作为一个玩具示例,假设我只有一条长度为10的染色体,那么我会看到一个矢量
library(GenomicRanges)
set.seed(1)
toyData = Rle(sample(1:3,10,replace=TRUE))
Run Code Online (Sandbox Code Playgroud)
我想将其强制转换为GRanges对象.我能想到的最好的是
gr = GRanges('toyChr',IRanges(cumsum(c(0,runLength(toyData)[-nrun(toyData)])),
width=runLength(toyData)),
toyData = runValue(toyData))
Run Code Online (Sandbox Code Playgroud)
哪个有效,但速度很慢.有没有更快的方法来构建同一个对象?
正如@TheUnfunCat 指出的,OP 的解决方案非常可靠。下面的解决方案仅比原始解决方案稍快一些。我尝试了几乎所有的组合,base R但都无法超越Rle该S4Vectors包的效率,因此我求助于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)
}
Run Code Online (Sandbox Code Playgroud)
该WhichDiffZero函数与中Rcpp的功能几乎完全相同。很大程度上归功于@G.Grothendieck。which(diff(v) != 0)base R
#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);
}
Run Code Online (Sandbox Code Playgroud)
以下是一些基准:
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
Run Code Online (Sandbox Code Playgroud)
过去几天我一直在断断续续地努力,但我绝对不满意。我希望有人能接受我所做的事情(因为这是一种不同的方法)并创造出更好的东西。
| 归档时间: |
|
| 查看次数: |
363 次 |
| 最近记录: |