kutlus
kutlus

Reputation: 361

How can create a sparse matrix out of outer function in R?

In my code, the outer function outputs a matrix. Is it possible to make that output sparse matrix? I could convert this output matrix to a sparse matrix, but I want to do something like outer(......, sparse=T) rather than first have the dense matrix then conversion. Because I have very large data. My code and short sample vectors are below. I have read all the related posts but can`t figure it out.

# myvec is a vector of length 100. 
# mycol is a column vector of length 10.

myvec <- c( 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 1, 0, 2, 1, 2, 1, 3, 2, 2, 1, 0, 1, 2, 1, 0, 2, 1, 2, 1, 3, 2, 2, 1, 0,1, 
          2, 2, 3, 1, 2, 1, 0, 2, 1, 2, 1,0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 1, 0, 2, 1, 2, 1, 3, 2, 2, 1, 0, 1, 2,
          1, 0, 2, 1, 2, 1, 3, 2, 2, 1, 0,1, 2, 2, 3, 1, 2, 1, 0, 2, 1, 2, 1,0, 1, 1, 2, 1, 2, 2, 3)


mycol <- c(-15.07,-7.64, -15.48, -18.59, -12.35, -10.44, -11.45, -18.49, -15.24, -13.23)   
 
res <- outer(1:length(mycol), 1:length(mycol), function(i,j) {
               ifelse(myvec > 1, 0, 
                 ifelse(myvec == 1, (mycol[j]-mycol[i])/(1-exp(-(mycol[j]-mycol[i]))), 
                   ifelse(myvec ==0, 1, myvec)))})

I have also tried to create a sparse matrix from scratch using row, col, value triplets, my code is below. But because the entry (resvec) length is 100, the sparse matrix is created but only using the first 10 of the entries to the diagonals and the rest of the off-diagonal elements are zero. But I wanted to write all 100 entries to their locations.

Many thanks in advance.

resvec<- as.vector(res)

matSparse <- sparseMatrix(
  i = 1:length(mycol), 
  j = 1:length(mycol), 
  x = resvec,
  dims = c(length(mycol),length(mycol)), 
  dimnames = list(rownames,colnames)
)

ps: row names and column names are the same.

Upvotes: 1

Views: 223

Answers (1)

pseudospin
pseudospin

Reputation: 2777

Something like this, where I'm just redoing what outer does but just for the myvec values which produce non-zero results. You could simplify the function f a bit, and perhaps make it a function of myvec too.

f <- function(i,j) {
  ifelse(myvec > 1, 0, 
    ifelse(myvec == 1, (mycol[j]-mycol[i])/(1-exp(-(mycol[j]-mycol[i]))), 
      ifelse(myvec ==0, 1, myvec)))}

library(Matrix)
i <- rep(1:length(mycol), times = length(mycol))[myvec < 2]
j <- rep(1:length(mycol), each = length(mycol))[myvec < 2]
myvec <- myvec[myvec < 2]
sparseMatrix(i, j, x = f(i, j))
#> 10 x 10 sparse Matrix of class "dgCMatrix"
#>                                                                                                                 
#>  [1,] 1.000000000  7.434410 1.000000000 .          2.9118151 4.675609 .          1.0000000 0.91740717 .         
#>  [2,] 0.004409999  1.000000 0.003087581 .          1.0000000 .        0.08629586 .         .          0.02095708
#>  [3,] 1.218969243  .        .           0.14518433 .         .        .          0.1560604 .          1.00000000
#>  [4,] .           10.950192 3.255184331 1.00000000 6.2521909 .        .          .         .          5.38531586
#>  [5,] 0.191815105  .        1.000000000 0.01219087 .         2.241996 .          0.0132598 0.17006693 0.62371549
#>  [6,] .            2.981293 .           .          0.3319956 .        0.57859728 .         .          .         
#>  [7,] .            .        0.072926774 .          1.0000000 1.588597 1.00000000 .         0.08761709 0.36106528
#>  [8,] .            .        .           .          6.1532598 1.000000 7.04617334 .         1.00000000 .         
#>  [9,] 1.087407174  .        0.884795398 0.12180607 3.0600669 .        .          0.1310995 .          .         
#> [10,] .            5.610957 .           .          .         2.972579 2.14106528 1.0000000 0.31098581 .

Upvotes: 2

Related Questions