我需要从使用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:我还调查了使用NA
查找所有NaN
/ x.array()==x.array()
值的路线,但无法找到将结果用于使用Eigen进行子集化的方法。
答案 0 :(得分:10)
也许我没有正确理解这个问题,但在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)
这比内置na.omit
的R的速度更快:
> 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
答案 1 :(得分:-1)
我不知道我是否正确理解了这个问题,但您可以使用以下参数:
a = c(1.5, NaN, 7, NA)
a[-which(is.na(a))]
[1] 1.5 7.0
如果你想在C ++中使用它,可能会使用`rinside'。