3

I have a matrix as below;

   1  2  3  4  5  
1  0  1  1  0  0  
2  0  0  1  1  0  
3  1  0  0  0  1  
4  0  0  1  0  0   
5  0  1  0  0  0  

I need to get symmetric matrix as follows with diagonal 0;

   1  2  3  4  5  
1  0  1  1  0  0  
2  1  0  1  1  1  
3  1  1  0  1  1  
4  0  1  1  0  0   
5  0  1  1  0  0  

I tried it with for loop, it is good when the size of the matrix is small. But for large size, it takes time. Is there any efficient way to do it in R?

EDIT: First row has 1s in 2nd and 3rd column, and first column has 1s in 3rd row. But to have symmetric first column is also need to have 1 in 2nd row. Similarly every rows and column should consider 1s to maintain the symmetric matrix.

Anu
  • 211
  • 1
  • 9

3 Answers3

5

Using logical operations

sym_mat <- (mat | t(mat)) * 1

@chinsoon12's suggestion is quite nice.

sym_mat <- +(mat | t(mat))
kangaroo_cliff
  • 6,067
  • 3
  • 29
  • 42
2
mat=read.table(text="   1  2  3  4  5  
1  0  1  1  0  0  
           2  0  0  1  1  0  
           3  1  0  0  0  1  
           4  0  0  1  0  0   
           5  0  1  0  0  0  ")

mat=as.matrix(mat)
m=ifelse(!t(mat)[lower.tri(mat)], mat[lower.tri(mat)], t(mat)[lower.tri(mat)])
mat[lower.tri(mat)]=m
mat[upper.tri(mat)]=t(mat)[upper.tri(mat)]


 mat
  X1 X2 X3 X4 X5
1  0  1  1  0  0
2  1  0  1  1  1
3  1  1  0  1  1
4  0  1  1  0  0
5  0  1  1  0  0
Onyambu
  • 67,392
  • 3
  • 24
  • 53
1

How about:

myTrues <- which(mat == 1, arr.ind = T)
mat[rbind(myTrues, myTrues[,c(2,1)])] <- 1L

mat
     [,1] [,2] [,3] [,4] [,5]
[1,]    0    1    1    0    0
[2,]    1    0    1    1    1
[3,]    1    1    0    1    1
[4,]    0    1    1    0    0
[5,]    0    1    1    0    0
Joseph Wood
  • 7,077
  • 2
  • 30
  • 65