Reputation: 480
I have a 3d numpy array of following form:
array([[[ 1., 5., 4.],
[ 1., 5., 4.],
[ 1., 2., 4.]],
[[ 3., 6., 4.],
[ 6., 6., 4.],
[ 6., 6., 4.]]])
Is there a efficient way to convert it to a 2d array of form:
array([[1, 1, 1, 5, 5, 2, 4, 4, 4],
[3, 6, 6, 6, 6, 6, 4, 4, 4]])
Thanks a lot!
Upvotes: 8
Views: 15599
Reputation: 880767
In [54]: arr = np.array([[[ 1., 5., 4.],
[ 1., 5., 4.],
[ 1., 2., 4.]],
[[ 3., 6., 4.],
[ 6., 6., 4.],
[ 6., 6., 4.]]])
In [61]: arr.reshape((arr.shape[0], -1), order='F')
Out[61]:
array([[ 1., 1., 1., 5., 5., 2., 4., 4., 4.],
[ 3., 6., 6., 6., 6., 6., 4., 4., 4.]])
The array arr
has shape (2, 3, 3)
. We wish to keep the first axis of length 2, and flatten the two axes of length 3.
If we call arr.reshape(h, w)
then NumPy will attempt to reshape arr
to shape (h, w)
. If we call arr.reshape(h, -1)
then NumPy will replace the -1
with whatever integer is needed for the reshape to make sense -- in this case, arr.size/h
.
Hence,
In [63]: arr.reshape((arr.shape[0], -1))
Out[63]:
array([[ 1., 5., 4., 1., 5., 4., 1., 2., 4.],
[ 3., 6., 4., 6., 6., 4., 6., 6., 4.]])
This is almost what we want, but notice that the values in each subarray, such as
[[ 1., 5., 4.],
[ 1., 5., 4.],
[ 1., 2., 4.]]
are being traversed by marching from left to right before going down to the next row.
We want to march down the rows before going on to the next column.
To achieve that, use order='F'
.
Usually the elements in a NumPy array are visited in C-order
-- where the last index moves fastest. If we visit the elements in F-order
then the first index moves fastest. Since in a 2D array of shape (h, w)
, the first axis is associated with the rows and the last axis the columns, traversing the array in F-order
marches down each row before moving on to the next column.
Upvotes: 16