I'd like to repeat an array along multiple dimensions, such that it matches the dimensions of another array.
For example, lets put:
import numpy as np
a = np.arange(300)
b = np.zeros((300, 10, 20, 40, 50))
I'd like to expand a
such that it matches the dimensions of b
, considering than be can have an arbitrary number of dimensions of arbitrary length.
For now, the only thing I can do is a loop over the dimensions like:
c = np.copy(a)
for axis, length in enumerate(b.shape[1:]):
c = np.repeat(c[..., None], length, axis 1)
But it is rather inefficient for a large number of dimensions ...
CodePudding user response:
One option is to reshape
a
so it can be broadcasted against b
, and then assign values to target array inplace:
c = np.zeros(b.shape)
c[:] = a.reshape(b.shape[:1] (1,) * (len(b.shape) - 1))
Or use np.expand_dims
to reshape:
c[:] = np.expand_dims(a, axis=tuple(range(1, len(b.shape))))
CodePudding user response:
You could use np.empty_like
together with np.copyto
c = np.emtpy_like(b)
np.copyto(c.T,a)
#check:
(c == a[:,None,None,None,None]).all()
# True
Or, if you want to retain a
's dtype:
c = np.empty(b.shape,a.dtype)
# etc.
CodePudding user response:
reshape and expand_dims can make an array that will broadcast
like a b
shaped array
tile
can expand that. Check the code, but I think it does repeated repeats
as you do:
d=np.tile(np.expand_dims(a,[1,2,3,4]),(1,) b.shape[1:])
Another way to expand the array to full size, but without the full memory use is:
w = np.broadcast_to(np.expand_dims(a,[1,2,3,4]),b.shape)
w
should have the same shape, but strides
will be (8, 0, 0, 0, 0)
, compared to (3200000, 320000, 16000, 400, 8)
for b
or c
.
But making w.copy()
will take nearly as long making c
or d
, because it has to make the full Gb array.