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