Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
565 views
in Technique[技术] by (71.8m points)

python - transform the upper/lower triangular part of a symmetric matrix (2D array) into a 1D array and return it to the 2D format

In this question it is explained how to access the lower and upper triagular parts of a given matrix, say:

m = np.matrix([[11, 12, 13],
               [21, 22, 23],
               [31, 32, 33]])

Here I need to transform the matrix in a 1D array, which can be done doing:

indices = np.triu_indices_from(m)
a = np.asarray( m[indices] )[-1]
#array([11, 12, 13, 22, 23, 33])

After doing a lot of calculations with a, changing its values, it will be used to fill a symmetric 2D array:

new = np.zeros(m.shape)
for i,j in enumerate(zip(*indices)):
    new[j]=a[i]
    new[j[1],j[0]]=a[i]

Returning:

array([[ 11.,  12.,  13.],
       [ 12.,  22.,  23.],
       [ 13.,  23.,  33.]])

Is there a better way to accomplish this? More especifically, avoiding the Python loop to rebuild the 2D array?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The fastest and smartest way to put back a vector into a 2D symmetric array is to do this:


Case 1: No offset (k=0) i.e. upper triangle part includes the diagonal

import numpy as np

X = np.array([[1,2,3],[4,5,6],[7,8,9]])
#array([[1, 2, 3],
#       [4, 5, 6],
#       [7, 8, 9]])

#get the upper triangular part of this matrix
v = X[np.triu_indices(X.shape[0], k = 0)]
print(v)
# [1 2 3 5 6 9]

# put it back into a 2D symmetric array
size_X = 3
X = np.zeros((size_X,size_X))
X[np.triu_indices(X.shape[0], k = 0)] = v
X = X + X.T - np.diag(np.diag(X))
#array([[1., 2., 3.],
#       [2., 5., 6.],
#       [3., 6., 9.]])

The above will work fine even if instead of numpy.array you use numpy.matrix.


Case 2: With offset (k=1) i.e. upper triangle part does NOT include the diagonal

import numpy as np

X = np.array([[1,2,3],[4,5,6],[7,8,9]])
#array([[1, 2, 3],
#       [4, 5, 6],
#       [7, 8, 9]])

#get the upper triangular part of this matrix
v = X[np.triu_indices(X.shape[0], k = 1)] # offset
print(v)
# [2 3 6]

# put it back into a 2D symmetric array
size_X = 3
X = np.zeros((size_X,size_X))
X[np.triu_indices(X.shape[0], k = 1)] = v
X = X + X.T
#array([[0., 2., 3.],
#       [2., 0., 6.],
#       [3., 6., 0.]])

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...