4

Say I have this matrices:

emp <- matrix(nrow = 13, ncol = 13)
emp2 <- matrix(nrow = 13, ncol = 13)

emp[lower.tri(emp)] <- 2
emp2[lower.tri(emp)] <- 3

And I want to combine them so below the diagonal, I have all values = 2 and above all values = 3. I have managed to produce this as such (then the result is just the emp matrix).

emp[upper.tri(emp)] <- t(emp2[lower.tri(emp2)])

However, now I would like to store the result and make a function for this (after all the matrices I want to use are inside elements of a list). Do you know how can I store this in a new matrix? Or perhaps a better alternative.

I hope I have provided a reproducible enough example, otherwise, let me know.

Thank you!

1
  • If dimensions are equal consider storing in arrays then! Commented Jun 2 at 17:35

3 Answers 3

2

I think you can use pmax with option na.rm = TRUE

> pmax(emp, t(emp2), na.rm = TRUE)
      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13]
 [1,]   NA    3    3    3    3    3    3    3    3     3     3     3     3
 [2,]    2   NA    3    3    3    3    3    3    3     3     3     3     3
 [3,]    2    2   NA    3    3    3    3    3    3     3     3     3     3
 [4,]    2    2    2   NA    3    3    3    3    3     3     3     3     3
 [5,]    2    2    2    2   NA    3    3    3    3     3     3     3     3
 [6,]    2    2    2    2    2   NA    3    3    3     3     3     3     3
 [7,]    2    2    2    2    2    2   NA    3    3     3     3     3     3
 [8,]    2    2    2    2    2    2    2   NA    3     3     3     3     3
 [9,]    2    2    2    2    2    2    2    2   NA     3     3     3     3
[10,]    2    2    2    2    2    2    2    2    2    NA     3     3     3
[11,]    2    2    2    2    2    2    2    2    2     2    NA     3     3
[12,]    2    2    2    2    2    2    2    2    2     2     2    NA     3
[13,]    2    2    2    2    2    2    2    2    2     2     2     2    NA
Sign up to request clarification or add additional context in comments.

1 Comment

This is the best answer, thank you
2

Just wrap the logic in a function and Map over the list.

> fx <- \(e1, e2) {
+   e1[upper.tri(e1)] <- t(e2[lower.tri(e2)])
+   e1
+ }
> lst <- list(list(emp, emp, emp), list(emp2, emp2, emp2))
> Map(fx, lst[[1]], lst[[2]])
[[1]]
      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13]
 [1,]   NA    3    3    3    3    3    3    3    3     3     3     3     3
 [2,]    2   NA    3    3    3    3    3    3    3     3     3     3     3
 [3,]    2    2   NA    3    3    3    3    3    3     3     3     3     3
 [4,]    2    2    2   NA    3    3    3    3    3     3     3     3     3
 [5,]    2    2    2    2   NA    3    3    3    3     3     3     3     3
 [6,]    2    2    2    2    2   NA    3    3    3     3     3     3     3
 [7,]    2    2    2    2    2    2   NA    3    3     3     3     3     3
 [8,]    2    2    2    2    2    2    2   NA    3     3     3     3     3
 [9,]    2    2    2    2    2    2    2    2   NA     3     3     3     3
[10,]    2    2    2    2    2    2    2    2    2    NA     3     3     3
[11,]    2    2    2    2    2    2    2    2    2     2    NA     3     3
[12,]    2    2    2    2    2    2    2    2    2     2     2    NA     3
[13,]    2    2    2    2    2    2    2    2    2     2     2     2    NA

[[2]]
      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13]
 [1,]   NA    3    3    3    3    3    3    3    3     3     3     3     3
 [2,]    2   NA    3    3    3    3    3    3    3     3     3     3     3
 [3,]    2    2   NA    3    3    3    3    3    3     3     3     3     3
 [4,]    2    2    2   NA    3    3    3    3    3     3     3     3     3
 [5,]    2    2    2    2   NA    3    3    3    3     3     3     3     3
 [6,]    2    2    2    2    2   NA    3    3    3     3     3     3     3
 [7,]    2    2    2    2    2    2   NA    3    3     3     3     3     3
 [8,]    2    2    2    2    2    2    2   NA    3     3     3     3     3
 [9,]    2    2    2    2    2    2    2    2   NA     3     3     3     3
[10,]    2    2    2    2    2    2    2    2    2    NA     3     3     3
[11,]    2    2    2    2    2    2    2    2    2     2    NA     3     3
[12,]    2    2    2    2    2    2    2    2    2     2     2    NA     3
[13,]    2    2    2    2    2    2    2    2    2     2     2     2    NA

[[3]]
      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13]
 [1,]   NA    3    3    3    3    3    3    3    3     3     3     3     3
 [2,]    2   NA    3    3    3    3    3    3    3     3     3     3     3
 [3,]    2    2   NA    3    3    3    3    3    3     3     3     3     3
 [4,]    2    2    2   NA    3    3    3    3    3     3     3     3     3
 [5,]    2    2    2    2   NA    3    3    3    3     3     3     3     3
 [6,]    2    2    2    2    2   NA    3    3    3     3     3     3     3
 [7,]    2    2    2    2    2    2   NA    3    3     3     3     3     3
 [8,]    2    2    2    2    2    2    2   NA    3     3     3     3     3
 [9,]    2    2    2    2    2    2    2    2   NA     3     3     3     3
[10,]    2    2    2    2    2    2    2    2    2    NA     3     3     3
[11,]    2    2    2    2    2    2    2    2    2     2    NA     3     3
[12,]    2    2    2    2    2    2    2    2    2     2     2    NA     3
[13,]    2    2    2    2    2    2    2    2    2     2     2     2    NA

2 Comments

Thank you! I hope I do not bother you by asking, but I do not understand the "\" in the function call. Could you explain it? Again thanks
@DanielEstévez \(x) is shorthand for function(x), actually since R4.1.
-1

I actually found a better solution and I wanted to post it here. In the previous example, it did work because both matrices were composed of single values. But the function is actually not working as it should. It should mirror the lower triangle of the second matrix in the upper triangle of the first one.

You can check this simulating matrices with difference values:

mat1 <- matrix(nrow = 10, ncol = 10)
mat2 <- matrix(nrow = 10, ncol = 10)

mat1[lower.tri(mat1)] <- runif(n = 10, min = 0, max = 1)
mat2[lower.tri(mat2)] <- runif(n = 10, min = 0, max = 1)

fx <- function(mat1, mat2) {
  n <- nrow(mat1)
  for (i in 1:n) {
    for (j in 1:n) {
      if (i > j) {
        mat1[j, i] <- mat2[i, j]
      }
    }
  }
  mat1
}

mat3 <- fx(mat1, mat2)

Note. We can see that in mat3 now the upper triangle corresponds to t(mat2).

1 Comment

"better"? In R, we do not need a for-for-if logic to do what your fx does. It's inefficient and needless. As a side note, upper.tri() and lower.tri() have diag-arg.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.