How to replace values in a matrix below the diagonal from bottom left to top right?

Viewed 237

Given is a matrix (no assumptions are made about its dimensions) which contains zeros below the diagonal that runs from the bottom left to the upper right corner:

m <- matrix(data = c(2, 1, 8, 9, 1,
                     5, 0, 4, 3, 6,
                     7, 1, 2, 5, 0,
                     3, 1, 0, 0, 0,
                     2, 8, 0, 0, 0,
                     9, 0, 0, 0, 0),
        nrow = 6,
        ncol = 5,
        byrow = TRUE)

The question is how to replace all these zeros below the diagonal with NA? The result should be the following:

       [,1] [,2] [,3] [,4] [,5]
 [1,]    2    1    8    9    1
 [2,]    5    0    4    3    6
 [3,]    7    1    2    5   NA
 [4,]    3    1    0   NA   NA
 [5,]    2    8   NA   NA   NA
 [6,]    9   NA   NA   NA   NA

The matrix may contain zeros elsewhere (on or above the diagonal). These zeros should not be replaced.

3 Answers

Use the base R functions row and col:

m[row(m) + col(m) > nrow(m) + 1] <- NA

Which gives the desired output:

> m
      [,1] [,2] [,3] [,4] [,5]
 [1,]    2    1    8    9    1
 [2,]    5    2    4    3    6
 [3,]    7    1    2    5   NA
 [4,]    3    1    3   NA   NA
 [5,]    2    8   NA   NA   NA
 [6,]    9   NA   NA   NA   NA

The trick is to add the row and column number of each cell. All cells that have a number greater than the number of rows plus 1 then correspond to the cells below the diagonal running from the bottom left to the upper right corner.

Try upper.tri like below

> replace(m, upper.tri(m)[nrow(m):1, ], NA)
     [,1] [,2] [,3] [,4] [,5]
[1,]    2    1    8    9    1
[2,]    5    0    4    3    6
[3,]    7    1    2    5   NA
[4,]    3    1    0   NA   NA
[5,]    2    8   NA   NA   NA
[6,]    9   NA   NA   NA   NA

An option with ^ and NA

m * NA^upper.tri(m)[rev(seq(nrow(m))),]
  [,1] [,2] [,3] [,4] [,5]
[1,]    2    1    8    9    1
[2,]    5    0    4    3    6
[3,]    7    1    2    5   NA
[4,]    3    1    0   NA   NA
[5,]    2    8   NA   NA   NA
[6,]    9   NA   NA   NA   NA
Related