在numpy.array中没有Fortran顺序

5

我在以下内容中找不到Fortran命令:

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

但在以下情况下它可以正常工作:
In [139]: np.reshape(np.arange(9),newshape=(3,3),order='F')
Out[139]: 
array([[0, 3, 6],
       [1, 4, 7],
       [2, 5, 8]])

那么在第一个例子中,我做错了什么?

2个回答

11

当您调用numpy.array从现有的Python对象创建一个数组时,它会返回一个具有与原始Python对象相同的任何形状的对象。因此,

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

永远会给予你,

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

这正是您键入的内容,所以不应该感到惊讶。Fortran顺序和C顺序并不描述数据的形状,而是描述内存布局。当您打印一个对象时,NumPy不会显示内存布局,它只会显示形状。

当您使用"K"顺序将其展平时,可以看到数组确实按Fortran顺序存储,该顺序保持元素的原始顺序:

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

这正是区分Fortran和C的真正区别所在:内存布局。大多数NumPy函数不强制您考虑内存布局,而是透明地处理不同的布局。

听起来你想要的是转置,即反转轴顺序。这可以简单地完成:

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

这并不会创建一个新的数组,而是创建了原数组的一个新视图:

>>> b.base is a
True

如果你想让数据在内存中保持1 2 3 4的布局,并且具有[[1, 3], [2, 4]]的Fortran视图,有效的做法是使用C顺序存储现有数组,然后对其进行转置,这将得到所需内容的Fortran顺序数组,并且不需要额外复制。

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

如果您使用Fortran顺序存储原始数据,则转置后将得到C顺序,因此您不希望出现这种情况(或者您只关心转置,内存顺序并不重要?)。无论哪种情况,数组在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]])

0
你构建二维数组的两种方式并不相同。第一种方式中,你指定了数组的结构。而在第二种方式中,你先创建了一个数组,然后再按照自己的需求进行重塑。
>>> np.reshape([1,2,3,4],newshape=(2,2),order='F')
array([[1, 3],
       [2, 4]])

再次进行比较,即使您要求将重塑和格式更改为FORTRAN,您也会得到指定的结构:

>>> np.reshape([[1,2],[3,4]],newshape=(2,2),order='F')
array([[1, 2],
       [3, 4]])

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接