繁体   English   中英

在C ++和Rcpp中重写慢速R函数

[英]Rewriting slow R function in C++ & Rcpp

我有这行R代码:

croppedDNA <- completeDNA[,apply(completeDNA,2,function(x) any(c(FALSE,x[-length(x)]!=x[-1])))]

它的作用是识别DNA序列矩阵(1行= 1 seq)中非常规(信息性)的位点(cols),并将它们从矩阵中子集化以制作新的“裁剪矩阵”即摆脱所有值相同的列。 对于大数据集,这需要大约6秒。 我不知道我是否可以在C ++中更快地完成它(仍然是C ++中的初学者),但尝试它对我有好处。 我的想法是使用Rcpp,循环遍历CharacterMatrix的列,拉出列(站点)作为CharacterVector检查它们是否相同。 如果它们相同,则记录该列号/索引,对所有列继续。 然后在最后创建一个只包含那些列的新CharacterMatrix。 重要的是我保持rownames和列名称,因为它们在矩阵的“R版本”中,即如果列,则colname也应如此。

我已经写了大约两分钟,到目前为止我所拥有的(未完成):

#include <Rcpp.h>
#include <vector>
using namespace Rcpp;
// [[Rcpp::export]]
CharacterMatrix reduce_sequences(CharacterMatrix completeDNA)
{
  std::vector<bool> informativeSites; 
  for(int i = 0; i < completeDNA.ncol(); i++)
  {
    CharacterVector bpsite = completeDNA(,i);
    if(all(bpsite == bpsite[1])
    {
      informativeSites.push_back(i);
    }
  }
CharacterMatrix cutDNA = completeDNA(,informativeSites);
return cutDNA;
}

我对此有正确的解决方法吗? 有没有更简单的方法。 我的理解是我需要std :: vector因为它很容易长大(因为我事先并不知道我要保留多少cols)。 有了索引,我需要在最后给信息站点向量+1(因为R索引来自1而C ++来自0)?

谢谢,本W.

样本数据:

set.seed(123)
z <- matrix(sample(c("a", "t", "c", "g", "N", "-"), 3*398508, TRUE), 3, 398508)

OP的解决方案:

system.time(y1 <- z[,apply(z,2,function(x) any(c(FALSE,x[-length(x)]!=x[-1])))])
#    user  system elapsed 
#   4.929   0.043   4.976 

使用基数R的更快版本:

system.time(y2 <- (z[, colSums(z[-1,] != z[-nrow(z), ]) > 0]))
#    user  system elapsed 
#   0.087   0.011   0.098 

结果完全相同:

identical(y1, y2)
# [1] TRUE

c ++很可能会击败它,但它真的有必要吗?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM