Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Assign Value to Diagonal Entries of Matrix

Tags:

r

matrix

assign

I need to access and assign single slots of an m*n matrix inside a for loop. The code so far:

rowCount <- 9
similMatrix = matrix(nrow = rowCount - 1, ncol = rowCount)
show(similMatrix)
for(i in (rowCount - 1)){
  for (j in rowCount)
    if (i == j){
      similMatrix[i == j] <- 0;
    }
}
show(similMatrix)

so if i = j the NA value in the matrix needs to be replaced with 0.

like image 835
DI MI Avatar asked Jan 14 '13 01:01

DI MI


2 Answers

You want the function diag<-

m <- matrix(1:12, nrow=3)
m
     [,1] [,2] [,3] [,4]
[1,]    1    4    7   10
[2,]    2    5    8   11
[3,]    3    6    9   12

diag(m) <- 0
m
     [,1] [,2] [,3] [,4]
[1,]    0    4    7   10
[2,]    2    0    8   11
[3,]    3    6    0   12
like image 71
Matthew Lundberg Avatar answered Oct 13 '22 01:10

Matthew Lundberg


For the purpose of setting the "diagonal" elements to zero you have already been given an answer but I wonder if you were hoping for something more general. The reasons for lack of success with that code were two-fold: the construction of your indices were flawed and the indexing was wrong. This would have succeeded:

for(i in 1:(rowCount - 1)){  # need an expression that retruns a sequence
  for (j in 1:rowCount)      # ditto
    if (i == j){
      similMatrix[i,j] <- 0;  # need to index the matrix with two element if using i,j
    }
}
#----------
> show(similMatrix)
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
[1,]    0   NA   NA   NA   NA   NA   NA   NA   NA
[2,]   NA    0   NA   NA   NA   NA   NA   NA   NA
[3,]   NA   NA    0   NA   NA   NA   NA   NA   NA
[4,]   NA   NA   NA    0   NA   NA   NA   NA   NA
[5,]   NA   NA   NA   NA    0   NA   NA   NA   NA
[6,]   NA   NA   NA   NA   NA    0   NA   NA   NA
[7,]   NA   NA   NA   NA   NA   NA    0   NA   NA
[8,]   NA   NA   NA   NA   NA   NA   NA    0   NA

But resorting to loops in R is generally considered a last resort (sometimes for the wrong reasons.) There is a much more compact way of doing the same "loop" operation and it generalizes more widely than just setting the diagonal.

similMatrix[ row(similMatrix) == col(similMatrix) ] <- 0
> similMatrix
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
[1,]    0   NA   NA   NA   NA   NA   NA   NA   NA
[2,]   NA    0   NA   NA   NA   NA   NA   NA   NA
[3,]   NA   NA    0   NA   NA   NA   NA   NA   NA
[4,]   NA   NA   NA    0   NA   NA   NA   NA   NA
[5,]   NA   NA   NA   NA    0   NA   NA   NA   NA
[6,]   NA   NA   NA   NA   NA    0   NA   NA   NA
[7,]   NA   NA   NA   NA   NA   NA    0   NA   NA
[8,]   NA   NA   NA   NA   NA   NA   NA    0   NA

If you wanted to set the subdiagonal to zero you could just use:

similMatrix[ row(similMatrix)-1 == col(similMatrix) ] <- 0

You can avoid generating the extra row and col matrices using this:

 mind <- min( dim(similMatrix) )
 # avoid going outside dimensions if not symmetric
 similMatrix[ cbind( seq(maxd),seq(maxd) ) <- 0
like image 39
IRTFM Avatar answered Oct 12 '22 23:10

IRTFM