numpy数组行主要和列专业

时间:2013-12-03 02:14:52

标签: python arrays numpy

我无法理解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]

这就是glossary中所述的内容。让我感到困惑的是,如果我尝试以线性方式访问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形状数组{{1}列主要顺序?那我怎么能得到一个看起来像这样的矩阵

(2, 3)

我真的希望能够在列表上线性迭代并将它们放入新创建的array([[ 1., 3., 5.], [ 2., 4., 6.]]) 中。原因是因为我将读取以列主要顺序设置的多维数组的文件。

5 个答案:

答案 0 :(得分:15)

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]])

答案 1 :(得分:8)

您的问题已得到解答,但我想我会添加此内容来解释您的观察,"此时我不确定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.

打印:

1 2 3 4 6 7

这是我们所期望的,因为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.

打印

1 4 2 6 3 7

这也是我们期望看到的,因为f的数据存储在列主要的连续数据中。

答案 2 :(得分:2)

通常,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]]

希望有所帮助。

答案 3 :(得分:1)

想在评论中添加它,但是我的代表太低了:

虽然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上的顺序参数说明)。

答案 4 :(得分:0)

以下是使用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顺序存储。