这是类似措辞的问题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形状信息,而无需“转换”为“正常的“阵列?
答案 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)