Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

No fortran order in numpy.array

Tags:

python

numpy

I see no fortran order in:

import numpy as np
In [143]: np.array([[1,2],[3,4]],order='F')
Out[143]: 
array([[1, 2],
       [3, 4]])

But in the following it works:

In [139]: np.reshape(np.arange(9),newshape=(3,3),order='F')
Out[139]: 
array([[0, 3, 6],
       [1, 4, 7],
       [2, 5, 8]])

So what am I doing wrong in the first one?

like image 932
ericj Avatar asked Jan 03 '23 01:01

ericj


1 Answers

When you call numpy.array to create an array from an existing Python object, it will give you an object with whatever shape that the original Python object has. So,

np.array([[1,2],[3,4]], ...)

Will always give you,

np.array([[1, 2],
          [3, 4]])

Which is exactly what you typed in, so it should not come as a surprise. Fortran order and C order do not describe the shape of the data, they describe the memory layout. When you print out an object, NumPy doesn't show you what the memory layout is, it only shows you the shape.

You can witness that the array truly is stored in Fortran order when you flatten it with the "K" order, which keeps the original order of the elements:

>>> a = np.array([[1,2],[3,4]], order="F")
>>> a.flatten(order="K")
array([1, 3, 2, 4])

This is what truly distinguishes Fortran from C order: the memory layout. Most NumPy functions do not force you to consider memory layout, instead, different layouts are handled transparently.

It sounds like what you want is to transpose, reversing the axis order. This can be done simply:

>>> b = numpy.transpose(a)
>>> b
array([[1, 3],
       [2, 4]])

This does not create a new array, but a new view of the same array:

>>> b.base is a
True

If you want the data to have the memory layout 1 2 3 4 and have a Fortran order view of that [[1, 3], [2, 4]], the efficient way to do this is to store the existing array with C order and then transpose it, which results in a Fortran-order array with the desired contents and requires no extra copies.

>>> a = np.array([[1, 2], [3, 4]]).transpose()
>>> a.flatten(order="K")
array([1, 2, 3, 4])
>>> a
array([[1, 3],
       [2, 4]])

If you store the original with Fortran order, the transposition will result in C order, so you don't want that (or maybe all you care about is the transposition, and memory order is not important?). In either case, the array will look the same in NumPy.

>>> a = np.array([[1, 2], [3, 4]], order="F").transpose()
>>> a.flatten(order="K")
array([1, 3, 2, 4])
>>> a
array([[1, 3],
       [2, 4]])
like image 158
Dietrich Epp Avatar answered Jan 16 '23 03:01

Dietrich Epp