Функция R repmat для разреженных матриц - PullRequest
0 голосов
/ 14 мая 2018

для моего проекта r мне нужно повторить несколько больших (то есть больше, чем 1000x1000) матриц. Я нашел две версии matmatb repmat-function в r, которые обе работают, но имеют серьезные ограничения, так что я не могу их использовать. У кого-нибудь есть другой подход к решению этой проблемы?


Чтобы уменьшить использование памяти, я использую sparse-функции из Matrix-Package (Diagonal(), Matrix(..., sparse=TRUE)).

> m <- Diagonal(10000)
> object.size(m)
1168 bytes

Теперь, чтобы повторить эту матрицу, я использую r перевод функции matlab repmat (которую можно найти здесь ):

repmat <- function(X, m, n){
    mx <- dim(X)[1]
    nx <- dim(X)[2]
    return(matrix(t(matrix(X,mx,nx*n)),mx*m,nx*n,byrow=T))
}

К сожалению, этот метод использует стандартную / плотную версию матрицы и работает только до определенного размера объекта, который довольно быстро превышается в моем проекте. Простая замена функции matrix(...) на Matrix(..., sparse=TRUE) также не будет работать из-за различных определений параметров для размеров матрицы.

Единственное другое решение - это repmat-версия из pcaMethods-Package , где я могу использовать разреженные матрицы:

repmat <- function(mat, M, N) {
    ## Check if all input parameters are correct
    if( !all(M > 0, N > 0) ) {
        stop("M and N must be > 0")
    }    

    ## Convert array to matrix
    ma <- mat
    if(!is.matrix(mat)) {
        ma <- Matrix(mat, nrow=1, sparse=TRUE)
    }

    rows <- nrow(ma)
    cols <- ncol(ma)
    replicate <- Matrix(0, rows * M, cols * N, sparse=TRUE)

    for (i in 1:M) {
        for(j in 1:N) {
            start_row <- (i - 1) * rows + 1
            end_row <- i * rows
            start_col <- (j - 1) * cols + 1
            end_col <- j * cols
            replicate[start_row:end_row, start_col:end_col] <- ma
        }
    }

     return(replicate)
}

Однако эта функция выполняет свою работу, но требует много времени выполнения (возможно, из-за вложенных циклов). Моя единственная оставленная опция - увеличить общее значение memory.limit, но это только приводит к исчерпанию физической памяти.


Я в своем уме. Любая помощь или совет будут оценены. Заранее благодарю за ответы.

1 Ответ

0 голосов
/ 14 мая 2018

Используйте методы Matrix для rbind и cbind:

repMat <- function(X, m, n){
  Y <- do.call(rbind, rep(list(X), m))
  do.call(cbind, rep(list(Y), n))
}


system.time(res <- repMat(m, 20, 30))
#user  system elapsed 
#0.48    0.44    0.92
str(res)
#Formal class 'dgCMatrix' [package "Matrix"] with 6 slots
#  ..@ i       : int [1:6000000] 0 10000 20000 30000 40000 50000 60000 70000 80000 90000 ...
#  ..@ p       : int [1:300001] 0 20 40 60 80 100 120 140 160 180 ...
#  ..@ Dim     : int [1:2] 200000 300000
#  ..@ Dimnames:List of 2
#  .. ..$ : NULL
#  .. ..$ : NULL
#  ..@ x       : num [1:6000000] 1 1 1 1 1 1 1 1 1 1 ...
#  ..@ factors : list()

object.size(res)
#73201504 bytes
...