2017-02-21 10 views
0

Я пытаюсь вычислить сходство Gower между набором элементов. Используя пакет Rcpp, я пишу свою собственную функцию для вычисления значения подобия, так как с большими данными функция daisy выдает ошибку.Вернуть список NumericVectors из функции Rcpp

Функция:

#include <Rcpp.h> 
using namespace Rcpp; 

// [[Rcpp::export]] 
List gowerSim(CharacterMatrix inp) { 

    int n_row = inp.nrow(), n_col = inp.ncol(); 
    int sumRow = 0, colLen; 
    List out(n_row); 

    //double sim[n_row]; 
    NumericVector sim(n_row); 

    for (int i = 0; i < n_row; i++) { 

    for (int j = 0; j < n_row; j++) { 

     sumRow = 0; 
     colLen = n_col; 

     for (int k = 0; k < n_col; k++) { 
     if (inp(i,k) != "NA" && inp(j,k) != "NA") { 

      if (inp(i,k) != inp(j,k)) { 
      sumRow = sumRow + 1; 
      } 
     } else { 
      colLen = colLen - 1; 
     } 
     } 
     if (colLen > 0) { 
     sim[j] = (double) sumRow/colLen; 
     //printf("%f",sim[j]); 
     } else { 
     sim[j] = NA_INTEGER; 
     } 
    } 

    out[i] = sim; 

    if (i < 3) { 
     print(out); 
    } 
    } 

    return out; 
} 

/*** R 
clust<-gowerSim(inp) 
*/ 

Возвращаемый список имеет последний вектор скопированный на все другие элементы, то есть, предположим, что если clust имеет длину 250, clust[[1]] и clust[[250]] имеют все значения одинаковы. Однако при печати (для верхних 3 элементов) каждый вектор out[1], out[2], out[3] отличается.

Может кто-нибудь, пожалуйста, скажите, в чем проблема?

ответ

1

Решение этой проблемы заключается в определении вектора sim после первого for команды, как это:

List gowerSim(CharacterMatrix inp) { 

    int n_row = inp.nrow(), n_col = inp.ncol(); 
    int sumRow=0,colLen; 
    List out(n_row); 

    for(int i=0;i<n_row;i++){ 

    NumericVector sim(n_row); 

    for(int j=0;j<n_row;j++){ 
     sumRow=0; 
     colLen=n_col; 
     for(int k=0; k<n_col;k++){ 
     if(inp(i,k)!="NA" && inp(j,k)!="NA"){ 
      if(inp(i,k)!=inp(j,k)){ 
      sumRow=sumRow+1; 
      } 
     }else{ 
      colLen=colLen-1; 
     } 
     } 
     if(colLen>0){ 
     sim[j] = (double) sumRow/colLen; 
     //printf("%f",sim[j]); 
     }else{ 
     sim[j] = NA_INTEGER; 
     } 
    } 
    out[i] = sim; 
    if(i<3){ 
     print(out); 
    } 
    } 

    return out; 
} 

Маленький пример:

mat <- matrix(as.character(c(rep(1,5),sample(3,15,repl=TRUE),rep(5,5))),5) 
clust <- gowerSim(mat) 
clust 

enter image description here

Или вы можете определите вектор так, как вы его сделали, и сбросьте его в первом for-loop.

Почему именно этот подход работает, а ваш нет: я действительно не знаю, но я думаю, что он ссылается на структуру списка на C++.

Мой первый подход к решению вашей проблемы был следующий: Вместо заполнения списка, мы заполняем матрицу, и это работает отлично, смотрите здесь:

NumericMatrix gowerSim(CharacterMatrix inp) { 

    int n_row = inp.nrow(), n_col = inp.ncol(); 
    int sumRow=0,colLen; 
    NumericMatrix out(n_row, n_col); 
    NumericVector sim(n_row); 

    for(int i=0;i<n_row;i++); 

    for(int j=0;j<n_row;j++){ 
     sumRow=0; 
     colLen=n_col; 
     for(int k=0; k<n_col;k++){ 
     if(inp(i,k)!="NA" && inp(j,k)!="NA"){ 
      if(inp(i,k)!=inp(j,k)){ 
      sumRow=sumRow+1; 
      } 
     }else{ 
      colLen=colLen-1; 
     } 
     } 
     if(colLen>0){ 
     sim[j] = (double) sumRow/colLen; 
     //printf("%f",sim[j]); 
     }else{ 
     sim[j] = NA_INTEGER; 
     } 
    } 
    out(_,i) = sim; 
    if(i<3){ 
     print(out); 
    } 
    } 

    return out; 
} 
+0

Это worked..thanks много. Не могли бы вы рассказать о том, почему это сработало? sim был объявлен как вектор для хранения сходства для всех комбинаций итератора «i» с «j», а затем назначить его. Так почему это провалилось? – TUSHAr

 Смежные вопросы

  • Нет связанных вопросов^_^