Repeat list to create numpy array of specified shape

Viewed 201

I have a list of values with length 10:

p = [1, 2, ..., 10]

This list corresponds to the second dimension of a 4D array (called T):

Tshp = np.shape(T)
print(Tshp)
(20, 10, 30, 40)

I need to create an array of the same size as T with the list p repeated over all the other dimensions.

I have tried:

new_p = np.tile(p, [Tshp[0], Tshp[2], Tshp[3]])

But I get something of size:

print(np.shape(new_p))
(20, 30, 400)
2 Answers

The simplest way is likely using np.full. The key here is to use broadcasting to make sure that the right dimensions are filled:

result = np.full(T.shape, p.reshape(1, -1, 1, 1))

You can acheive a similar result with tile by a similar operation:

s = list(T.shape)
s[1] = 1
result = np.tile(p.reshape(1, -1, 1, 1), s)

Assignment works too:

result = np.empty_like(T)
T[:] = p.reshape(1, -1, 1, 1)

You can even use direct broadcasting:

result = np.broadcast_to(p.reshape(1, -1, 1, 1), T.shape)

This is a version that does not copy the data at all.

In all cases, I assumed that you converted p to an array, e.g. with p = np.array(p). If not, substitute p.reshape(...) with np.reshape(p, (...)). You can also omit the leading unit dimensions, since broadcasting aligns to the right. For example, in all cases 1, -1, 1,1 can be replaced with just -1, 1, 1.

In [42]: p = np.arange(1,11)
In [43]: p.shape
Out[43]: (10,)
In [44]: T = np.zeros((20,10,30,40),int)

If we expand p to (10,1,1) shape, then by broadcasting it can be assigned to T, expanding to (1,10,1,1) and then to T.shape:

In [45]: T[:] = p[:,None,None]

To use tile, first expand p to 4d

In [48]: T2 = np.tile(p[None,:,None,None],(20,1,30,40))
In [49]: T2.shape
Out[49]: (20, 10, 30, 40)
In [50]: np.allclose(T,T2)
Out[50]: True
Related