我有一个大矩阵,大约有6千万行和150个列(总共大约90亿个元素)。我已将此数据存储在big.matrix
对象中(来自包bigmemory
)。现在,我希望计算每一行的总和,这是一个问题,因为big.matrix
是面向列的,所以据我所知,所有汇总函数都是面向列的(例如colsum
,{ {1}}等)并且默认情况下没有可用于计算行总和的函数。当然我可以做colmax
,但这需要很长时间。我也可以逐个循环遍历列并使用矢量化添加来添加它们:
apply(x, 1, sum)
但是这仍然需要20多分钟,并且显然不是最理想的,因为它每次通过循环创建一个新的6000万元素向量。似乎必须有一些更快的方法来做到这一点。
我通过一次处理大约一百万行的行,并在那些行上调用rowSums,然后连接结果,将此缩短到10分钟。不过,我仍然有兴趣知道是否有一种优化的方法可以做到这一点。
答案 0 :(得分:2)
我已经编写了一些C ++代码来执行此操作,改编自bigmemory Rcpp gallery:
<强> rowSums.cpp 强>
// [[Rcpp::depends(BH)]]
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::depends(BH, bigmemory)]]
#include <bigmemory/MatrixAccessor.hpp>
#include <numeric>
// Logic for BigRowSums.
template <typename T>
NumericVector BigRowSums(XPtr<BigMatrix> pMat, MatrixAccessor<T> mat) {
NumericVector rowSums(pMat->nrow(), 0.0);
NumericVector value(1);
for (int jj = 0; jj < pMat->ncol(); jj++) {
for (int ii = 0; ii < pMat->nrow(); ii++) {
value = mat[jj][ii];
if (all(!is_na(value))) {
rowSums[ii] += value[0];
}
}
}
return rowSums;
}
// Dispatch function for BigRowSums
//
// [[Rcpp::export]]
NumericVector BigRowSums(SEXP pBigMat) {
XPtr<BigMatrix> xpMat(pBigMat);
switch(xpMat->matrix_type()) {
case 1:
return BigRowSums(xpMat, MatrixAccessor<char>(*xpMat));
case 2:
return BigRowSums(xpMat, MatrixAccessor<short>(*xpMat));
case 4:
return BigRowSums(xpMat, MatrixAccessor<int>(*xpMat));
case 6:
return BigRowSums(xpMat, MatrixAccessor<float>(*xpMat));
case 8:
return BigRowSums(xpMat, MatrixAccessor<double>(*xpMat));
default:
throw Rcpp::exception("unknown type detected for big.matrix object!");
}
}
在R:
library(bigmemory)
library(Rcpp)
sourceCpp("rowSums.cpp")
m <- as.big.matrix(matrix(1:9, 3))
BigRowSums(m@address)
[1] 12 15 18