2017-02-21 105 views
0

我想要計算一組項目之間的高爾相似度。使用Rcpp包我正在編寫自己的函數來計算相似度值,因爲菊花函數會導致錯誤發生。從Rcpp函數返回NumericVectors的列表

的功能是:

#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循環中重置它。

爲什麼這種方法的工作原理和你不是:我真的不知道,但我認爲它被引用到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」的所有組合的相似性,然後分配給out。那爲什麼它失敗了? – TUSHAr