2013-10-03 10 views
0

RcppEigen으로 구현 된 함수 내의 벡터에서 NA 값을 효율적으로 제거해야합니다. 물론 루프를 사용하여 for을 사용할 수는 있지만보다 효율적인 방법이 있는지 궁금합니다. 여기 NA 값을 효율적으로 제거하십시오.

는 예입니다 : 내 사용의 경우

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 

I합니다 (Rcpp 기능 내부) 루프에서이 약 백만 번을해야하고, 벡터가 매우 길 수도 (의 1000 개 요소를 가정하자).

추신 : 나는 x.array()==x.array()을 사용하여 모두 NA/NaN 값을 찾을 수있는 경로를 조사했지만 Eigen으로 하위 집합에 결과를 사용하는 방법을 찾을 수 없습니다.

+0

: R의 na.omit에 내장보다 더 빠르게

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 값을 생략 간단한 na.omit.cpp 기능입니다 그 과정에서 이전에 'NA'를 제거 하시겠습니까? –

+0

불행히도 아닙니다. 내 실제 사용 사례에서는 함수에 세 개의 행렬을 전달하고 해당 열 벡터 간의 회귀를 수행합니다. 그리고 그 때문에 NA 사례를 제거해야합니다. 그래서 나는 작품에'na.omit'과 같은 것을 필요로합니다. R에서 열 인덱스를 반복하고 싶지 않습니다. – Roland

답변

9

아마도 질문을 올바르게 이해하지 못하고 있지만 Rcpp에서는 for 루프보다 더 효율적으로이 작업을 수행 할 수있는 방법을 알지 못합니다. for 루프는 일반적으로 R에서 비효율적입니다. R에서 루프를 반복 할 때 많은 해석기가 필요하기 때문입니다. 그러나 일단 C++ 수준에 이르면이 경우가 아닙니다. 기본적으로 벡터화 된 R 함수조차도 궁극적으로 C에서 for 루프로 구현됩니다. 따라서이 방법을 더 효율적으로 만들 수있는 유일한 방법은 병렬로 수행하는 것입니다. 나는 방법이 없습니다 가정

> 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 
+0

+1 - 하루가 끝나면 각 요소 (i, j)를 살펴 봐야합니다. 마술 뒤에 숨겨진 고리를 가장 할 수는 있지만 왜 그렇게 간단하지 않고 여기에 제시된대로할까요? –

+0

예, 지금이 같은 것을 사용했고 충분히 빠릅니다. 그러나'resize'는 Eigen의 데이터를 보존하지 않는다는 것을 명심하십시오. – Roland

+0

is_na()를 통해 테스트 해 보셨습니까? 인 텐트를 명시 적으로 만든 다음 비교합니다. –

-1

내가 제대로 여부 문제를 이해하면 나도 몰라하지만 당신은 다음 인수를 사용할 수 있습니다

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

당신이 C에서 사용하려는 경우 ++ '`rinside를 사용하는 것이 유용 할 수 있습니다.

+0

일반 R에서는 Rcpp를 사용하고 싶지 않습니다. R을 사용하면'na.omit' 만 사용할 것입니다. 'RInside'를 사용하면 순수한 Rcpp/RcppEigen과 비교할 때 다소 느릴 수 있습니다. – Roland

+0

이 답변에는 상당한 혼란이 있습니다. RInside는 R 내부에서 별도의 응용 프로그램을 만들기위한 것입니다. 이것은 C++ 코드를 R 안에 넣는 것을 목표로하는 Rcpp의 반대입니다. –

관련 문제