23

I have a (w,h) np array in 2d. I want to make a 3d dimension that has a value greater than 1 and copy its value over along the 3rd dimensions. I was hoping broadcast would do it but it can't. This is how i'm doing it

arr = np.expand_dims(arr, axis=2)
arr = np.concatenate((arr,arr,arr), axis=2)

is there a a faster way to do so?

1
  • 5
    np.stack((arr,arr,arr), -1) combines the expand dims and concatenate into one expression. No speedup, just shorter. Commented Sep 13, 2016 at 6:28

7 Answers 7

18

You can push all dims forward, introducing a singleton dim/new axis as the last dim to create a 3D array and then repeat three times along that one with np.repeat, like so -

arr3D = np.repeat(arr[...,None],3,axis=2)

Here's another approach using np.tile -

arr3D = np.tile(arr[...,None],3)
Sign up to request clarification or add additional context in comments.

1 Comment

It turned out to be the case that both of these options are not better than numpy.concatenate. Just numpy.concatenate would do the job, in the fastest manner!
8

Another approach that works:

x_train = np.stack((x_train,) * 3, axis=-1)

Comments

4

Better helpful in converting gray a-channel matrix into 3 channel matrix.

img3 = np.zeros((gray.shape[0],gray.shape[1],3))
img3[:,:,0] = gray
img3[:,:,1] = gray
img3[:,:,2] = gray
fig = plt.figure(figsize = (15,15))
plt.imshow(img3)

Comments

4

Another simple approach is to use matrix multiplication - multiplying by a matrix of ones that will essentially copy the values across the new dimension:

a=np.random.randn(4,4)    #a.shape = (4,4)
a = np.expand_dims(a,-1)  #a.shape = (4,4,1)
a = a*np.ones((1,1,3))
a.shape                   #(4, 4, 3)

Comments

4

I'd suggest you to use the barebones numpy.concatenate() simply because the below piece of code shows that it's the fastest among all other suggested answers:

# sample 2D array to work with
In [51]: arr = np.random.random_sample((12, 34))

# promote the array `arr` to 3D and then concatenate along `axis 2`
In [52]: arr3D = np.concatenate([arr[..., np.newaxis]]*3, axis=2)

# verify for desired shape
In [53]: arr3D.shape
Out[53]: (12, 34, 3)

You can see the timings below to convince yourselves. (ordered: best to worst):

In [42]: %timeit -n 100000 np.concatenate([arr[..., np.newaxis]]*3, axis=2)
1.94 µs ± 32.9 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

In [43]: %timeit -n 100000 np.repeat(arr[..., np.newaxis], 3, axis=2)
4.38 µs ± 46.7 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

In [44]: %timeit -n 100000 np.dstack([arr]*3)
5.1 µs ± 57.6 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

In [49]: %timeit -n 100000 np.stack([arr]*3, -1)
5.12 µs ± 125 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

In [46]: %timeit -n 100000 np.tile(arr[..., np.newaxis], 3)
7.13 µs ± 85.1 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

Having said that, if you're looking for shortest piece of code, then you can use:

# wrap your 2D array in an iterable and then multiply it by the needed depth
arr3D = np.dstack([arr]*3)

# verify shape
print(arr3D.shape)
(12, 34, 3)

Comments

2

This would work. (I think this would not a recommended way :-) But maybe this is the most closest way you thought.)

np.array([img, img, img]).transpose(1,2,0)

just stacking targets(img) any time you want(3), and make the channel(3) go to the last axis.

Comments

1

Not sure if I understood correctly, but broadcasting seems working to me in this case:

>>> a = numpy.array([[1,2], [3,4]])
>>> c = numpy.zeros((4, 2, 2))
>>> c[0] = a
>>> c[1:] = a+1
>>> c
array([[[ 1.,  2.],
        [ 3.,  4.]],

       [[ 2.,  3.],
        [ 4.,  5.]],

       [[ 2.,  3.],
        [ 4.,  5.]],

       [[ 2.,  3.],
        [ 4.,  5.]]])

1 Comment

what i meant was to use numpy built in broadcast function, which you do not use in your example above. Bt your method seems to work as well.

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.