# [R] column permutation of sparse matrix

cberry at tajo.ucsd.edu cberry at tajo.ucsd.edu
Wed Dec 21 02:33:00 CET 2011

```Douglas Bates <bates at stat.wisc.edu> writes:

> On Tue, Dec 20, 2011 at 8:20 AM, Jean V Adams <jvadams at usgs.gov> wrote:
>
> Hi Jean,
>
>> khai wrote on 12/19/2011 11:26:55 PM:
>>
>>> Hi,
>>>
>>> I'm very new to working with sparse matrices and would like to know how
>> I
>>> can column permute a sparse matrix. Here is a small example:
>>>
>>> > M1 <-
>>> > spMatrix(nrow=5,ncol=6,i=sample(5,15,replace=TRUE),j=sample(6,
>>> 15,replace=TRUE),x=round_any(rnorm(15,2),0.001))
>>> > M1
>>> 5 x 6 sparse Matrix of class "dgTMatrix"
>>>
>>> [1,] 2.983      .     1.656    5.003    .        .
>>> [2,]    .            .     2.990        .         .        .
>>> [3,]    .     0.592   5.349    1.115    .        .
>>> [4,] 1.836      .     2.804        .         .        .
>>> [5,]    .     6.961       .             .         .     1.077
>>>
>>> I know I can permute entire columns this way
>>>
>>> > M1[,sample(6,6)]
>>> 5 x 6 sparse Matrix of class "dgTMatrix"
>>>
>>> [1,] 5.003        .           .           .       1.656    2.983
>>> [2,]     .             .           .           .       2.990       .
>>> [3,] 1.115    0.592      .           .       5.349       .
>>> [4,]     .             .           .          .       2.804     1.836
>>> [5,]     .         6.961   1.077     .          .            .
>>>
>>> But I would like the new sparse matrix to look like this...where only
>> the
>>> nonzero elements are permuted.
>>>
>>> [1,] 1.656      .     5.003    2.983    .        .
>>> [2,]    .            .     2.990        .         .        .
>>> [3,]    .    5.349    1.115    0.592    .        .
>>> [4,] 2.804      .     1.836        .         .        .
>>> [5,]    .     1.077       .             .         .     6.961
>>>
>
> A peculiar request but you can do that by permuting the 'x' slot in
>
>> set.seed(1)
>> (M1 <- spMatrix(nrow=5,ncol=6,i=sample(5,15,replace=TRUE),j=sample(6, 15,replace=TRUE),x=round(rnorm(15,2),3)))
> 5 x 6 sparse Matrix of class "dgTMatrix"
>
> [1,] .     .     2.738  .     3.595 .
> [2,] .     .     .      .     .     .
> [3,] 3.879 .     4.289 -0.215 1.374 .
> [4,] .     4.966 1.180  1.379 .     2.487
> [5,] 3.512 .     .      .     2.330 .
>> (nnz <- nnzero(M1))
>  15
>> M2 <- M1
>> M2 at x <- M2 at x[sample(nnz, nnz)]
>> M2
> 5 x 6 sparse Matrix of class "dgTMatrix"
>
> [1,] .     .     2.487 .      3.595 .
> [2,] .     .     .     .      .     .
> [3,] 3.709 .     2.875 3.512 -0.215 .
> [4,] .     3.764 1.164 2.576  .     3.125
> [5,] 2.184 .     .     .      2.738 .
>

I do not think this is what was wanted.

M1 and M2 are matrices with 12 non-zero elements, not 15 as nnzero() reports.

The dgTMatrix representation effectively treats the slots of M1 like this:

res <- tapply(M1 at x, list(M1 at i,M1 at j), sum)
res[is.na(res)] <- 0
res

So permuting 'x' will return a different dgTMatrix with the same number
of non-zero elements in place of the existing non-zero elements, but not
necessarily having the same values when the (i,j) pairs are not
unique. (e.g. 3.709 is seen in M2, but not M1)

I think the OP was asking for permutations of the non-zero values in
'res', rather than permutations of M1 at x.

HTH,

Chuck

>>
>> I don't have experience with sparse matrices, but I was able to get this
>> to work by converting the sparse matrix to a "base" matrix and back again.
>>
>>
>> library(Matrix)
>>
>> nonzero.cols <- !apply(M1==0, 2, all)
>> M2 <- as.matrix(M1)
>> reord <- sample(seq(dim(M1))[nonzero.cols])
>> M2[, nonzero.cols] <- as.matrix(M1[, reord])
>> Matrix(M2, sparse=TRUE)
>
> This solution has the disadvantage of converting the sparse matrix to
> a dense matrix, which may end up producing a much larger object.
>

--
Charles C. Berry                            Dept of Family/Preventive Medicine
cberry at ucsd edu			    UC San Diego
http://famprevmed.ucsd.edu/faculty/cberry/  La Jolla, San Diego 92093-0901

```