Return 来自 Rcpp 函数的 NumericVectors 列表

Return a list of NumericVectors from Rcpp function

我正在尝试计算一组项目之间的 Gower 相似度。使用 Rcpp 包,我正在编写自己的函数来计算相似度值,因为对于较大的数据,daisy 函数会抛出错误。

函数是:

#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] 是不同的。

谁能告诉我这是什么问题?

这个问题的解决方法是在第一个for命令之后定义向量sim,像这样:

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

或者您可以按原样定义矢量并在第一个 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;
}