operating with big.matrix

笑着哭i 提交于 2019-12-06 11:20:49

With big.matrix objects, I found 2 solutions that offer good performances:

  • code a function in Rcpp for what you specifically need. Here, 2 nested for loops would do the trick. Yet, you can't recode everything you need.
  • use an R function on column blocks of your big.matrix and aggregate the results. It is easy to do and uses R code only.

In your case, with 10,000 times more columns:

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

So, colSums is very fast but needs all the matrix in the RAM, whereas biganalytics::apply is slow, but memory-efficient. A compromise would be to use something like this:

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

Edit: This is now implemented in package 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))

I don't know if it's the fastest way to do it, by try with:

biganalytics::apply(x, 2, function(x) {sqrt(sum(x^2))})
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!