Reputation: 43
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.
Upvotes: 1
Views: 2667
Reputation: 231385
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.
Upvotes: 0
Reputation: 402
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))
Upvotes: 0
Reputation: 260640
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]]])
Upvotes: 1