我在平面列表(连续行)中有对称矩阵的上三角形条目(包括对角线),我想用它们来填充整个矩阵,包括下三角形。最快的方法是什么?
这是我目前的做法。对于这么简单的操作来说,似乎有很多工作。
import numpy as np
def utri2mat(utri,ntotal):
iu1 = np.triu_indices(ntotal)
ret = np.zeros([ntotal,ntotal])
ret[iu1] = utri
ret = ret + ret.transpose() - np.diag(ret.diagonal())
return ret
答案 0 :(得分:1)
此版本略有不同:
import numpy as np
def utri2mat(utri):
n = int(-1 + np.sqrt(1 + 8*len(utri))) // 2
iu1 = np.triu_indices(n)
ret = np.empty((n, n))
ret[iu1] = utri
ret.T[iu1] = utri
return ret
我替换了
ret = ret + ret.transpose() - np.diag(ret.diagonal())
将utri
直接分配给ret
的转置:
ret.T[iu1] = utri
我还删除了参数ntotal
,而是根据n
的长度计算utri
必须的内容。
答案 1 :(得分:1)
受https://isocpp.org/wiki/faq/inline-functions#where-to-put-inline-keyword的启发,您可以使用this solution
来设置元素,因此可能非常有效。这是实现它的一种方法 -
def mask_based_utri2mat(utri,ntotal):
# Setup output array
out = np.empty((ntotal,ntotal))
# Create upper triang. mask
mask = np.triu(np.ones((ntotal,ntotal),dtype=bool))
# Set upper triang. elements with mask
out[mask] = utri
# Set lower triang. elements with transposed mask
out.T[mask] = utri
return out
运行时测试 -
In [52]: # Inputs
...: ntotal = 100
...: utri = np.random.rand(np.triu_indices(ntotal)[0].size)
...:
In [53]: np.allclose(mask_based_utri2mat(utri,ntotal),utri2mat(utri,ntotal))
Out[53]: True
In [54]: %timeit utri2mat(utri,ntotal)
1000 loops, best of 3: 270 µs per loop
In [55]: %timeit mask_based_utri2mat(utri,ntotal)
10000 loops, best of 3: 127 µs per loop
In [56]: # Inputs
...: ntotal = 1000
...: utri = np.random.rand(np.triu_indices(ntotal)[0].size)
...:
In [57]: np.allclose(mask_based_utri2mat(utri,ntotal),utri2mat(utri,ntotal))
Out[57]: True
In [58]: %timeit utri2mat(utri,ntotal)
10 loops, best of 3: 53.9 ms per loop
In [59]: %timeit mask_based_utri2mat(utri,ntotal)
100 loops, best of 3: 15.1 ms per loop
答案 2 :(得分:1)
这是我提出的更快,也可能更好的方法,从平面值制作对称矩阵:
def make_sym(val, n):
# uses boolean mask
# uses the same lower tri as np.triu
mask = ~np.tri(5,k=-1,dtype=bool)
out = np.zeros((n,n),dtype=val.dtype)
out[mask] = val
out.T[mask] = val
return out
测试:
In [939]: val=np.arange(1,16)
In [940]: make_sym(val, 5)
Out[940]:
array([[ 1, 2, 3, 4, 5],
[ 2, 6, 7, 8, 9],
[ 3, 7, 10, 11, 12],
[ 4, 8, 11, 13, 14],
[ 5, 9, 12, 14, 15]])
与其他答案一样,它使用out.T[]
指定下三角。
Warren的回答使用np.triu_indices
,即where
值。这种类型的索引比布尔掩码慢一点。
但是我注意到Divakar使用的np.triu
在早期的numpy
版本中没有返回布尔掩码(例如1.9)。这促使我深入研究这个问题。
在1.10中,该功能被重写为:
mask = np.tri(*m.shape[-2:], k=k-1, dtype=bool)
return np.where(mask, np.zeros(1, m.dtype), m)
通过将where
替换为~mask
,我获得了一些速度。同样的结果,但只是削减了一个中间步骤。
答案 3 :(得分:0)
假设您有一个包含对称矩阵的上三角值(n x n)的向量,则可以按如下所示重新构建完整的矩阵:
import numpy as np
# dimension of the full matrix
n = 80
# artificial upper triangle entries n(n-1) / 2 if matrix is symmetric
entries = np.array(range((80*79) / 2))
full_matrix = np.zeros((n,n))
inds = np.triu_indices_from(full_matrix, k = 1)
full_matrix[inds] = entries
full_matrix[(inds[1], inds[0])] = entries
print(full_matrix)
验证:
np.allclose(full_matrix, full_matrix.T)