创建一个 Numpy 结构标量而不是数组

Ham*_*asi 5 python numpy

我刚刚发现了 Numpy 结构化数组,我发现它们非常强大。我的脑海中自然而然地出现了一个问题:我到底如何创建一个 Numpy 结构标量。让我告诉你我的意思。假设我想要一个包含一些数据的结构:

import numpy as np
dtype = np.dtype([('a', np.float_), ('b', np.int_)])
ar = np.array((0.5, 1), dtype=dtype)
ar['a']
Run Code Online (Sandbox Code Playgroud)

这给了我array(0.5)而不是0.5. 另一方面,如果我这样做:

import numpy as np
dtype = np.dtype([('a', np.float_), ('b', np.int_)])
ar = np.array([(0.5, 1)], dtype=dtype)
ar[0]['a']
Run Code Online (Sandbox Code Playgroud)

我明白了0.5,就像我想要的那样。这意味着它ar[0]不是数组,而是标量。是否有可能以比我所描述的更优雅的方式创建结构化标量?

hpa*_*ulj 7

Singleton 这个词不太合适,但我明白你想要的。

arr = np.array((0.5, 1), dtype=dtype)
Run Code Online (Sandbox Code Playgroud)

创建此数据类型的 0d 单元素数组。检查它的 dtype 和 shape。

arr.item()返回一个元组(0.5, 1)。阿苏测试arr[()]arr.tolist()

np.float64(0.5)使用 numpy 包装器创建一个浮点数。它与 类似,但不完全相同np.array(0.5)。他们的方法有些不同。

我不知道任何与复合数据类型类似的事情。


In [123]: dt = np.dtype('i,f,U10')
In [124]: dt
Out[124]: dtype([('f0', '<i4'), ('f1', '<f4'), ('f2', '<U10')])
In [125]: arr = np.array((1,2,3),dtype=dt)
In [126]: arr
Out[126]: 
array((1,  2., '3'),
      dtype=[('f0', '<i4'), ('f1', '<f4'), ('f2', '<U10')])
In [127]: arr.shape
Out[127]: ()
Run Code Online (Sandbox Code Playgroud)

arr是一个 0d 1 元素数组。它可以通过以下方式建立索引:

In [128]: arr[()]
Out[128]: (1,  2., '3')
In [129]: type(_)
Out[129]: numpy.void
Run Code Online (Sandbox Code Playgroud)

该索引生成一个np.void对象。对 0d 浮点数组执行相同的操作将生成一个np.float对象。

但您不能使用np.void((1,2,3), dtype=dt)直接创建这样的对象(与 相比np.float(12.34))。

item是从数组中提取“标量”的正常方法。这里它返回一个元组,与我们用作创建输入的对象类型相同arr

In [131]: arr.item()
Out[131]: (1, 2.0, '3')
In [132]: type(_)
Out[132]: tuple
Run Code Online (Sandbox Code Playgroud)

np.asscalar(arr)返回相同的元组。

对象和元组之间的一个区别np.void是,它仍然可以使用字段名称 进行索引,arr[()]['f0']而元组必须使用数字进行索引arr.item()[0]。仍然void有一个dtype,而元组没有。

fromrecords使recarray. 这类似于结构化数组,但允许我们将字段作为属性访问。它实际上可能是一个较旧的类,已合并到numpy,因此有np.rec前缀。我们大多数情况下使用结构化数组,尽管np.rec仍然有一些方便的功能。(实际上在numpy.lib.recfunctions):

In [133]: res = np.rec.fromrecords((1,2,3), dt)
In [134]: res
Out[134]: 
rec.array((1,  2., '3'), 
          dtype=[('f0', '<i4'), ('f1', '<f4'), ('f2', '<U10')])
In [135]: res.f0
Out[135]: array(1, dtype=int32)
In [136]: res.item()
Out[136]: (1, 2.0, '3')
In [137]: type(_)
Out[137]: tuple
In [138]: res[()]
Out[138]: (1, 2.0, '3')
In [139]: type(_)
Out[139]: numpy.record
Run Code Online (Sandbox Code Playgroud)

所以这产生了 anp.record而不是 a np.void。但这只是一个子类:

In [143]: numpy.record.__mro__
Out[143]: (numpy.record, numpy.void, numpy.flexible, numpy.generic, object)
Run Code Online (Sandbox Code Playgroud)

通过字段名称访问结构化数组会给出相应数据类型(和相同形状)的数组

In [145]: arr['f1']
Out[145]: array(2.0, dtype=float32)
In [146]: arr[()]['f1']
Out[146]: 2.0
In [147]: type(_)
Out[147]: numpy.float32
Run Code Online (Sandbox Code Playgroud)

Out[146]也可以用 来创建np.float32(2.0)


ar[0]检查我对一维数组的评论:

In [158]: arr1d = np.array([(1,2,3)], dt)
In [159]: arr1d
Out[159]: 
array([(1,  2., '3')],
      dtype=[('f0', '<i4'), ('f1', '<f4'), ('f2', '<U10')])
In [160]: arr1d[0]
Out[160]: (1,  2., '3')
In [161]: type(_)
Out[161]: numpy.void
Run Code Online (Sandbox Code Playgroud)

因此arr[()]arr1d[0]对它们各自大小的数组执行相同的操作。同样arr2d[0,0],也可以写成arr2d[(0,0)]