Convert 1d array to lower triangular matrix

  • A+
Category:Languages

I would like to convert a 1 dimensional array into a lower, zero diagonal matrix while keeping all the digits.

I am aware of numpy.tril function but it replaces some of the elements with zeros. I need to expand the matrix to contain all the original digits.

For example:

[10,20,40,46,33,14,12,46,52,30,59,18,11,22,30,2,11,58,22,72,12]

Should be

0 10 0 20 40 0 46 33 14 0 12 46 52 30 0 59 18 11 22 30 0 2 11 58 22 72 12 0 

 


With the input array holding all the values as required to fill up the lower diagonal places, here's one approach with masking -

def fill_lower_diag(a):     n = int(np.sqrt(len(a)*2))+1     mask = np.tri(n,dtype=bool, k=-1) # or np.arange(n)[:,None] > np.arange(n)     out = np.zeros((n,n),dtype=int)     out[mask] = a     return out 

Sample run -

In [82]: a Out[82]:  array([10, 20, 40, 46, 33, 14, 12, 46, 52, 30, 59, 18, 11, 22, 30,  2, 11,        58, 22, 72, 12])  In [83]: fill_lower_diag(a) Out[83]:  array([[ 0,  0,  0,  0,  0,  0,  0],        [10,  0,  0,  0,  0,  0,  0],        [20, 40,  0,  0,  0,  0,  0],        [46, 33, 14,  0,  0,  0,  0],        [12, 46, 52, 30,  0,  0,  0],        [59, 18, 11, 22, 30,  0,  0],        [ 2, 11, 58, 22, 72, 12,  0]]) 

Timings on large array with 5k x 5k shape -

In [146]: np.random.seed(0)  In [147]: n = 5000  In [148]: a = np.random.randint(0,9,n*(n+1)/2)  In [149]: %timeit tril_indices_app(a) #@Brenlla's solution 1 loop, best of 3: 218 ms per loop  In [151]: %timeit fill_lower_diag(a) # From this post 10 loops, best of 3: 43.1 ms per loop 

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: