1

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 ...

3
  • np.tile can do it, but it too does repeated repeats. But does it need to fully match, or is broadcasting enough? There is also a broadcast_to. Commented Oct 2, 2021 at 18:09
  • The problem isn't just the large number of dimensions, it's the large final size of that array. I keep killing my terminal when I test various alternatives (on a rather modest machine. Commented Oct 2, 2021 at 20:16
  • For your first comment, please find the original issue here. Commented Oct 4, 2021 at 9:17

3 Answers 3

2

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Not sure what you mean with you comment on w size. I have (c == w).all() which True !
1

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))))

Comments

1

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.