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 : a Out:  array([10, 20, 40, 46, 33, 14, 12, 46, 52, 30, 59, 18, 11, 22, 30,  2, 11,        58, 22, 72, 12])  In : fill_lower_diag(a) Out:  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 : np.random.seed(0)  In : n = 5000  In : a = np.random.randint(0,9,n*(n+1)/2)  In : %timeit tril_indices_app(a) #@Brenlla's solution 1 loop, best of 3: 218 ms per loop  In : %timeit fill_lower_diag(a) # From this post 10 loops, best of 3: 43.1 ms per loop