2017-02-08 35 views
2

我必须使用big.matrix对象,并且我无法计算某些函数。让我们考虑以下big.matrix:使用big.matrix操作

# create big.matrix object 
x <- as.big.matrix(
     matrix(sample(1:10, 20, replace=TRUE), 5, 4, 
      dimnames=list(NULL, c("a", "b", "c", "d")))) 

> x 
An object of class "big.matrix" 
Slot "address": 
<pointer: 0x00000000141beee0> 

相应的矩阵对象为:

# create matrix object 

x2<-x[,] 

> x2 
    a b c d 
[1,] 6 9 5 3 
[2,] 3 6 10 8 
[3,] 7 1 2 8 
[4,] 7 8 4 10 
[5,] 6 3 6 4 

如果我计算与矩阵对象作业本,它的工作原理:

sqrt(slam::col_sums(x2*x2)) 

> sqrt(slam::col_sums(x2*x2)) 
     a  b  c  d 
13.37909 13.82027 13.45362 15.90597 

而如果我使用big.matrix对象(实际上我必须使用),它不起作用:

sqrt(biganalytics::colsum(x*x)) 

的问题是2:*操作(用于创建矩阵的每个元素的平方),其产生错误:

Error in x * x : non-numeric argument transformed into binary operator

和sqrt函数,其产生错误:

Error in sqrt(x) : non-numeric argument to mathematical function.

如何使用big.matrix对象计算此操作?

回答

0

我不知道它是否做到这一点,通过尝试用最快的方法:

biganalytics::apply(x, 2, function(x) {sqrt(sum(x^2))}) 
1

随着big.matrix对象,我发现2个解决方案,提供良好的性能:

  • 代码在Rcpp中用于你特别需要的功能。在这里,2个嵌套for循环会做的伎俩。然而,你无法重新编码你需要的一切。
  • 在您的big.matrix的列块上使用R函数并汇总结果。这很容易做,只使用R代码。

在你的情况下,10000次列:

require(bigmemory) 

x <- as.big.matrix(
    matrix(sample(1:10, 20000, replace=TRUE), 5, 40000, 
      dimnames=list(NULL, rep(c("a", "b", "c", "d"), 10000)))) 

print(system.time(
    true <- sqrt(colSums(x[,]^2)) 
)) 

print(system.time(
    test1 <- biganalytics::apply(x, 2, function(x) {sqrt(sum(x^2))}) 
)) 
print(all.equal(test1, true)) 

所以,colSums是非常快的,但是需要所有的矩阵在RAM中,而biganalytics::apply是缓慢的,但记忆效率。一种折衷的办法是使用这样的:

CutBySize <- function(m, block.size, nb = ceiling(m/block.size)) { 
    int <- m/nb 

    upper <- round(1:nb * int) 
    lower <- c(1, upper[-nb] + 1) 
    size <- c(upper[1], diff(upper)) 

    cbind(lower, upper, size) 
} 

seq2 <- function(lims) seq(lims["lower"], lims["upper"]) 

require(foreach) 
big_aggregate <- function(X, FUN, .combine, block.size = 1e3) { 
    intervals <- CutBySize(ncol(X), block.size) 

    foreach(k = 1:nrow(intervals), .combine = .combine) %do% { 
    FUN(X[, seq2(intervals[k, ])]) 
    } 
} 

print(system.time(
    test2 <- big_aggregate(x, function(X) sqrt(colSums(X^2)), .combine = 'c') 
)) 
print(all.equal(test2, true)) 

编辑:现在这是在包中实现bigstatsr

print(system.time(
    test2 <- bigstatsr::big_apply(x, a.FUN = function(X, ind) { 
    sqrt(colSums(X[, ind]^2)) 
    }, a.combine = 'c') 
)) 
print(all.equal(test2, true))