R - 在 Rcpp 中存储距离矩阵

R - store distance matrix in Rcpp

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

让我们想象一下,我想将以下函数存储在 n*n 个个体的距离矩阵中(我不对 sum 进行平方,因为我不确定如何在 rcpp.

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))

您的 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

至于平方,可以在distxy

中使用std::pow
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
}