Copy upper triangle to lower triangle in a python matrix
Question:
iluropoda_melanoleuca bos_taurus callithrix_jacchus canis_familiaris
ailuropoda_melanoleuca 0 84.6 97.4 44
bos_taurus 0 0 97.4 84.6
callithrix_jacchus 0 0 0 97.4
canis_familiaris 0 0 0 0
This is a short version of the python matrix I have. I have the information in the upper triangle. Is there an easy function to copy the upper triangle to the down triangle of the matrix?
Answers:
If I understand the question correctly, I believe this will work
for i in range(num_rows):
for j in range(i, num_cols):
matrix[j][i] = matrix[i][j]
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
Heres a better one i guess :
>>> a = np.arange(16).reshape(4, 4)
>>> print(a)
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15]])
>>> iu = np.triu_indices(4,1)
>>> il = (iu[1],iu[0])
>>> a[il]=a[iu]
>>> a
array([[ 0, 1, 2, 3],
[ 1, 5, 6, 7],
[ 2, 6, 10, 11],
[ 3, 7, 11, 15]])
The easiest AND FASTEST (no loop) way to do this for NumPy arrays is the following:
The following is ~3x faster for 100×100 matrices compared to the accepted answer and roughly the same speed for 10×10 matrices.
import numpy as np
X= np.array([[0., 2., 3.],
[0., 0., 6.],
[0., 0., 0.]])
X = X + X.T - np.diag(np.diag(X))
print(X)
#array([[0., 2., 3.],
# [2., 0., 6.],
# [3., 6., 0.]])
Note that the matrix must either be upper triangular to begin with or it should be made upper triangular as follows.
rng = np.random.RandomState(123)
X = rng.randomint(10, size=(3, 3))
print(X)
#array([[2, 2, 6],
# [1, 3, 9],
# [6, 1, 0]])
X = np.triu(X)
X = X + X.T - np.diag(np.diag(X))
print(X)
#array([[2, 2, 6],
# [2, 3, 9],
# [6, 9, 0]])
If U is an upper triangular matrix, you can use triu and transpose to make it symmetric:
LDU = triu(U,1)+U.T
def inmatrix(m,n):#input Matrix Function
a=[]
for i in range(m):
b=[]
for j in range(n):
elm=int(input("Enter number in Pocket ["+str(i)+"]["+str(j)+"] "))
b.append(elm)
a.append(b)
return a
def Matrix(a):#print Matrix Function
for i in range(len(a)):
for j in range(len(a[0])):
print(a[i][j],end=" ")
print()
m=int(input("Enter number of row "))
n=int(input("Enter number of column"))
a=inmatrix(m,n) #call input Matrix function
Matrix(a)#print Matrix
t=[]#create Blank list
for i in range(m):
for j in range(n):
if i>j:#check upper triangular Elements
t.append(a[i][j])#add them in a list
k=0#variable for list
for i in range(m):
for j in range(n):
if i<j:
a[i][j]=t[k]copy list item to lower triangular
k=k+1
Matrix(a)# print Matrix after change
iluropoda_melanoleuca bos_taurus callithrix_jacchus canis_familiaris
ailuropoda_melanoleuca 0 84.6 97.4 44
bos_taurus 0 0 97.4 84.6
callithrix_jacchus 0 0 0 97.4
canis_familiaris 0 0 0 0
This is a short version of the python matrix I have. I have the information in the upper triangle. Is there an easy function to copy the upper triangle to the down triangle of the matrix?
If I understand the question correctly, I believe this will work
for i in range(num_rows):
for j in range(i, num_cols):
matrix[j][i] = matrix[i][j]
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
Heres a better one i guess :
>>> a = np.arange(16).reshape(4, 4)
>>> print(a)
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15]])
>>> iu = np.triu_indices(4,1)
>>> il = (iu[1],iu[0])
>>> a[il]=a[iu]
>>> a
array([[ 0, 1, 2, 3],
[ 1, 5, 6, 7],
[ 2, 6, 10, 11],
[ 3, 7, 11, 15]])
The easiest AND FASTEST (no loop) way to do this for NumPy arrays is the following:
The following is ~3x faster for 100×100 matrices compared to the accepted answer and roughly the same speed for 10×10 matrices.
import numpy as np
X= np.array([[0., 2., 3.],
[0., 0., 6.],
[0., 0., 0.]])
X = X + X.T - np.diag(np.diag(X))
print(X)
#array([[0., 2., 3.],
# [2., 0., 6.],
# [3., 6., 0.]])
Note that the matrix must either be upper triangular to begin with or it should be made upper triangular as follows.
rng = np.random.RandomState(123)
X = rng.randomint(10, size=(3, 3))
print(X)
#array([[2, 2, 6],
# [1, 3, 9],
# [6, 1, 0]])
X = np.triu(X)
X = X + X.T - np.diag(np.diag(X))
print(X)
#array([[2, 2, 6],
# [2, 3, 9],
# [6, 9, 0]])
If U is an upper triangular matrix, you can use triu and transpose to make it symmetric:
LDU = triu(U,1)+U.T
def inmatrix(m,n):#input Matrix Function
a=[]
for i in range(m):
b=[]
for j in range(n):
elm=int(input("Enter number in Pocket ["+str(i)+"]["+str(j)+"] "))
b.append(elm)
a.append(b)
return a
def Matrix(a):#print Matrix Function
for i in range(len(a)):
for j in range(len(a[0])):
print(a[i][j],end=" ")
print()
m=int(input("Enter number of row "))
n=int(input("Enter number of column"))
a=inmatrix(m,n) #call input Matrix function
Matrix(a)#print Matrix
t=[]#create Blank list
for i in range(m):
for j in range(n):
if i>j:#check upper triangular Elements
t.append(a[i][j])#add them in a list
k=0#variable for list
for i in range(m):
for j in range(n):
if i<j:
a[i][j]=t[k]copy list item to lower triangular
k=k+1
Matrix(a)# print Matrix after change