python numpy array row major和column major

yzckvree  于 2023-05-21  发布在  Python
关注(0)|答案(6)|浏览(81)

我无法理解numpy如何存储数据。考虑以下情况:

>>> import numpy as np
>>> a = np.ndarray(shape=(2,3), order='F')
>>> for i in xrange(6): a.itemset(i, i+1)
... 
>>> a
array([[ 1.,  2.,  3.],
       [ 4.,  5.,  6.]])
>>> a.flags
  C_CONTIGUOUS : False
  F_CONTIGUOUS : True
  OWNDATA : True
  WRITEABLE : True
  ALIGNED : True
  UPDATEIFCOPY : False

这表明a是列主(F_CONTIGUOUS),因此,在内部,a应该如下所示:

[1, 4, 2, 5, 3, 6]

这正是本词汇表中所述的内容。令我困惑的是,如果我试图以线性方式访问a的数据,我会得到:

>>> for i in xrange(6): print a.item(i)
... 
1.0
2.0
3.0
4.0
5.0
6.0

在这一点上,我不确定F_CONTIGUOUS标志告诉我们什么,因为它不荣誉顺序。显然,Python中的所有内容都是行优先的,当我们想要以线性方式迭代时,我们可以使用迭代器flat

**问题如下:**假设我们有一个数字列表,比如:1, 2, 3, 4, 5, 6,我们如何创建一个numpy数组的形状(2, 3)在列主顺序?这就是如何得到一个像这样的矩阵

array([[ 1.,  3.,  5.],
       [ 2.,  4.,  6.]])

我真的希望能够对列表进行线性迭代,并将它们放入新创建的ndarray中。这样做的原因是因为我将阅读以列优先顺序设置的多维数组文件。

des4xlb0

des4xlb01#

numpy以行优先顺序存储数据。

>>> a = np.array([[1,2,3,4], [5,6,7,8]])
>>> a.shape
(2, 4)
>>> a.shape = 4,2
>>> a
array([[1, 2],
       [3, 4],
       [5, 6],
       [7, 8]])

如果更改形状,数据的顺序不会更改。
如果你加一个“F”,你就能得到你想要的。

>>> b
array([1, 2, 3, 4, 5, 6])
>>> c = b.reshape(2,3,order='F')
>>> c
array([[1, 3, 5],
       [2, 4, 6]])
0mkxixxg

0mkxixxg2#

您的问题已经回答了,但我想我会添加这一点来解释您关于 “在这一点上,我不确定F_CONTIGUOUS标志告诉我们什么,因为它不荣誉订单。”
item方法并不像您想象的那样直接访问数据。为此,您应该访问data属性,该属性为您提供字节串。
举个例子:

c = np.array([[1,2,3],
              [4,6,7]], order='C')

f = np.array([[1,2,3],
              [4,6,7]], order='F')

观察

print c.flags.c_contiguous, f.flags.f_contiguous
# True, True

print c.nbytes == len(c.data)
# True

现在让我们打印这两个数据的连续数据:

nelements = np.prod(c.shape)
bsize = c.dtype.itemsize # should be 8 bytes for 'int64'
for i in range(nelements):
    bnum = c.data[i*bsize : (i+1)*bsize] # The element as a byte string.
    print np.fromstring(bnum, dtype=c.dtype)[0], # Convert to number.

这将打印:
这是我们所期望的,因为c是顺序'C',即,其数据以行为主连续存储。
另一方面

nelements = np.prod(f.shape)
bsize = f.dtype.itemsize # should be 8 bytes for 'int64'
for i in range(nelements):
    bnum = f.data[i*bsize : (i+1)*bsize] # The element as a byte string.
    print np.fromstring(bnum, dtype=f.dtype)[0], # Convert to number.

印刷品
这再次是我们期望看到的,因为f的数据是以列为主的连续存储的。

bq9c1y66

bq9c1y663#

想在评论中添加这一点,但我的代表性太低:
虽然Kill Console的答案给出了OP所需的解决方案,但我认为重要的是要注意,如numpy.reshape()文档(https://docs.scipy.org/doc/numpy/reference/generated/numpy.reshape.html)中所述:
请注意,无法保证返回数组的内存布局(C或Fortran连续)。
因此,即使视图是按列的,数据本身也可能不是,这可能导致计算中的低效率,而计算受益于按列存储在存储器中的数据。或许:

a = np.array(np.array([1, 2, 3, 4, 5, 6]).reshape(2,3,order='F'), order='F')

提供了更多的保证,即数据是按列存储的(请参见https://docs.scipy.org/doc/numpy-1.15.1/reference/generated/numpy.array.html中的order参数描述)。

gudnpqoy

gudnpqoy4#

一般来说,numpy使用order来描述内存布局,但是数组的python行为应该是一致的,而不管内存布局如何。我认为你可以使用视图获得你想要的行为。视图是与另一个数组共享内存的数组。例如:

import numpy as np

a = np.arange(1, 6 + 1)
b = a.reshape(3, 2).T

a[1] = 99
print b
# [[ 1  3  5]
#  [99  4  6]]

希望能帮上忙。

3df52oht

3df52oht5#

下面是一个简单的方法,通过使用ravel()函数来按内存顺序打印数据:

>>> import numpy as np
>>> a = np.ndarray(shape=(2,3), order='F')
>>> for i in range(6): a.itemset(i, i+1)

>>> print(a.ravel(order='K'))
[ 1.  4.  2.  5.  3.  6.]

这将确认数组以Fortran顺序存储。

bf1o4zei

bf1o4zei6#

这是一个很老的问题,但我觉得答案是缺失的。
只是提到一些没有提到的功能:

a = np.ascontiguousarray(in_arr)
b = np.asfortranarray(in_arr)

但是,它们不会帮助解决您的问题。什么会有帮助:

a = np.ndarray(shape=(2,3), order='F')
def memory_index(*args, x):
    idx = (np.array(x.strides) / a.itemsize).dot(np.array(args))
    return int(idx)

flat_view = a.ravel(order='A')   # or order='F' to be explicit
for i, value in enumerate([1, 2, 3, 4, 5, 6]):
    flat_view[i] = value

print(a)

array([[ 1.,3.,5.],[ 2.,4.,6.]])

相关问题