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
Inspired by this solution, you can use boolean indexing to set elements and as such might be pretty efficient. Here's one way to implement it -
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
Runtime tests -
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