2

I am trying to make a symmetric matrix using R. I already have a matrix. My matrix is very big so below is a simple example.

EX.

1 2 3

4 5 6

7 8 9

I need to make them like this.

1 2+4 3+7

4+2 5 6+8

7+3 8+6 9

//So I tried this. // mat is the matrix I am using.

lowervector <- square_07[lower.tri(square_07, diag = FALSE)]

uppervector <- square_07[upper.tri(square_07, diag = FALSE)]

lowermat <- square_07 uppermat <- square_07

lowermat[lower.tri(lowermat, diag = FALSE)] <- t(square_07)[lower.tri(square_07, diag = FALSE)]

uppermat[upper.tri(uppermat, diag = FALSE)] <- t(square_07)[upper.tri(square_07, diag = FALSE)]

When I execute the last 2 lines, an error occurs;

Subscript 'upper.tri(uppermat, diag = FALSE)' is a matrix, the data 't[upper.tri(square_07, diag = FALSE)]' must have size 1.

You should know. The upper matrix is just an example. My actual matrix is much more bigger. It is a 248*248 matrix.

How can I solve this problem?

Mir
  • 63
  • 6
  • I need to add the values of the two sides around the center line of the matrix...! The center line's values are 1, 5, 9. So 2 and 4 should be added together. And 3 and 7, 6 and 8 should be added together also. – Mir Jul 29 '21 at 04:26

5 Answers5

6

This is simpler:

result <- square_07 + t(square_07)
diag(result) <- diag(square_07)
result
#      [,1] [,2] [,3]
# [1,]    1    6   10
# [2,]    6    5   14
# [3,]   10   14    9
dcarlson
  • 10,936
  • 2
  • 15
  • 18
1

You can try this -

mat[upper.tri(mat)] <- mat[upper.tri(mat)] + mat[lower.tri(mat)]
mat[lower.tri(mat)] <- mat[upper.tri(mat)]
mat

#     [,1] [,2] [,3]
#[1,]    1    6   10
#[2,]    6    5   14
#[3,]   10   14    9

data

mat <- structure(c(1L, 4L, 7L, 2L, 5L, 8L, 3L, 6L, 9L), .Dim = c(3L, 3L))
mat

#     [,1] [,2] [,3]
#[1,]    1    2    3
#[2,]    4    5    6
#[3,]    7    8    9
Ronak Shah
  • 377,200
  • 20
  • 156
  • 213
  • I think this is a more simple solution if it works...Thank you! But the problem is this code also occurs an error message. **Subscript `upper.tri(square_07)` is a matrix, the data `square_07[upper.tri(square_07)] + square_07[lower.tri(square_07)]` must have size 1.** – Mir Jul 29 '21 at 04:39
  • square_07 is my matrix – Mir Jul 29 '21 at 04:40
  • What is `class(square_07)` and what is `dim(square_07)` ? – Ronak Shah Jul 29 '21 at 04:40
  • class is data frame. class(square_07) "tbl_df" "tbl" "data.frame" dimension is 248*248 – Mir Jul 29 '21 at 04:47
  • class of square_07[upper.tri(square_07)] is numeric – Mir Jul 29 '21 at 04:49
  • But dimension of square_07[upper.tri(square_07)] is NULL.... However square_07[upper.tri(square_07)] has numeric values in it. – Mir Jul 29 '21 at 04:50
  • @Mir First convert `square_07` to matrix. `square_07 <- as.matrix(square_07)` and then try the answer. – Ronak Shah Jul 29 '21 at 04:50
  • Oh..I guess I didn't know the difference between data frames and matrices. Thank you so much! The problem is solved. – Mir Jul 29 '21 at 04:57
1

Add to it the transpose (giving you the desired off-diagonal elements) and subtract the diagonal (because the previous operation will double your diagonal elements):

desired.matrix <- matrix + t(matrix) - diag(diag(matrix))

The reason for the iterated diag commands is because the first diag will just give you a vector. The second diag will result to the desired matrix w/c you want to subract.

Marco
  • 2,368
  • 6
  • 22
  • 48
tolits
  • 11
  • 1
0

Another approach would be something like below:

# make square matrix of 16 elements
M <- matrix(data=sample(1:16), nrow=4, ncol=4, byrow=FALSE)

# make the matrix symmetric
MS <- 1/2 * (M + t(M))

# check if matrix is symmetric
isSymmetric(MS)
GSA
  • 751
  • 8
  • 12
0

We can try igraph to interpret the matrix as an adjacency matrix of a graph

library(igraph)
mat %>%
  graph_from_adjacency_matrix(mode = "plus") %>%
  get.adjacency()

which gives

[1,]  1  6 10
[2,]  6  5 14
[3,] 10 14  9

data

mat <- structure(c(1L, 4L, 7L, 2L, 5L, 8L, 3L, 6L, 9L), .Dim = c(3L, 3L))
ThomasIsCoding
  • 96,636
  • 9
  • 24
  • 81