Suppose I have a Nx3 array A, and another empty MxNx3 array B. I want to copy the values from A to B such that those sets of values appear M times in B. How to do this efficiently other than using a loop?
3 Answers
You can write b[:] = a and let broadcasting take over. For example:
>>> a = np.arange(6).reshape(2, 3)
>>> b = np.zeros((3, 2, 3))
>>> a
array([[0, 1, 2],
[3, 4, 5]])
>>> b
array([[[ 0., 0., 0.],
[ 0., 0., 0.]],
[[ 0., 0., 0.],
[ 0., 0., 0.]],
[[ 0., 0., 0.],
[ 0., 0., 0.]]])
Then to copy a into b:
>>> b[:] = a
>>> b
array([[[ 0., 1., 2.],
[ 3., 4., 5.]],
[[ 0., 1., 2.],
[ 3., 4., 5.]],
[[ 0., 1., 2.],
[ 3., 4., 5.]]])
Note that b has to be able to hold the datatype of a. If a was an array of complex numbers, the imaginary part would be lost when copying to b (because it can only hold float values).
1 Comment
Eric
TIL broadcasting works for slice assignment instead of just on mathematical operators
It seems that for large arrays numpy.repeat(a, repeats, axis) is the fastest option, despite allocating b's memory on the fly.
import numpy as np
a = np.arange(20 * 30 * 40).reshape(20, 30, 40)
b = np.empty((16, 20, 30, 40))
%timeit b[:] = a
# 272 µs ± 22.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit np.empty((16, 20, 30, 40))[:] = a
# 277 µs ± 19 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit np.repeat(a[np.newaxis, ...], repeats=16, axis=0)
# 140 µs ± 483 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)