copy from two multidimensional numpy array to another with different shape

Viewed 176

I have two numpy arrays of the following shape:

print(a.shape) -> (100, 20, 3, 3)
print(b.shape) -> (100, 3)

Array a is empty, as I just need this predefined shape, I created it with:

a = numpy.empty(shape=(100, 20, 3, 3))

Now I would like to copy data from array b to array a so that the second and third dimension of array a gets filled with the same 3 values of the corresponding row of array b.

Let me try to make it a bit clearer: Array b contains 100 rows (100, 3) and each row holds three values (100, 3). Now every row of array a (100, 20, 3, 3) should also hold the same three values in the last dimension (100, 20, 3, 3), while those three values stay the same for the second and third dimension (100, 20, 3, 3) for the same row (100, 20, 3, 3).

How can I copy the data as described without using loops? I just can not get it done but there must be an easy solution for this.

2 Answers

You can use repeat along axis. You also do not need to predefine a. I would also suggest NOT to use broadcast_to since it returns readonly view and memory is shared among elements:

a = np.repeat(b[:,None,None,:], 20, 1) #adds dimensions 1 and 2 and repeats 20 times along axis 1
a = np.repeat(a, 3, 2) #repeats 3 times along axis 2

Smaller example:

b = np.arange(2*3).reshape(2,3)
#[[0 1 2]
# [3 4 5]]
a = np.repeat(b[:,None,None,:], 2, 1) 
a = np.repeat(a, 3, 2) 
#shape(2,2,3,3)
[[[[0 1 2]
   [0 1 2]
   [0 1 2]]

  [[0 1 2]
   [0 1 2]
   [0 1 2]]]


 [[[3 4 5]
   [3 4 5]
   [3 4 5]]

  [[3 4 5]
   [3 4 5]
   [3 4 5]]]]

We can make use of np.broadcast_to.

If you are okay with a view -

np.broadcast_to(b[:,None, None, :], (100, 2, 3, 3))

If you need an output with its own memory space, simply append with .copy().

If you want to save on memory and fill into already defined array, a :

a[:] = b[:,None,None,:]

Note that we can skip the trailing :s.

Timings :

In [20]: b = np.random.rand(100, 3)

In [21]: %timeit np.broadcast_to(b[:,None, None, :], (100, 2, 3, 3))
5.93 µs ± 64.4 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

In [22]: %timeit np.broadcast_to(b[:,None, None, :], (100, 2, 3, 3)).copy()
11.4 µs ± 56.2 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

In [23]: %timeit np.repeat(np.repeat(b[:,None,None,:], 20, 1), 3, 2)
39.3 µs ± 147 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
Related