I do not understand the reshape function in numpy
in Python. I have got the following problem:
I want to reshape the (6, 2)
array
A = np.c_[np.arange(1, 7), np.arange(6, 12)]
Which is
array([[ 1, 6],
[ 2, 7],
[ 3, 8],
[ 4, 9],
[ 5, 10],
[ 6, 11]])
Into a (2, 3, 2)
array like
array([[[ 1, 2, 3],
[ 4, 5, 6]],
[[ 6, 7, 8],
[ 9, 10, 11]]])
I have tried
np.reshape(A, (2, 3, 2), order='F')
But the result was not what I am looking for. Instead, it was:
array([[[ 1, 6],
[ 3, 8],
[ 5, 10]],
[[ 2, 7],
[ 4, 9],
[ 6, 11]]])
There are two problems here:
(2, 2, 3)
, not (2, 3, 2)
.order="F"
doesn't do what you think it does. What you actually want is to transpose the array using A.T
.Also, you can use A.reshape(...)
instead of np.reshape(A, ...)
.
Here is the code:
import numpy as np
A = np.c_[np.arange(1,7), np.arange(6,12)]
print(A)
print("\n->\n")
print(A.T.reshape((2, 2, 3)))
Which gives:
array([[ 1, 6],
[ 2, 7],
[ 3, 8],
[ 4, 9],
[ 5, 10],
[ 6, 11]])
->
array([[[ 1, 2, 3],
[ 4, 5, 6]],
[[ 6, 7, 8],
[ 9, 10, 11]]])
order="F"
vs. .T
Try A.ravel(order="F")
to see what the elements of the array are in the "F"
order. You will get:
array([[ 1, 6],
[ 2, 7],
[ 3, 8],
[ 4, 9],
[ 5, 10],
[ 6, 11]])
->
array([ 1, 2, 3, 4, 5, 6, 6, 7, 8, 9, 10, 11])
Now if you apply a normal order
after this, you get your expected result:
A.ravel(order="F").reshape((2, 2, 3)) ->
array([[[ 1, 2, 3],
[ 4, 5, 6]],
[[ 6, 7, 8],
[ 9, 10, 11]]])
The problem is, order="F"
also affects how the ravelled elements are added back into the array. Not only are the elements taken out column-wise, they are added back in column-wise as well. So:
[[[], []], [[], []]] ->
[[[1], []], [[], []]] ->
[[[1], []], [[2], []]] ->
[[[1], [3]], [[2], []]] ->
[[[1], [3]], [[2], [4]]] ->
[[[1, 5], [3]], [[2], [4]]] ->
[[[1, 5], [3]], [[2, 6], [4]]] ->
[[[1, 5], [3, 7]], [[2, 6], [4]]] ->
[[[1, 5], [3, 6]], [[2, 6], [4, 7]]] ->
[[[1, 5, 8], [3, 6]], [[2, 6], [4, 7]]] ->
[[[1, 5, 8], [3, 6]], [[2, 6, 9], [4, 7]]] ->
[[[1, 5, 8], [3, 6, 10]], [[2, 6, 9], [4, 7]]] ->
[[[1, 5, 8], [3, 6, 10]], [[2, 6, 9], [4, 7, 11]]]
Not:
[[[1], []], [[], []]] ->
[[[1, 2], []], [[], []]] ->
[[[1, 2, 3], []], [[], []]] ->
[[[1, 2, 3], [4]], [[], []]] ->
[[[1, 2, 3], [4, 5]], [[], []]] ->
[[[1, 2, 3], [4, 5, 6]], [[], []]] ->
[[[1, 2, 3], [4, 5, 6]], [[6], []]] ->
[[[1, 2, 3], [4, 5, 6]], [[6, 7], []]] ->
[[[1, 2, 3], [4, 5, 6]], [[6, 7, 8], []]] ->
[[[1, 2, 3], [4, 5, 6]], [[6, 7, 8], [9]]] ->
[[[1, 2, 3], [4, 5, 6]], [[6, 7, 8], [9, 10]]] ->
[[[1, 2, 3], [4, 5, 6]], [[6, 7, 8], [9, 10, 11]]]
Therefore, you end up with an odd result. If you just want to take the elements out with order="F"
but not add them back in that way, transposing the array will have the same effect.