I have the upper triangle entries (including diagonal) of a symmetric matrix in a flat list (concatenated rows), and I want to use them to fill in the full matrix, including the
Here's my nomination for a faster, and possibly better, way to make a symmetric matrix from flat values:
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
testing:
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]])
Like the other answers it uses out.T[]
to assign the lower triangle.
Warren's answer uses np.triu_indices
, which are the where
values. This type of indexing is a bit slower than boolean masking.
But as I noted the np.triu
that Divakar uses does not return a boolean mask in earlier numpy
versions (e.g. 1.9). This is what prompted me to dig into the issue.
In 1.10 this function was rewritten as:
mask = np.tri(*m.shape[-2:], k=k-1, dtype=bool)
return np.where(mask, np.zeros(1, m.dtype), m)
I gain a bit of speed by replacing the where
with ~mask
. Same result, but just cutting out an intermediate step.