Skip to content

Creating a Sparse Matrix from a Sparse Vector

2 messages · BDGrantham at Hormel.com, Martin Maechler

#
Hello,

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

Starting Matrix:

exampleMatrix
3 x 4 sparse Matrix of class "dgCMatrix"

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

New Matrix:..

 newExampleMatrix
3 x 4 sparse Matrix of class "dgCMatrix"

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

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

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

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

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

And finally, when I tried the next instruction, I got the error "Error in
as.vector(x, mode) :  cannot coerce type 'S4' to vector of type 'any' Error
in as.matrix.csc(as.matrix.csr(x)) : error in evaluating the argument 'x'
in selecting a method for function 'as.matrix.csc'" :

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

Are there any other ways to accomplish this?],

Thanks,

Brian




Notice:
This communication is an electronic communication within the meaning
of the Electronic Communications Privacy Act, 18 U.S.C. sec. 2510. Its
disclosure is strictly limited to the recipient(s) intended by the
sender of this message.  This transmission and any attachments may
contain proprietary, confidential, attorney-client privileged
information and/or attorney work product. If you are not the intended
recipient, any disclosure, copying, distribution, reliance on, or use
of any of the information contained herein is STRICTLY PROHIBITED.
Please destroy the original transmission and its attachments without
reading or saving in any matter and confirm by return email.
#
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