Get upper triangular matrix from nonsymmetric matrix

Viewed 716

Is there an easy way to retrieve the upper(or lower) triangular matrix of a nonsymmetric matrix in R? For a symmetric matrix, this can be achieved using mat[upper.tri(mat)], but how about for a non-symmetric matrix? Here the definition of an upper triangular matrix is like this: if a cell having more than 1/2 of its part belongs to the upper right corner of the matrix delimited by the diagonal line, then this cell belongs to the upper triangular matrix (e.g., the red part in the figure).

Thanks. enter image description here

1 Answers

It's actually not so difficult:

mat[nrow(mat) * (2 * col(mat) - 1) / (2 * ncol(mat)) - row(mat) > -1/2]
# [1]  4  7 10 11 13 14 15

Imagine that your picture is the upper right quarter of the R^2 space. That is, the lower left corner corresponds to (0,0), and so on. Let nc and nr correspond do the number of columns and rows in your matrix, respectively. Also, let c and r correspond to the column and row of a particular cell.

It's easy to see that the equation of the diagonal line is y = nr - nr / nc * x in the usual notation. What is left is computing the area corresponding to each (c,r) cell. The upper line of this cell is at the level y = nr - r + 1 and it goes from x = c - 1 to x = c. Whenever this area is greater than 1/2, we include this cell to the answer. The matrix of those areas is given by

nrow(mat) * (2 * col(mat) - 1) / (2 * ncol(mat)) - row(mat) + 1

While the matrix is not square, there is still a lot of symmetry and, if the matrix were huge, you could exploit that and compute the areas for only 25%~ of the cells, but I assume that's not the case here.

Due to this symmetry, the lower triangular matrix is also very easy to get:

mat[nrow(mat) * (2 * col(mat) - 1) / (2 * ncol(mat)) - row(mat) < -1/2]
# [1]  1  2  3  5  6  9 12
Related