r语言 - 有效删除 NA 值



我需要有效地从使用 RcppEigen 实现的函数内的向量中删除NA值。我当然可以使用for循环来做到这一点,但我想知道是否有更有效的方法。

下面是一个示例:

library(RcppEigen)
library(inline)
incl <- '
using  Eigen::Map;
using  Eigen::VectorXd;
typedef  Map<VectorXd>  MapVecd;
'
body <- '
const MapVecd         x(as<MapVecd>(xx)), y(as<MapVecd>(yy));
VectorXd              x1(x), y1(y);
int                   k(0);
for (int i = 0; i < x.rows(); ++i) {
 if (x.coeff(i)==x.coeff(i) && y.coeff(i)==y.coeff(i)) {
  x1(k) = x.coeff(i);
  y1(k) = y.coeff(i);
  k++;
 };
};
x1.conservativeResize(k);
y1.conservativeResize(k);
return Rcpp::List::create(Rcpp::Named("x") = x1,
                          Rcpp::Named("y") = y1);
'
na.omit.cpp <- cxxfunction(signature(xx = "Vector", yy= "Vector"), 
                   body, "RcppEigen", incl)
na.omit.cpp(c(1.5, NaN, 7, NA), c(7.0, 1, NA, 3))
#$x
#[1] 1.5
#
#$y
#[1] 7

在我的用例中,我需要在一个循环中(在 Rcpp 函数内)执行此操作大约一百万次,并且向量可能很长(假设 1000 个元素)。

PS:我还研究了使用 x.array()==x.array() 查找所有 NA/NaN 值的路线,但无法找到将结果用于特征子集的方法。

也许我没有正确理解这个问题,但在 Rcpp 中,我看不出你怎么可能比for循环更有效地做到这一点。 for循环在 R 中通常效率低下,只是因为遍历 R 中的循环需要大量繁重的解释机制。 但是,一旦您处于C++级别,情况就不是这样了。 即使是本机矢量化的 R 函数最终也是通过 C 中的for循环实现的。 因此,我能想到的提高效率的唯一方法是尝试并行进行。

例如,下面是一个简单的na.omit.cpp函数,它省略了单个向量中的NA值:

rcppfun<-"
Rcpp::NumericVector naomit(Rcpp::NumericVector x){
std::vector<double> r(x.size());
int k=0;
  for (int i = 0; i < x.size(); ++i) {
    if (x[i]==x[i]) {
    r[k] = x[i];
    k++;
   }
  }
 r.resize(k);
 return Rcpp::wrap(r);    
}"
na.omit.cpp<-cppFunction(rcppfun)

这比 R 内置的 na.omit 运行得更快:

> set.seed(123)
> x<-1:10000
> x[sample(10000,1000)]<-NA
> y1<-na.omit(x)
> y2<-na.omit.cpp(x)
> all(y1==y2)
[1] TRUE
> require(microbenchmark)
> microbenchmark(na.omit(x),na.omit.cpp(x))
Unit: microseconds
           expr     min       lq   median      uq      max neval
     na.omit(x) 290.157 363.9935 376.4400 401.750 6547.447   100
 na.omit.cpp(x) 107.524 168.1955 173.6035 210.524  222.564   100
我不知道

我是否正确理解了这个问题,但您可以使用以下参数:

       a = c(1.5, NaN, 7, NA)
       a[-which(is.na(a))]
       [1] 1.5 7.0
如果您想

在C++中使用"rinside"可能会很有用。

最新更新