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 t
ranspose
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
How to See All Rows of a Data Frame in a Jupyter Notebook with an R Kernel
Removing Particular Character in a Column in R
Extract Date from Given String in R
How to Plot a List of Vectors with Different Lengths
Create Columns from Column of List in Data.Table
Extract Certain Files from .Zip
Adding Labels on Curves in Glmnet Plot in R
Loop Through a Series of Qplots
R: Interpolation of Nas by Group
How to Increase Smoothness of Spheres3D in Rgl
R Ggplot Ordering Bars in "Barplot-Like " Plot
Why Does Mapply Not Return Date-Objects
Plot Line and Bar Graph (With Secondary Axis for Line Graph) Using Ggplot
Usage of Uioutput in Multiple Menuitems in R Shiny Dashboard
R: Formatting Plotly Hover Text