2017-02-08 8 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 для того, что вам нужно. Здесь два вложенных цикла будут делать трюк. Тем не менее, вы не можете перекодировать все, что вам нужно.
  • используйте функцию R на блоках столбцов вашего big.matrix и соберите результаты. Это легко сделать и использует только 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 очень быстро, но нужно все матрицы в памяти, в то время как 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)) 

Edit: Это теперь реализован в пакете 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))