简体   繁体   中英

Stacking 2D arrays into a 3D array

I have a very simple question but I just can't figure it out. I would like to stack a bunch of 2D numpy arrays into a 3D array one by one along the third dimension (depth).

I know that I can use np.stack() like this:

d1 = np.arange(9).reshape(3,3)
d2 = np.arange(9,18).reshape(3,3)

foo = np.stack((d1,d2))

and I get

print(foo.shape)
>>> (2, 3, 3)
print(foo)
>>> [[[ 0  1  2]
      [ 3  4  5]
      [ 6  7  8]]

     [[ 9 10 11]
      [12 13 14]
      [15 16 17]]]

Which is pretty much what I want so far. Though, I am a bit confused here that the depth dimension is indexed as the first one here. However, I would like to add new 3x3 array along the first dimension now(?) (this confuses me), like this.

d3 = np.arange(18,27).reshape(3,3)
foo = np.stack((foo,d3))

This does not work. I understand that it has a problem with dimensions of the arrays now, but no vstack, hstack, dstack work here. All I want at this point is pretty much this.

print(foo)
>>> [[[ 0  1  2]
      [ 3  4  5]
      [ 6  7  8]]

     [[ 9 10 11]
      [12 13 14]
      [15 16 17]]

     [[18 19 20]
      [21 22 23]
      [24 25 26]]]

and then just be able to add more arrays like this.

I looked at some questions on this topic, of course, but I still have problem understanding 3D arrays (especially np.dstack()) and don't know how to solve my problem.

Why don't you add directly d1, d2, d3 in a single stack ( np.stack((d1, d2, d3)) )? This is generally bad practice to repeatedly concatenate arrays.

In any case, you can use:

np.stack((*foo, d3))

or:

np.vstack((foo, d3[None]))

output:

array([[[ 0,  1,  2],
        [ 3,  4,  5],
        [ 6,  7,  8]],

       [[ 9, 10, 11],
        [12, 13, 14],
        [15, 16, 17]],

       [[18, 19, 20],
        [21, 22, 23],
        [24, 25, 26]]])

You are looking for np.vstack :

np.vstack((d1,d2,d3)).reshape(3,3,3)

or iteratively

foo = np.vstack((d1, d2))
foo = np.vstack((foo, d3))

Make 2 arrays with distinctive shapes (so it's clear where the 2,3 and 4 come from):

In [123]: d1 = np.arange(12).reshape(3,4)
     ...: d2 = np.arange(12,24).reshape(3,4)

Combining them into a new array - the result is a (2,3,4). Note how [] are nested, as though you had a list of 2 lists, each of which is has 3 lists of length 4.

In [124]: np.array((d1,d2))
Out[124]: 
array([[[ 0,  1,  2,  3],
        [ 4,  5,  6,  7],
        [ 8,  9, 10, 11]],

       [[12, 13, 14, 15],
        [16, 17, 18, 19],
        [20, 21, 22, 23]]])

stack with the default axis does the same thing - join the (3,4) arrays along a new leading dimension:

In [125]: np.stack((d1,d2))
Out[125]: 
array([[[ 0,  1,  2,  3],
        [ 4,  5,  6,  7],
        [ 8,  9, 10, 11]],

       [[12, 13, 14, 15],
        [16, 17, 18, 19],
        [20, 21, 22, 23]]])

Making a (3,2,4) array:

In [126]: np.stack((d1,d2), axis=1)
Out[126]: 
array([[[ 0,  1,  2,  3],
        [12, 13, 14, 15]],

       [[ 4,  5,  6,  7],
        [16, 17, 18, 19]],

       [[ 8,  9, 10, 11],
        [20, 21, 22, 23]]])

and a (3,4,2):

In [127]: np.stack((d1,d2), axis=2)
Out[127]: 
array([[[ 0, 12],
        [ 1, 13],
        [ 2, 14],
        [ 3, 15]],

       [[ 4, 16],
        [ 5, 17],
        [ 6, 18],
        [ 7, 19]],

       [[ 8, 20],
        [ 9, 21],
        [10, 22],
        [11, 23]]])

Often depth is the last dimension. That's implied by the d in np.dstack .

vstack joins them on an existing 1st dimension, making a (2*3, 4) array:

In [128]: np.vstack((d1,d2))
Out[128]: 
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11],
       [12, 13, 14, 15],
       [16, 17, 18, 19],
       [20, 21, 22, 23]])

All these *stack functions tweak the dimensions and then use np.concatenate . The default stack adds a new leading dimension, as in:

In [129]: np.concatenate((d1[None,:,:], d2[None,:,:])).shape
Out[129]: (2, 3, 4)

While vstack can be used repeated in a loop, provided you start with an appropriate array, it is slow. It's better to collect the whole list of arrays, and do just one combination.

An extra problem with stack in a loop is that it adds a dimension each time, and requires matching shapes.

np.stack((foo,d3))  # a (2,3,3) with a (3,3); dimensions don't match
np.stack((foo,foo)) # produces (2,2,3,3)

To add more arrays to foo you have to expand them to (1,3,3) shape

np.concatenate((foo, d3[None,:,:], d4[None,:,:]), axis=0)

This then joins (2,3,3) with (1,3,3) and another (1,3,3) etc; matching dimensions except the first.

When joining arrays with any of these functions, you can't be casual about the dimensions. np.concatenate has very specific rules about that it can combine.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM