How to Replace Lower/Upper Triangular Elements of a Matrix

How to replace lower/upper triangular elements of a matrix?

Are lower.tri and upper.tri what you are looking for ?

These functions are in R base.

Replacing upper triangular matrix elements in row order

The value insertions are in column order (in matrix, data.frame). We may assign on the lower.tri and then get the transpose

ex_mat_new[lower.tri(ex_mat_new)] <- rank(-(t(ex_mat)[lower.tri(ex_mat)]))
ex_mat_new <- t(ex_mat_new)
ex_mat_new[lower.tri(ex_mat_new)] <- ex_mat[lower.tri(ex_mat)]

-output

> ex_mat_new
[,1] [,2] [,3] [,4]
[1,] 0.4270634 2.0000000 5.0000000 3.0000000
[2,] 2.0556220 1.1157322 1.0000000 6.0000000
[3,] 1.2252602 0.1063053 0.6396099 4.0000000
[4,] 0.3614062 1.1118661 0.5000143 0.2491543

or this can be done in a single line with replace

t(replace(t(ex_mat), lower.tri(ex_mat), rank(-(t(ex_mat)[lower.tri(ex_mat)]))))

-output

       [,1]      [,2]      [,3]      [,4]
[1,] 0.4270634 2.0000000 5.0000000 3.0000000
[2,] 2.0556220 1.1157322 1.0000000 6.0000000
[3,] 1.2252602 0.1063053 0.6396099 4.0000000
[4,] 0.3614062 1.1118661 0.5000143 0.2491543

data

ex_mat <- structure(c(0.4270634, 2.055622, 1.2252602, 0.3614062, 2.192089, 
1.1157322, 0.1063053, 1.1118661, 0.5647472, 2.6723637, 0.6396099,
0.5000143, 1.7149861, 0.3155507, 0.7903348, 0.2491543), .Dim = c(4L,
4L), .Dimnames = list(NULL, NULL))

Conditionally replace matrix upper-triangle elements with lower-triangle

z <- matrix(c(0,1,2,0,0,1,0,0,0),nrow=3,ncol=3)
z[upper.tri(z) & t(z) == 1] = 1

works for me.

Note: your upperTriangel and lowerTriangle do not appear to be part of base. You might want to indicate which package they are from.

Copy upper triangle to lower triangle in a python matrix

To do this in NumPy, without using a double loop, you can use tril_indices. Note that depending on your matrix size, this may be slower that adding the transpose and subtracting the diagonal though perhaps this method is more readable.

>>> i_lower = np.tril_indices(n, -1)
>>> matrix[i_lower] = matrix.T[i_lower] # make the matrix symmetric

Be careful that you do not try to mix tril_indices and triu_indices as they both use row major indexing, i.e., this does not work:

>>> i_upper = np.triu_indices(n, 1)
>>> i_lower = np.tril_indices(n, -1)
>>> matrix[i_lower] = matrix[i_upper] # make the matrix symmetric
>>> np.allclose(matrix.T, matrix)
False

Extract upper or lower triangular part of a numpy matrix

Try numpy.triu (triangle-upper) and numpy.tril (triangle-lower).

Code example:

np.triu([[1,2,3],[4,5,6],[7,8,9],[10,11,12]])
array([[ 1, 2, 3],
[ 4, 5, 6],
[ 0, 8, 9],
[ 0, 0, 12]])

How can I to leave NA in upper triangle matrix?

You can use upper.tri as in

dt[upper.tri(dt, diag=FALSE)] <- NA

and change diag=FALSE to diag=TRUE to include diagonal

Giving an element from lower/upper triangular matrix

My solution might be equivalent to your’s, I haven’t checked:

index = N * i - ((i - 1) * i) / 2 + (j - i)

Here’s a complete Python test for it. I used Python because Numpy has triu_indices, which gives the upper-triangular indexes.

import numpy as np

def mksquare(N):
"""Make a square N by N matrix containing 0 .. N*N-1"""
return np.arange(N * N).reshape(N, N)

def mkinds(N):
"""Return all triu indexes for N by N matrix"""
return [(i,j) for i in range(N) for j in range(N) if i <= j]

def ij2linear(i, j, N):
"""Convert (i,j) 2D index to linear triu index for N by N array"""
return N * i - ((i - 1) * i) // 2 + (j - i)

def test(N):
"""Make sure my `mkinds` works for given N"""
arr = mksquare(N)
vec = arr[np.triu_indices(N)]

inds = mkinds(N)
expected = [arr[i, j] for (i, j) in inds]

actual = [vec[ij2linear(i, j, N)] for (i, j) in inds]

return np.all(np.equal(actual, expected))

"""Run `test` for a bunch of `N`s and make sure they're all right"""
print(all(map(test, range(2, 20))))
# prints True br>

Worth a blog post explaining how to arrive at this conclusion, but this’ll do for now .

Convert a matrix in R into a upper triangular/lower triangular matrix with those corresponding entries

To get the upper triangular matrix:

mat <- matrix(1:9, 3, 3)
mat[lower.tri(mat)] <- 0

To remove diagonal, use:

mat[lower.tri(mat,diag=TRUE)] <- 0 or mat[!upper.tri(mat)] <- 0 as suggested in the comments by Karolis.



Related Topics



Leave a reply



Submit