R - 以Rcpp存储距离矩阵

时间:2016-07-08 14:44:53

标签: r matrix distance rcpp

我无法弄清楚如何在Rcpp中存储距离矩阵。

让我们想象一下,我想将以下函数存储在n*n个人的距离矩阵中(我不会对sum进行平方,因为我不确定如何在{rcpp中执行此操作1}}。

distxy = function(x,y) sum (x - y) 

在这个例子中,我想成对比较3个人

      [,1] [,2] [,3] [,4]
[1,]   24   24   22   20
[2,]   21   24   30   20
[3,]   44   34   41   13

R中,我会通过像这样的矩阵循环函数

mat = matrix(0, nrow(d), nrow(d))

  len = nrow(d)
  mat = matrix(0, len, len)

  for(j in 1:len){
    for(i in 1:len){
      mat[j,i] = distxy( d[j,], d[i,] ) 
    }
  }

并得到(我可以对结果进行平方,但这在这里并不重要)

     [,1] [,2] [,3]
[1,]    0   -5  -42
[2,]    5    0  -37
[3,]   42   37    0

我在rcpp

中做同样的事情时遇到了麻烦

到目前为止我取得的成就是

// [[Rcpp::export]]
NumericVector FunCpp(NumericMatrix x) {
  int nrow = x.nrow();
  NumericMatrix out(nrow);

  for (int i = 0; i < nrow; i++) {
    for (int j = 0; j < nrow; j++) { 
      out[i,j] = sum( x(i,_) - x(j,_) ) ; 
    }
  }
  return out;
}

但距离矩阵不正确。任何的想法 ?

d = rbind(c(24, 24, 22, 20), 
      c(21, 24, 30, 20), 
      c(44, 34, 41, 13))

1 个答案:

答案 0 :(得分:4)

您的Rcpp代码中存在一些语法错误:

  • 返回NumericVector而不是NumericMatrix
  • 使用operator[]按两个维度(out[i,j]
  • 进行索引

这是一个清理版本:

#include <Rcpp.h>

inline double distxy(Rcpp::NumericVector x, Rcpp::NumericVector y) {
    return Rcpp::sum(x - y);
}

// [[Rcpp::export]]
Rcpp::NumericMatrix FunCpp(Rcpp::NumericMatrix x) {
    int nrow = x.nrow();
    Rcpp::NumericMatrix out(nrow);

    for (int i = 0; i < nrow; i++) {
        for (int j = 0; j < nrow; j++) { 
            out(j, i) = distxy(x.row(j), x.row(i)); 
        }
    }

    return out;
}

针对您的R函数进行测试,

m <- matrix(
    c(24, 24, 22, 20,
      21, 24, 30, 20,
      44, 34, 41, 13),
    nrow = 3, byrow = TRUE
)

all.equal(FunR(m), FunCpp(m))
#[1] TRUE

至于平方,您可以在std::pow内使用distxy

return std::pow(Rcpp::sum(x - y), 2);

或内循环中的FunCpp内部:

out(j, i) = std::pow(distxy(x.row(j), x.row(i)), 2);
distxy <- function(x,y) sum(x - y) 

FunR <- function(d) {
    len <- nrow(d)
    mat <- matrix(0, len, len)

    for(j in 1:len){
        for(i in 1:len){
            mat[j,i] <- distxy(d[j,], d[i,]) 
        }
    }
    mat
}