Reputation: 398
I thought I understood the reshape function in Numpy until I was messing around with it and came across this example:
a = np.arange(16).reshape((4,4))
which returns:
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15]])
This makes sense to me, but then when I do:
a.reshape((2,8), order = 'F')
it returns:
array([[0, 8, 1, 9, 2, 10, 3, 11],
[4, 12, 5, 13, 6, 14, 7, 15]])
I would expect it to return:
array([[0, 4, 8, 12, 1, 5, 9, 13],
[2, 6, 10, 14, 3, 7, 11, 15]])
Can someone please explain what is happening here?
Upvotes: 15
Views: 20342
Reputation: 51
As the docs mention that 'F' order changes the first index fastest. That means that the first axis of your reshaped array or the axis=0 is going to be filled first with the elements.
It's actually a little difficult to understand this with words. So I am going to attach some images while describing them at the same time.
The source array is first flattened according to the order (In your case that is 'F')
That means, As the First dimension of your source array is the row, it is going to read the elements row by row and put them in a vector.
Then the elements of the flattened array or the vector are placed in the reshaped array according to the order.
You can think that, first an array with the demanded shape is constructed without any element inside it.
Then again as the First dimension of your demanded array is also the row it is going to fill the elements row by row.
Image 3 (Resulting Array Construction)
And that's the array which is returned!
I Hope this answer will help understand some little tricky concepts. And however this answer was for a matrix , the logic explained here applies for tensors too. So if you need help on this topic with tensors please let me know. I would be very glad to help.
Upvotes: 5
Reputation: 231665
The elements of a
in order 'F'
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15]])
are [0,4,8,12,1,5,9 ...]
Now rearrange them in a (2,8) array.
I think the reshape
docs talks about raveling the elements, and then reshaping them. Evidently the ravel is done first.
Experiment with a.ravel(order='F').reshape(2,8)
.
Oops, I get what you expected:
In [208]: a = np.arange(16).reshape(4,4)
In [209]: a
Out[209]:
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15]])
In [210]: a.ravel(order='F')
Out[210]: array([ 0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15])
In [211]: _.reshape(2,8)
Out[211]:
array([[ 0, 4, 8, 12, 1, 5, 9, 13],
[ 2, 6, 10, 14, 3, 7, 11, 15]])
OK, I have to keep the 'F' order during the reshape
In [214]: a.ravel(order='F').reshape(2,8, order='F')
Out[214]:
array([[ 0, 8, 1, 9, 2, 10, 3, 11],
[ 4, 12, 5, 13, 6, 14, 7, 15]])
In [215]: a.ravel(order='F').reshape(2,8).flags
Out[215]:
C_CONTIGUOUS : True
F_CONTIGUOUS : False
...
In [216]: a.ravel(order='F').reshape(2,8, order='F').flags
Out[216]:
C_CONTIGUOUS : False
F_CONTIGUOUS : True
From np.reshape
docs
You can think of reshaping as first raveling the array (using the given index order), then inserting the elements from the raveled array into the new array using the same kind of index ordering as was used for the raveling.
The notes on order
are fairly long, so it's not surprising that the topic is confusing.
Upvotes: 15