Numpy "Fortran"-like reshape?

Viewed 291

Let's say I have an array X of shape (6, 2) like this:

import numpy as np
X = np.array([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10], [11, 12]])

I want to reshape it to an array of shape (3, 2, 2), so I did this:

X.reshape(3, 2, 2)

And got:

array([[[ 1,  2],
        [ 3,  4]],

       [[ 5,  6],
        [ 7,  8]],

       [[ 9, 10],
        [11, 12]]])

However, I need my data in a different format. To be precise, I want to end up wth:

array([[[ 1,  2],
        [ 7,  8]],

       [[ 3,  4],
        [ 9,  10]],

       [[ 5, 6],
        [11, 12]]])

Should I be using reshape for this or something else? What's the best way to do this in Numpy?

3 Answers

You have to set the order option:

>>> X.reshape(3, 2, 2, order='F')
array([[[ 1,  2],
        [ 7,  8]],

       [[ 3,  4],
        [ 9, 10]],

       [[ 5,  6],
        [11, 12]]])

ā€˜F’ means to read / write the elements using Fortran-like index order, with the first index changing fastest, and the last index changing slowest.

see: https://numpy.org/doc/stable/reference/generated/numpy.reshape.html

You need to specify order;

X.reshape(3, 2, 2, order='F')

should work

A functional equivalent to the order='F' reshape:

In [31]: x.reshape(2,3,2).transpose(1,0,2)
Out[31]: 
array([[[ 1,  2],
        [ 7,  8]],

       [[ 3,  4],
        [ 9, 10]],

       [[ 5,  6],
        [11, 12]]])

In [32]: x.reshape(2,3,2).transpose(1,0,2).strides
Out[32]: (16, 48, 8)

Without the transpose the strides would be (48,16,8).

A thing that's a bit tricky about this layout is that the last dimension remains in 'C' order. It's the just first two dimension that are switched.

The full 'F' layout would be

In [33]: x = np.arange(1,13).reshape(3,2,2,order='F')
In [34]: x
Out[34]: 
array([[[ 1,  7],
        [ 4, 10]],

       [[ 2,  8],
        [ 5, 11]],

       [[ 3,  9],
        [ 6, 12]]])
Related