2017-01-23 10 views
1

나는 R에서 중복을 찾는 빠른 검색을 찾으려고 노력하고 있습니다. 코드의 목적은 행렬의 행 번호를 사용하여 행렬을 Rcpp에 전달한 다음 찾고있는 전체 행렬을 반복합니다 그 행에 대한 일치. 문제의 행렬은 1000 행과 250 행을 갖는 논리 행렬입니다.중복 검색 Rcpp를 사용하여

소리는 간단하지만 아래 코드는 동일한 벡터 행을 감지하지 못합니다. equals() 함수 또는 행렬 또는 벡터 정의 방법에 문제가 있는지 확실하지 않습니다.

#include <Rcpp.h> 
using namespace Rcpp; 

// [[Rcpp::plugins]] 
#include <cstddef> // std:size_t 
#include <iterator> // std:begin, std::end 
#include <vector> // std::vector 
#include <iostream> 
#include <string> 

// [[Rcpp::export]] 
    bool dupCheckRcpp (int nVector, 
         LogicalMatrix bigMatrix) { 
    // initialize 
     int i, j, nrow, ncol; 
     nrow = bigMatrix.nrow(); 
     ncol = bigMatrix.ncol(); 
     LogicalVector vec(ncol); // holds vector of interest 
     LogicalVector vecMatrix(ncol); // temp vector for loop through bigMatrix 
     nVector = nVector - 1; 

    // copy bigMatrix data into vec based on nVector row 
     for (j = 0; j < ncol; ++j) { 
     vec(j) = bigMatrix(nVector,j); 
     } 

    // check loop: check vecTeam against each row in allMatrix 
     for (i = 0; i < nrow; ++i) { 
     // copy bigMatrix data into vecMatrix 
      for (j = 0; j < ncol; ++j) { 
      vecMatrix(j) = bigMatrix(i,j); 
      } 
     // check for equality 
      if (i != nVector) { // skip if nVector row 
      // compare vecTeam to vecMatrix 
       if (std::equal(vec.begin(),vec.end(),vecMatrix.begin())) { 
       return true; 
      } 
      } 
     } // close check loop 
     return false; 
    } 
+2

당신은'거의 그 모든 시간이 이미 쉽지 않을 수도 있습니다 빨리 만들기 C.에서 실행 paste''에 소요되는 매트릭스에서 호출 duplicated'의 호출 스택을 보면 . – alistaire

+3

'(colSums (t (mat) == mat [20,]) == ncol (mat))'은 내 시스템에서 약 1.5ms 걸립니다. 너무 느린가요? – Roland

+2

또한 'tmp = tcrossprod (mat); which ((tmp == rowSums (mat)) & lower.tri (tmp), TRUE)'는 앞에서 all을 계산할 수 있다면 _all_와 일치하는 행을 반환합니다. 그리고 중간의 행렬은 크기가 1e3 * 1e3입니다. 이것은 관리가 잘된 것 같습니다. –

답변

3

내가 실수 코드에 자리하고있는 곳입니다 정확히 모르겠지만, 당신이 정말로 지금까지 수동으로이 같은 Rcpp 유형 간의 요소를 복사 할 필요가 없습니다 참고 :

// copy bigMatrix data into vec based on nVector row 
for (j = 0; j < ncol; ++j) { 
    vec(j) = bigMatrix(nVector, j); 
} 

가있다 거의 항상 적절한 클래스 및/또는 적절한 대입 연산자가 될 것입니다.이를 통해보다 쉽고 간결하게 (프로그래밍 오류가 발생하지 않는)보다 쉽게이 작업을 수행 할 수 있습니다. 상기 충고의 정신

#include <Rcpp.h> 
using namespace Rcpp; 

// [[Rcpp::export]] 
bool is_duplicate_row(R_xlen_t r, LogicalMatrix x) { 
    R_xlen_t i = 0, nr = x.nrow(); 
    const LogicalMatrix::Row& y = x.row(r); 

    for (; i < r; i++) { 
     if (is_true(all(y == x.row(i)))) { 
      return true; 
     } 
    } 
    for (i = r + 1; i < nr; i++) { 
     if (is_true(all(y == x.row(i)))) { 
      return true; 
     } 
    } 

    return false; 
} 

,

  • const LogicalMatrix::Row& y = x.row(r);

    우리에게 매트릭스
  • x.row(i)r 행째에 일정한 기준을 제공하는 i 번째 지칭한다 : 여기 간단한 구현은 x

이 두 표현식 모두 요소 별 복사를 방지합니다. for 루프를 통해 더 읽기 쉬운 IMO입니다. 또한 이나 다른 표준 알고리즘을 사용하는 데는 아무런 문제가 없지만 Rcpp를 사용하면 is_true(all(y == x.row(i)))과 같은 설탕 표현을 사용하면 코드를 훨씬 더 단순하게 만들 수 있습니다.


set.seed(123) 
m <- matrix(rbinom(1000 * 250, 1, 0.25) > 0, 1000) 
m[600,] <- m[2,] 

which(sapply(1:nrow(m) - 1, is_duplicate_row, m)) 
# [1] 2 600 

c(which(duplicated(m, fromLast = TRUE)), which(duplicated(m))) 
# [1] 2 600 
+1

매우 명확한 설명과 함께 굉장한 대답입니다. 루프 당 193.2 초에서 4.7 초로 코드가 변경되었습니다. 속도가 97 % 향상되었습니다. 감사합니다. PS. 작은 컴파일 오류가 코드를 실행 한 : "SEXP에서 긴 long int 변환 잘못되었습니다. int R_xlen_t 용어를 변경하고 괜찮 았는데. –

+1

'[[Rcpp :: plugins (cpp11)]]'사용 'R_xlen_t' 타입을 사용할 수 있으려면 C++ 11을 필요로하는''long int '의 리스터 (recast)입니다. – coatless