Instantiate a matrix with x zeros and the rest ones Instantiate a matrix with x zeros and the rest ones numpy numpy

Instantiate a matrix with x zeros and the rest ones


Here's one way. n is the number of columns in the result. The number of rows is determined by len(arr).

In [29]: n = 5In [30]: arr = np.array([1, 2, 3, 0, 3])In [31]: (np.arange(n) >= arr[:, np.newaxis]).astype(int)Out[31]: array([[0, 1, 1, 1, 1],       [0, 0, 1, 1, 1],       [0, 0, 0, 1, 1],       [1, 1, 1, 1, 1],       [0, 0, 0, 1, 1]])

There are two parts to the explanation of how this works. First, how to create a row with m zeros and n-m ones? For that, we use np.arange to create a row with values [0, 1, ..., n-1]`:

In [35]: nOut[35]: 5In [36]: np.arange(n)Out[36]: array([0, 1, 2, 3, 4])

Next, compare that array to m:

In [37]: m = 2In [38]: np.arange(n) >= mOut[38]: array([False, False,  True,  True,  True], dtype=bool)

That gives an array of boolean values; the first m values are False and the rest are True. By casting those values to integers, we get an array of 0s and 1s:

In [39]: (np.arange(n) >= m).astype(int)Out[39]: array([0, 0, 1, 1, 1])

To perform this over an array of m values (your arr), we use broadcasting; this is the second key idea of the explanation.

Note what arr[:, np.newaxis] gives:

In [40]: arrOut[40]: array([1, 2, 3, 0, 3])In [41]: arr[:, np.newaxis]Out[41]: array([[1],       [2],       [3],       [0],       [3]])

That is, arr[:, np.newaxis] reshapes arr into a 2-d array with shape (5, 1). (arr.reshape(-1, 1) could have been used instead.) Now when we compare this to np.arange(n) (a 1-d array with length n), broadcasting kicks in:

In [42]: np.arange(n) >= arr[:, np.newaxis]Out[42]: array([[False,  True,  True,  True,  True],       [False, False,  True,  True,  True],       [False, False, False,  True,  True],       [ True,  True,  True,  True,  True],       [False, False, False,  True,  True]], dtype=bool)

As @RogerFan points out in his comment, this is basically an outer product of the arguments, using the >= operation.

A final cast to type int gives the desired result:

In [43]: (np.arange(n) >= arr[:, np.newaxis]).astype(int)Out[43]: array([[0, 1, 1, 1, 1],       [0, 0, 1, 1, 1],       [0, 0, 0, 1, 1],       [1, 1, 1, 1, 1],       [0, 0, 0, 1, 1]])


Not as concise as I wanted (I was experimenting with mask_indices), but this will also do the work:

>>> n = 3>>> zeros = [2, 1, 3, 0]>>> numpy.array([[0] * zeros[i] + [1]*(n - zeros[i]) for i in range(len(zeros))])array([[0, 0, 1],       [0, 1, 1],       [0, 0, 0],       [1, 1, 1]])>>>

Works very simple: concatenates multiplied required number of times, one-element lists [0] and [1], creating the array row by row.