8

Assume a 1D array A is given. Is there an easy way to construct a 3D array B, such that B[i,j,k] = A[k] for all i,j,k? You can assume that the shape of B is prescribed, and that B.shape[2] = A.shape[0].

1

3 Answers 3

10
>>> k = 4
>>> a = np.arange(k)
>>> j = 3
>>> i = 2
>>> np.tile(a,j*i).reshape((i,j,k))
array([[[0, 1, 2, 3],
        [0, 1, 2, 3],
        [0, 1, 2, 3]],

       [[0, 1, 2, 3],
        [0, 1, 2, 3],
        [0, 1, 2, 3]]]
Sign up to request clarification or add additional context in comments.

3 Comments

You can replace np.tile(np.tile(a,j),i).reshape((i,j,k)) with np.tile(a, i*j).reshape((i,j,k))
I removed my np.tile(A,(i,j,1)) suggestion because it had terrible performance for large arrays. Do you know why np.tile(A,i*j).reshape(i,j,k) scales so much better?
@MLW: I typed numpy.source(numpy.tile) and saw that tile calls reshape and repeat for each element in the reps tuple. reshape returns a copy which means re-allocating all that memory each time. Seems poorly implemented to me.
4

Another easy way to do this is simple assignment -- broadcasting will automatically do the right thing:

i = 2
j = 3
k = 4
a = numpy.arange(k)
b = numpy.empty((i, j, k))
b[:] = a
print b

prints

[[[ 0.  1.  2.  3.]
  [ 0.  1.  2.  3.]
  [ 0.  1.  2.  3.]]

 [[ 0.  1.  2.  3.]
  [ 0.  1.  2.  3.]
  [ 0.  1.  2.  3.]]]

Comments

0
for k,v in enumerate(A): B[:,:,k] = v

2 Comments

Isn't this very inefficient since it involves a slow for loop?
@celli It is O(n) on the size of A, and no algorithm can do better than that because each element of A must be examined to perform the computation. Other answers have suggested that using numppy.tile() is a better option than a direct assignment. The solution I propose is clear and pythonic, and I expect NumPy to handle the assignments efficiently (perhaps with tile()), but one would have to measure (time it) to know.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.