numpy结构化数组的ndim?

时间:2013-12-10 09:23:25

标签: python arrays numpy

这是类似措辞的问题ndim in numpy array loaded with scipy.io.loadmat? - 但它实际上更基本。

假设我有这个结构化数组:

import sys
import numpy as np
from pprint import pprint

a = np.array([(1.5,2.5),(3.,4.),(1.,3.)],
        dtype=[('x','f4'),('y',np.float32)])

pprint(a)
# array([(1.5, 2.5), (3.0, 4.0), (1.0, 3.0)],
#       dtype=[('x', '<f4'), ('y', '<f4')])

我看到这是一个3行2列的表,所以3x2。但是,在这里尝试使用ndim,我看到了:

print(".ndim", a.ndim)
print(".shape", a.shape)
print("asarray.ndim", np.asarray(a).ndim)
# ('.ndim', 1)
# ('.shape', (3,))
# ('asarray.ndim', 1)

...这就是让我感到困惑的是 - 当{/ 1}}明确定义字段/列时,numpy认为这应该是一个数组?是什么原因?!

考虑到输出,难怪重塑不起作用:

pprint(a.reshape(3,2))
# ValueError: total size of new array must be unchanged

现在,我可以将结构化数组强制成一个(“正常”numpy,我猜?)数组:

b = np.column_stack((a['x'], a['y']))
pprint(b)
# array([[ 1.5,  2.5],
#        [ 3. ,  4. ],
#        [ 1. ,  3. ]], dtype=float32)

print(".ndim", b.ndim)
print(".shape", b.shape)
print("asarray.ndim", np.asarray(b).ndim)
# ('.ndim', 2)
# ('.shape', (3, 2))
# ('asarray.ndim', 2)

...所以我得到了我期望的信息。

但是我想知道 - 为什么numpy在结构化数组中表现得像这样 - 并且有一种方法可以直接从原始结构化数组(a)中检索3x2形状信息,而无需“转换”为“正常的“阵列?

2 个答案:

答案 0 :(得分:1)

numpy数组的维度是独立于数据类型定义的,并且以对float64等简单数据类型和更复杂的用户定义类型一致的方式定义。请记住,dtype可能是一个非常奇特的对象,成员甚至可以是不同类型的。你期待看到你喜欢的类型中的numpy,并假设它是一个常规数组。

如果您想知道自定义类型中有多少元素,可以从len(a.dtype)中找到它。

答案 1 :(得分:1)

对于相同类型的元素的结构化数组,您可以使用view

>>> dtype = [('x','f4'),('y','f4')]
>>> a = np.array([(1.5,2.5), (3.,4.), (1.,3.)], dtype=dtype)
>>> a.view('f4').reshape(a.shape[0], -1)
array([[ 1.5,  2.5],
       [ 3. ,  4. ],
       [ 1. ,  3. ]], dtype=float32)

在一般情况下,您应该小心,因为您的记录元素可能具有不同的大小,并且翻译可能含糊不清:

>>> dtype = [('x','f4'), ('y','f8')]
>>> a = np.array([(1.5,2.5), (3.,4.), (1.,3.)], dtype=dtype)
>>> a.view('f8')
Traceback (most recent call last):
  ...
ValueError: new type not compatible with array.
>>> a.view('f4').reshape(a.shape[0], -1)
array([[ 1.5   ,  0.    ,  2.0625],
       [ 3.    ,  0.    ,  2.25  ],
       [ 1.    ,  0.    ,  2.125 ]], dtype=float32)

甚至喜欢:

>>> a.view('i1').reshape(a.shape[0], -1)
array([[   0,    0,  -64,   63,    0,    0,    0,    0,    0,    0,    4,   64],
       [   0,    0,   64,   64,    0,    0,    0,    0,    0,    0,   16,   64],
       [   0,    0, -128,   63,    0,    0,    0,    0,    0,    0,    8,   64]],  dtype=int8)