R 使用大矩阵对象计算欧氏距离矩阵

R 使用大矩阵对象计算欧氏距离矩阵,r,matrix,bigdata,sparse-matrix,r-bigmemory,R,Matrix,Bigdata,Sparse Matrix,R Bigmemory,我在R中有一个类为big.matrix的对象,其维度为778844 x 2。这些值都是整数(公里)。我的目标是使用big.matrix计算欧几里德距离矩阵,并因此得到类big.matrix的对象。我想知道是否有一个最佳的方法来做到这一点 我选择使用类big.matrix的原因是内存限制。我可以将我的big.matrix转换为类matrix的对象,并使用dist()计算欧几里德距离矩阵。但是,dist()将返回一个大小不在内存中分配的对象 编辑 以下答案由bigmemory软件包的作者和维护者Jo

我在
R
中有一个类为
big.matrix
的对象,其维度为
778844 x 2
。这些值都是整数(公里)。我的目标是使用
big.matrix
计算欧几里德距离矩阵,并因此得到类
big.matrix
的对象。我想知道是否有一个最佳的方法来做到这一点

我选择使用类
big.matrix
的原因是内存限制。我可以将我的
big.matrix
转换为类
matrix
的对象,并使用
dist()
计算欧几里德距离矩阵。但是,
dist()
将返回一个大小不在内存中分配的对象

编辑

以下答案由
bigmemory
软件包的作者和维护者John W.Emerson给出:

我希望您可以使用大代数,但这也是通过sourceCpp()实现Rcpp的一个非常好的用例,而且非常简单。但简言之,我们甚至不尝试提供高级功能(除了作为概念验证而实现的基本功能)。一旦你开始谈论内存不足的问题,没有一种算法能够覆盖所有用例


下面是一种使用
RcppArmadillo
的方法。这在很大程度上类似于。这将返回一个带有相关成对(按行)欧氏距离的
big.matrix
。我喜欢将我的
big.matrix
函数包装在包装函数中,以创建更清晰的语法(即避免
@address
和其他初始化)

注意-由于我们使用的是bigmemory(因此与RAM的使用有关),我在这个示例中只返回了下三角元素的N-1 x N-1矩阵。您可以修改这个矩阵,但这是我组合的

欧洲大学区

// To enable the functionality provided by Armadillo's various macros,
// simply include them before you include the RcppArmadillo headers.
#define ARMA_NO_DEBUG

#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo, BH, bigmemory)]]

using namespace Rcpp;
using namespace arma;

// The following header file provides the definitions for the BigMatrix
// object
#include <bigmemory/BigMatrix.h>

// C++11 plugin
// [[Rcpp::plugins(cpp11)]]

template <typename T>
void BigArmaEuclidean(const Mat<T>& inBigMat, Mat<T> outBigMat) {

  int W = inBigMat.n_rows;

  for(int i = 0; i < W - 1; i++){
      for(int j=i+1; j < W; j++){
          outBigMat(j-1,i) = sqrt(sum(pow((inBigMat.row(i) - inBigMat.row(j)),2)));
      }
  }
}

// [[Rcpp::export]]
void BigArmaEuc(SEXP pInBigMat, SEXP pOutBigMat) {
  // First we tell Rcpp that the object we've been given is an external
  // pointer.
  XPtr<BigMatrix> xpMat(pInBigMat);
  XPtr<BigMatrix> xpOutMat(pOutBigMat);


  int type = xpMat->matrix_type();
  switch(type) {
      case 1:
        BigArmaEuclidean(
            arma::Mat<char>((char *)xpMat->matrix(), xpMat->nrow(), xpMat->ncol(), false),
            arma::Mat<char>((char *)xpOutMat->matrix(), xpOutMat->nrow(), xpOutMat->ncol(), false)
        );
        return;

      case 2:
        BigArmaEuclidean(
          arma::Mat<short>((short *)xpMat->matrix(), xpMat->nrow(), xpMat->ncol(), false),
          arma::Mat<short>((short *)xpOutMat->matrix(), xpOutMat->nrow(), xpOutMat->ncol(), false)
        );
        return;

      case 4:
        BigArmaEuclidean(
          arma::Mat<int>((int *)xpMat->matrix(), xpMat->nrow(), xpMat->ncol(), false),
          arma::Mat<int>((int *)xpOutMat->matrix(), xpOutMat->nrow(), xpOutMat->ncol(), false)
        );
        return;

      case 8:
        BigArmaEuclidean(
          arma::Mat<double>((double *)xpMat->matrix(), xpMat->nrow(), xpMat->ncol(), false),
          arma::Mat<double>((double *)xpOutMat->matrix(), xpOutMat->nrow(), xpOutMat->ncol(), false)
        );
        return;

      default:
        // We should never get here, but it resolves compiler warnings.
        throw Rcpp::exception("Undefined type for provided big.matrix");
  }

}
//要启用犰狳的各种宏提供的功能,
//只需在包含RcppArmadillo头之前包含它们。
#定义ARMA_NO_调试
#包括
//[[Rcpp::depends(RcppArmadillo,BH,bigmemory)]]
使用名称空间Rcpp;
使用arma;
//以下头文件提供了BigMatrix的定义
//反对
#包括
//C++11插件
//[[Rcpp::插件(cpp11)]]
模板
void BigArmaEuclidean(常数Mat&inBigMat,Mat-outBigMat){
int W=inBigMat.n_行;
对于(int i=0;imatrix_type();
开关(类型){
案例1:
双欧几里德(
arma::Mat((char*)xpMat->matrix(),xpMat->nrow(),xpMat->ncol(),false),
arma::Mat((char*)xpOutMat->matrix(),xpOutMat->nrow(),xpOutMat->ncol(),false)
);
返回;
案例2:
双欧几里德(
arma::Mat((短*)xpMat->matrix(),xpMat->nrow(),xpMat->ncol(),false),
arma::Mat((短*)xpOutMat->matrix(),xpOutMat->nrow(),xpOutMat->ncol(),false)
);
返回;
案例4:
双欧几里德(
arma::Mat((int*)xpMat->matrix(),xpMat->nrow(),xpMat->ncol(),false),
arma::Mat((int*)xpOutMat->matrix(),xpOutMat->nrow(),xpOutMat->ncol(),false)
);
返回;
案例8:
双欧几里德(
arma::Mat((双*)xpMat->matrix(),xpMat->nrow(),xpMat->ncol(),false),
arma::Mat((双*)xpOutMat->matrix(),xpOutMat->nrow(),xpOutMat->ncol(),false)
);
返回;
违约:
//我们不应该到这里,但它解决了编译器警告。
抛出Rcpp::exception(“提供的big.matrix的未定义类型”);
}
}
我的小包装

bigMatrixEuc <- function(bigMat){
    zeros <- big.matrix(nrow = nrow(bigMat)-1,
                        ncol = nrow(bigMat)-1,
                        init = 0,
                        type = typeof(bigMat))
    BigArmaEuc(bigMat@address, zeros@address)
    return(zeros)
}

bigmartixeuc我运行了上面的程序,得到了
bm\u
作为
matrix
。阅读包装,我原以为
bm\u out
应该是一个
big.matrix
。我错了吗?这个例子确实应该产生一个
matrix
?任何方法都可以将
bm\code>直接作为
big.matrix
(而不是我作为.big.matrix传递给
matrix
)@Ricky只需删除括号,然后删除“[]”,因为它们仅用于确认输出与“dist”中的相同。
library(Rcpp)
sourceCpp("euc_dist.cpp")

library(bigmemory)

set.seed(123)
mat <- matrix(rnorm(16), 4)
bm <- as.big.matrix(mat)

# Call new euclidean function
bm_out <- bigMatrixEuc(bm)[]

# pull out the matrix elements for out purposes
distMat <- as.matrix(dist(mat))
distMat[upper.tri(distMat, diag=TRUE)] <- 0
distMat <- distMat[2:4, 1:3]

# check if identical 
all.equal(bm_out, distMat, check.attributes = FALSE)
[1] TRUE