dan
dan

Reputation: 6314

Populate a sparse matrix by a matrix of indices

I have a symmetric sparse matrix, initialized to zero:

library(Matrix)
set.seed(1)
mat <- Matrix(0,5,5)

Then I have a matrix (idx.mat) which specifies for each row in mat, three column indices which should be filled with values given by another matrix (val.mat):

idx.mat <- do.call(rbind,lapply(1:5,function(i) sample(1:5,3,replace=F)))
val.mat <- matrix(runif(15,1,10),5,3)

So I'm wondering if there's a faster way to populate mat according to idx.mat and val.mat than:

mat <- do.call(rbind,lapply(1:nrow(mat),function(i) {
  mat[i,idx.mat[i,]] <- val.mat[i,]
  return(mat[i,])
}))

Upvotes: 0

Views: 62

Answers (2)

Maurits Evers
Maurits Evers

Reputation: 50678

You can also define and declare a sparseMatrix right from the start.

# Index/value dataframe
df.idx <- cbind.data.frame(
    melt(idx.mat)[, -2],
    melt(val.mat)[, "value"]);
names(df.idx) <- c("i", "j", "x");

# Declare and define sparseMatrix
mat <- sparseMatrix(i = df.idx$i, j = df.idx$j, x = df.idx$x);
mat;
#5 x 5 sparse Matrix of class "dgCMatrix"
#
#[1,] .        5.479293 .        4.475027 9.412347
#[2,] 2.909283 .        1.120513 .        7.458567
#[3,] .        4.441492 6.865064 .        9.927155
#[4,] 4.420317 .        .        8.827218 2.129996
#[5,] .        3.404986 4.063141 7.997007 .    

Or without the melt+df.idx detour:

i <- rep(seq(1:nrow(idx.mat)), ncol(idx.mat));
j <- c(idx.mat);
x <- c(val.mat);
mat <- sparseMatrix(i = i, j = j, x = x);

#5 x 5 sparse Matrix of class "dgCMatrix"
#
#[1,] .        5.479293 .        4.475027 9.412347
#[2,] 2.909283 .        1.120513 .        7.458567
#[3,] .        4.441492 6.865064 .        9.927155
#[4,] 4.420317 .        .        8.827218 2.129996
#[5,] .        3.404986 4.063141 7.997007 .

Upvotes: 1

Gregor Thomas
Gregor Thomas

Reputation: 145775

A better way is to convert your idx.mat to n x 2 matrix where the columns correspond to row and column indices:

idx = cbind(rep(1:nrow(idx.mat), ncol(idx.mat)), c(idx.mat))

Then you can use that matrix to index and just assign:

mat[idx] = c(val.mat)
mat
# 5 x 5 sparse Matrix of class "dgCMatrix"
#                                                  
# [1,] .        5.479293 .        4.475027 9.412347
# [2,] 2.909283 .        1.120513 .        7.458567
# [3,] .        4.441492 6.865064 .        9.927155
# [4,] 4.420317 .        .        8.827218 2.129996
# [5,] .        3.404986 4.063141 7.997007 . 

Upvotes: 1

Related Questions