Python 如何在NumPy中将三角形矩阵转换为正方形?

Python 如何在NumPy中将三角形矩阵转换为正方形?,python,arrays,numpy,matrix,linear-algebra,Python,Arrays,Numpy,Matrix,Linear Algebra,我在一个冗余的完整矩阵上做一些计算(即可以是一个三角形矩阵而不丢失信息)。我意识到我只能计算三角形的较低部分以获得更快的结果。完成后,如何将下部三角形投影到上部三角形 换句话说,我怎样才能反转np.tril方法 print DF_var.as_matrix() # [[1 1 0 1 1 1 0 1 0 0 0] # [1 1 1 1 1 0 1 0 1 1 1] # [0 1 1 0 0 0 0 0 0 0 0] # [1 1 0 1 0 0 0 0 0 0 0] # [1 1 0 0

我在一个冗余的完整矩阵上做一些计算(即可以是一个三角形矩阵而不丢失信息)。我意识到我只能计算三角形的较低部分以获得更快的结果。完成后,如何将下部三角形投影到上部三角形

换句话说,我怎样才能反转
np.tril
方法

print DF_var.as_matrix()
# [[1 1 0 1 1 1 0 1 0 0 0]
#  [1 1 1 1 1 0 1 0 1 1 1]
#  [0 1 1 0 0 0 0 0 0 0 0]
#  [1 1 0 1 0 0 0 0 0 0 0]
#  [1 1 0 0 1 0 0 0 0 0 0]
#  [1 0 0 0 0 1 1 0 0 0 0]
#  [0 1 0 0 0 1 1 0 0 0 0]
#  [1 0 0 0 0 0 0 1 1 0 0]
#  [0 1 0 0 0 0 0 1 1 0 0]
#  [0 1 0 0 0 0 0 0 0 1 0]
#  [0 1 0 0 0 0 0 0 0 0 1]]
print np.tril(DF_var.as_matrix())
# [[1 0 0 0 0 0 0 0 0 0 0]
#  [1 1 0 0 0 0 0 0 0 0 0]
#  [0 1 1 0 0 0 0 0 0 0 0]
#  [1 1 0 1 0 0 0 0 0 0 0]
#  [1 1 0 0 1 0 0 0 0 0 0]
#  [1 0 0 0 0 1 0 0 0 0 0]
#  [0 1 0 0 0 1 1 0 0 0 0]
#  [1 0 0 0 0 0 0 1 0 0 0]
#  [0 1 0 0 0 0 0 1 1 0 0]
#  [0 1 0 0 0 0 0 0 0 1 0]
#  [0 1 0 0 0 0 0 0 0 0 1]]

如何将其转换回完整矩阵?

由于矩阵是对称的,您可以执行以下操作:

m = np.array([1,1,0,1,1,1,0,1,1]).reshape((3,3))

# after some computation you get x
x = np.tril(m)

m_recomposed = x + x.transpose() - np.diag(np.diag(x))

#array([[1, 1, 0],
#       [1, 1, 1],
#       [0, 1, 1]])

#In [152]: np.array_equal(m, m_recomposed)
#Out[152]: True

假设
A
作为输入数组,下面列出了几种方法

方法#1:
a的转置版本上使用
np.triu
-

np.triu(A.T,1) + A
方法#2:避免使用A.T和A之间的直接求和,然后索引以设置对角线元素的
np.triu
-

out = A.T + A
idx = np.arange(A.shape[0])
out[idx,idx] = A[idx,idx]
out = A.T + A
mask = np.eye(out.shape[0],dtype=bool)
out[mask] = A[mask]
方法#3:与前一种方法相同,但使用内置索引进行压缩-

out = A.T + A
np.fill_diagonal(out,np.diag(A))
方法#4:与前一种方法相同,但使用布尔索引来设置对角线元素-

out = A.T + A
idx = np.arange(A.shape[0])
out[idx,idx] = A[idx,idx]
out = A.T + A
mask = np.eye(out.shape[0],dtype=bool)
out[mask] = A[mask]
方法#5:对带有
np.where
-

np.where(np.eye(A.shape[0],dtype=bool),A,A.T+A)
np.where(np.triu(np.ones(A.shape[0],dtype=bool),1),A.T,A)
方法#6:对所有元素使用基于掩码的选择,其中
np.where
-

np.where(np.eye(A.shape[0],dtype=bool),A,A.T+A)
np.where(np.triu(np.ones(A.shape[0],dtype=bool),1),A.T,A)

运行时测试

功能-

def func1(A):
    return np.triu(A.T,1) + A

def func2(A):
    out = A.T + A
    idx = np.arange(A.shape[0])
    out[idx,idx] = A[idx,idx]
    return out

def func3(A):
    out = A.T + A
    np.fill_diagonal(out,np.diag(A))
    return out

def func4(A):
    out = A.T + A
    mask = np.eye(out.shape[0],dtype=bool)
    out[mask] = A[mask]
    return out

def func5(A):
    return np.where(np.eye(A.shape[0],dtype=bool),A,A.T+A)

def func6(A):
    return np.where(np.triu(np.ones(A.shape[0],dtype=bool),1),A.T,A)
时间安排-

In [140]: # Input array
     ...: N = 5000
     ...: A = np.tril(np.random.randint(0,9,(N,N)))
     ...: 

In [141]: %timeit func1(A)
     ...: %timeit func2(A)
     ...: %timeit func3(A)
     ...: %timeit func4(A)
     ...: %timeit func5(A)
     ...: %timeit func6(A)
     ...: 
1 loops, best of 3: 617 ms per loop
1 loops, best of 3: 354 ms per loop
1 loops, best of 3: 354 ms per loop
1 loops, best of 3: 395 ms per loop
1 loops, best of 3: 597 ms per loop
1 loops, best of 3: 440 ms per loop

看起来#2和#3方法非常有效

哇@divakar,这是一个难以置信的全面答案。看到所有这些解决这个问题的方法真的很有帮助。我一定会一遍又一遍地提到这个。与表演的比较真的很好,谢谢你的回答!