[R] Creating a Sparse Matrix from a Sparse Vector

Martin Maechler maechler at stat.math.ethz.ch
Tue Jan 20 22:21:01 CET 2009


>>>>> "B" == BDGrantham  <BDGrantham at Hormel.com>
>>>>>     on Tue, 20 Jan 2009 11:53:55 -0600 writes:

    B> Hello,

    B> I am working with a sparse matrix that is approx. 13,900 by 14,100.  My
    B> goal is to select a row out of the matrix and create a new matrix with that
    B> row repeated 13,900 times without having to do any looping.  Example:

    B> Starting Matrix:

    B> exampleMatrix
    B> 3 x 4 sparse Matrix of class "dgCMatrix"

    B> [1,] 1 . . .
    B> [2,] . 1 . 0.5
    B> [3,] . . 1 ..

    B> New Matrix:..

    B> newExampleMatrix
    B> 3 x 4 sparse Matrix of class "dgCMatrix"

    B> [1,] . 1 . 0.5
    B> [2,] . 1 . 0.5
    B> [3,] . 1 . 0.5

    B> When I try the following I get a memory allocation error due to the size of
    B> the array or vector:

{the following is too ugly for me to deparse ..}

If you used variable names of one or two letters, spaces and
proper indentation, that would have been a different business.

    B> newExampleMatrix<-Matrix(rep(exampleMatrix[2,],times=nrow
    B> (exampleMatrix)),nrow=nrow(exampleMatrix),ncol=ncol
    B> (exampleMatrix),byrow=TRUE,sparse=TRUE)
    B> newExampleMatrix<-Matrix(exampleMatrix[2,],nrow=nrow
    B> (exampleMatrix),ncol=ncol(exampleMatrix),byrow=TRUE,sparse=TRUE)

Matrix() should not be used for large sparse matrices.
It's input, when not a sparseMatrix must be *dense* in one way
or the other.

The real solution of course is to step back and think a bit:

What will the (i,j,x)  [triplet aka "Tsparse"]
           or (i,p,x)  [column-compressed aka "Csparse"]
structure be.
After a fraction of a second you'll see that the triplet
representation will be trivial .... more on that below.


    B> When I tried the next set, I got the error "Error in Matrix(as(rep
    B> (exampleMatrix[2, ], times = nrow(exampleMatrix)),  :   invalid type/length
    B> (S4/12) in vector allocation":

    B> newExampleMatrix<-Matrix(as(rep(exampleMatrix[2,],times=nrow
    B> (exampleMatrix)),"sparseVector"),nrow=nrow(exampleMatrix),ncol=ncol
    B> (exampleMatrix),byrow=TRUE,sparse=TRUE)
    B> newExampleMatrix<-Matrix(as(exampleMatrix[2,],"sparseVector"),nrow=nrow
    B> (exampleMatrix),ncol=ncol(exampleMatrix),byrow=TRUE,sparse=TRUE)

    B> And finally, when I tried the next instruction, I got the error "Error in
    B> as.vector(x, mode) :  cannot coerce type 'S4' to vector of type 'any' Error
Here seem to have loaded "SparseM" additionally to "Matrix",
not something useful at all here ..

    B> in as.matrix.csc(as.matrix.csr(x)) : error in evaluating the argument 'x'
    B> in selecting a method for function 'as.matrix.csc'" :

    B> as.matrix.csc(as(rep(currentMatrix[pivitRow,],times=nrow
    B> (currentMatrix)),"sparseVector"),nrow=nrow(currentMatrix),ncol=ncol
    B> (currentMatrix))

    B> Are there any other ways to accomplish this?],

yes; many, as always with R.
Since I'm sick in bed and cannot really do rocket science (:-)
I've solved this exercise for you:

require("Matrix")

repRow <- function(m, i, times)
{
    ## Purpose: return a sparse matrix containing row m[i,] 'times' times
    ## ----------------------------------------------------------------------
    ## Arguments: m: sparseMatrix;  i: row index;  times: #{replicates}
    ## ----------------------------------------------------------------------
    ## Author: Martin Maechler, Date: 20 Jan 2009, 21:48
    stopifnot(is(m, "sparseMatrix"),
              length(i) == 1, length(times <- as.integer(times)) == 1,
              i >= 1, times >= 0, i == as.integer(i))
    cl <- class(m)
    m <- as(m, "TsparseMatrix")
    mi <- m[i,, drop=FALSE]
    ## result: replace the parts of 'm':
    r <- new(class(mi))
    r at Dim <- c(times, m at Dim[2])
    r at i <- rep.int(seq_len(times) - 1L, length(mi at j))
    r at j <- rep(mi at j, each = times)
    r at Dimnames <- list(NULL, mi at Dimnames[[2]])
    if(!extends(cl, "nMatrix")) ## have 'x' slot
        r at x <- rep(mi at x, each = times)
    validObject(r)
    if(extends(cl, "CsparseMatrix")) as(r, "CsparseMatrix") else r
}


(m <- Matrix(c(0,0,2:0), 3,5))
repRow(m,3, 7)
repRow(m,2, 11)
repRow(m,1, 1)
repRow(m,1, 0) # even that works

## now with a big (very sparse) one:
M <- kronecker(m, diag(1000))
r <- repRow(M,2, 4) # still quite quick

##-------------

Best regards,
Martin Maechler, ETH Zurich



More information about the R-help mailing list