2017-02-21 64 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