将"numpy"数组的"顺序"选项从"C"(行主)更改为"Fortran"(列主)不起作用



正如标题所说,我试图通过更改以下测试脚本中的排序来验证numpy数组中的排序:

import numpy as np

# Standard array
arr = [[1, 2, 3], [-7, -8, -9], ['A', 'B', 'C']]
print(arr, 'n')
for row_index, row_entries in enumerate(arr):
print('Row ' + str(row_index+1))
for column_index, column_entries in enumerate(row_entries):
print(' Column ' + str(column_index+1) + 'n', 't [' + str(column_entries) + ']')

# NumPy array
arr = np.asarray([[1, 2, 3], [-7, -8, -9], ['A', 'B', 'C']], order='F')    # Try 'C' vs. 'F'!!
print('nn', arr, 'n')
for row_index, row_entries in enumerate(arr):
print('Row ' + str(row_index+1))
for column_index, column_entries in enumerate(row_entries):
print(' Column ' + str(column_index+1) + 'n', 't [' + str(column_entries) + ']')
----------------------------------------------------------------------------------------------
Output:
[[1, 2, 3], [-7, -8, -9], ['A', 'B', 'C']] 
Row 1
Column 1
[1]
Column 2
[2]
Column 3
[3]
Row 2
Column 1
[-7]
Column 2
[-8]
Column 3
[-9]
Row 3
Column 1
[A]
Column 2
[B]
Column 3
[C]

[['1' '2' '3']
['-7' '-8' '-9']
['A' 'B' 'C']] 
Row 1
Column 1
[1]
Column 2
[2]
Column 3
[3]
Row 2
Column 1
[-7]
Column 2
[-8]
Column 3
[-9]
Row 3
Column 1
[A]
Column 2
[B]
Column 3
[C]

为什么我得到相同的输出?

您从列表开始:

In [29]: alist = [[1, 2, 3], [-7, -8, -9], ['A', 'B', 'C']]
In [30]: alist
Out[30]: [[1, 2, 3], [-7, -8, -9], ['A', 'B', 'C']]

显然,我们可以遍历列表和子列表。

我们可以从这个列表中生成一个数组。通常我们不指定order,但默认为"C":

In [31]: arr1 = np.array(alist, order='C')
In [32]: arr1
Out[32]: 
array([['1', '2', '3'],
['-7', '-8', '-9'],
['A', 'B', 'C']], dtype='<U21')

注意,dtype是字符串(我想我本可以指定object(。

相同的东西,但有"F":

In [34]: arr2 = np.array(alist, order='F')
In [35]: arr2
Out[35]: 
array([['1', '2', '3'],
['-7', '-8', '-9'],
['A', 'B', 'C']], dtype='<U21')

显示内容相同。

为了了解元素是如何存储的,我们必须"遍历"数组。结果是一个新的1d数组。请参阅np.reshapenp.ravel文档了解"K"订单的使用:

In [36]: arr1.ravel('K')
Out[36]: array(['1', '2', '3', '-7', '-8', '-9', 'A', 'B', 'C'], dtype='<U21')
In [38]: arr2.ravel('K')
Out[38]: array(['1', '-7', 'A', '2', '-8', 'B', '3', '-9', 'C'], dtype='<U21')

在这里,我们沿着列读取arr2的值。第一个数组的ravel,但与"F"顺序产生相同的东西:

In [39]: arr1.ravel('F')
Out[39]: array(['1', '-7', 'A', '2', '-8', 'B', '3', '-9', 'C'], dtype='<U21')

正如您所做的,迭代不会随着order而改变。它有效地将数组视为列表。

In [40]: [row for row in arr1]
Out[40]: 
[array(['1', '2', '3'], dtype='<U21'),
array(['-7', '-8', '-9'], dtype='<U21'),
array(['A', 'B', 'C'], dtype='<U21')]
In [41]: [row for row in arr2]
Out[41]: 
[array(['1', '2', '3'], dtype='<U21'),
array(['-7', '-8', '-9'], dtype='<U21'),
array(['A', 'B', 'C'], dtype='<U21')]
In [42]: arr2.tolist()
Out[42]: [['1', '2', '3'], ['-7', '-8', '-9'], ['A', 'B', 'C']]

您必须使用numpy's自己的方法和工具才能看到order的效果。order在通过reshape:创建阵列时更有用

In [43]: np.arange(12)
Out[43]: array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11])
In [44]: np.arange(12).reshape(3,4)
Out[44]: 
array([[ 0,  1,  2,  3],
[ 4,  5,  6,  7],
[ 8,  9, 10, 11]])
In [45]: np.arange(12).reshape(3,4,order='F')
Out[45]: 
array([[ 0,  3,  6,  9],
[ 1,  4,  7, 10],
[ 2,  5,  8, 11]])

调整形状,然后应用转置:

In [46]: np.arange(12).reshape(4,3,order='F')
Out[46]: 
array([[ 0,  4,  8],
[ 1,  5,  9],
[ 2,  6, 10],
[ 3,  7, 11]])
In [47]: np.arange(12).reshape(4,3,order='F').T
Out[47]: 
array([[ 0,  1,  2,  3],
[ 4,  5,  6,  7],
[ 8,  9, 10, 11]])

编辑

如果我制作一个较小的数组,每个元素只有1个字节,可能会更清楚。

两个订单:

In [70]: arr1 = np.array([[1,2,3],[4,5,6]], 'uint8')
In [72]: arr2 = np.array([[1,2,3],[4,5,6]], 'uint8',order='F')
In [73]: arr1
Out[73]: 
array([[1, 2, 3],
[4, 5, 6]], dtype=uint8)
In [74]: arr2
Out[74]: 
array([[1, 2, 3],
[4, 5, 6]], dtype=uint8)

代替ravel,将tobytes与"A"订单一起使用以保留基本订单(请参阅tobytes文档(:

In [75]: arr1.tobytes(order='A')
Out[75]: b'x01x02x03x04x05x06'
In [76]: arr2.tobytes(order='A')
Out[76]: b'x01x04x02x05x03x06'

差异也可以从步伐中看出:

In [77]: arr1.strides
Out[77]: (3, 1)
In [78]: arr2.strides
Out[78]: (1, 2)

strides控制numpy如何在编译后的代码中遍历数组(但在使用python级别的迭代时则不然(。

一条评论建议使用nditer通过numpy自己的方法进行迭代。一般来说,我不建议使用nditer,但这里是说明性的:

In [79]: [i for i in np.nditer(arr1)]
Out[79]: 
[array(1, dtype=uint8),
array(2, dtype=uint8),
array(3, dtype=uint8),
array(4, dtype=uint8),
array(5, dtype=uint8),
array(6, dtype=uint8)]
In [80]: [i for i in np.nditer(arr2)]
Out[80]: 
[array(1, dtype=uint8),
array(4, dtype=uint8),
array(2, dtype=uint8),
array(5, dtype=uint8),
array(3, dtype=uint8),
array(6, dtype=uint8)]

nditer采用order,但"K"是默认值(与许多其他情况下"C"为默认值形成对比(。

最新更新