结构化数组#

介绍#

结构化数组是数据类型为简单数据类型组合并以一系列命名 字段 组织的 ndarray.例如,:

>>> x = np.array([('Rex', 9, 81.0), ('Fido', 3, 27.0)],
...              dtype=[('name', 'U10'), ('age', 'i4'), ('weight', 'f4')])
>>> x
array([('Rex', 9, 81.), ('Fido', 3, 27.)],
      dtype=[('name', '<U10'), ('age', '<i4'), ('weight', '<f4')])

这里 x 是一个长度为两的一维数组,其数据类型是一个包含三个字段的结构:1. 一个长度为10或更少的字符串,名为 ‘name’,2. 一个名为 ‘age’ 的32位整数,以及 3. 一个名为 ‘weight’ 的32位浮点数.

如果你在位置1索引 x ,你会得到一个结构:

>>> x[1]
np.void(('Fido', 3, 27.0), dtype=[('name', '<U10'), ('age', '<i4'), ('weight', '<f4')])

你可以通过使用字段名称索引访问和修改结构化数组的各个字段:

>>> x['age']
array([9, 3], dtype=int32)
>>> x['age'] = 5
>>> x
array([('Rex', 5, 81.), ('Fido', 5, 27.)],
      dtype=[('name', '<U10'), ('age', '<i4'), ('weight', '<f4')])

结构化数据类型旨在能够模仿C语言中的’结构体’,并共享类似的内存布局.它们用于与C代码接口和低级操作结构化缓冲区,例如用于解释二进制数据块.为了这些目的,它们支持专门的功能,如子数组、嵌套数据类型和联合体,并允许控制结构的内存布局.

想要操作表格数据(如存储在csv文件中的数据)的用户可能会发现其他pydata项目更适合,例如xarray、pandas或DataArray.这些项目为表格数据分析提供了高级接口,并且针对该用途进行了更好的优化.例如,numpy中结构化数组的类C结构内存布局可能会导致较差的缓存行为.

结构化数据类型#

一个结构化数据类型可以被认为是一个特定长度(结构体的 itemsize)的字节序列,这些字节被解释为一组字段的集合.每个字段都有一个名称、一个数据类型和一个在结构体中的字节偏移量.字段的数据类型可以是任何 numpy 数据类型,包括其他结构化数据类型,它也可以是一个 子数组数据类型,其行为类似于指定形状的 ndarray.字段的偏移量是任意的,字段甚至可以重叠.这些偏移量通常由 numpy 自动确定,但也可以指定.

结构化数据类型创建#

可以使用函数 numpy.dtype 创建结构化数据类型.有四种不同的规范形式,它们在灵活性和简洁性上有所不同.这些在 数据类型对象 参考页中有进一步的文档说明,总结如下:

  1. 一个元组列表,每个字段一个元组

    每个元组的形式是 (fieldname, datatype, shape) ,其中 shape 是可选的.``fieldname`` 是一个字符串(如果使用标题,则为元组,见下面的 字段标题 ),``datatype`` 可以是任何可转换为数据类型的对象,``shape`` 是一个整数元组,指定子数组形状.

    >>> np.dtype([('x', 'f4'), ('y', np.float32), ('z', 'f4', (2, 2))])
    dtype([('x', '<f4'), ('y', '<f4'), ('z', '<f4', (2, 2))])
    

    如果 fieldname 是空字符串 '' ,该字段将被赋予一个默认名称,形式为 f# ,其中 # 是字段的整数索引,从左到右从0开始计数:

    >>> np.dtype([('x', 'f4'), ('', 'i4'), ('z', 'i8')])
    dtype([('x', '<f4'), ('f1', '<i4'), ('z', '<i8')])
    

    结构中字段的字节偏移量和总结构项大小是自动确定的.

  2. 一串以逗号分隔的 dtype 规范

    在这种简写表示法中,任何 字符串数据类型规范 都可以在字符串中使用,并用逗号分隔.字段的项目大小和字节偏移量是自动确定的,字段名称被赋予默认名称 f0, f1 等.:

    >>> np.dtype('i8, f4, S3')
    dtype([('f0', '<i8'), ('f1', '<f4'), ('f2', 'S3')])
    >>> np.dtype('3int8, float32, (2, 3)float64')
    dtype([('f0', 'i1', (3,)), ('f1', '<f4'), ('f2', '<f8', (2, 3))])
    
  3. 字段参数数组的字典

    这是最灵活的规范形式,因为它允许控制字段的字节偏移量和结构的项目大小.

    字典有两个必需的键,’names’ 和 ‘formats’,以及四个可选的键,’offsets’、’itemsize’、’aligned’ 和 ‘titles’.’names’ 和 ‘formats’ 的值应分别为字段名称列表和 dtype 规范列表,长度相同.可选的 ‘offsets’ 值应为整数字节偏移列表,每个字段在结构中一个.如果未给出 ‘offsets’,则自动确定偏移量.可选的 ‘itemsize’ 值应为描述 dtype 总字节大小的整数,必须足够大以包含所有字段.:

    >>> np.dtype({'names': ['col1', 'col2'], 'formats': ['i4', 'f4']})
    dtype([('col1', '<i4'), ('col2', '<f4')])
    >>> np.dtype({'names': ['col1', 'col2'],
    ...           'formats': ['i4', 'f4'],
    ...           'offsets': [0, 4],
    ...           'itemsize': 12})
    dtype({'names': ['col1', 'col2'], 'formats': ['<i4', '<f4'], 'offsets': [0, 4], 'itemsize': 12})
    

    偏移量可以选择为使得字段重叠,尽管这意味着对一个字段的赋值可能会破坏任何重叠字段的数据.作为一种例外,:class:numpy.object_ 类型的字段不能与其他字段重叠,因为存在破坏内部对象指针并随后解引用的风险.

    可选的 ‘aligned’ 值可以设置为 True 以使自动偏移计算使用对齐的偏移(参见 自动字节偏移和对齐),就像 numpy.dtype 的 ‘align’ 关键字参数被设置为 True 一样.

    可选的 ‘titles’ 值应该是一个与 ‘names’ 长度相同的标题列表,请参见下面的 字段标题.

  4. 字段名称的字典

    字典的键是字段名,值是元组,指定类型和偏移量:

    >>> np.dtype({'col1': ('i1', 0), 'col2': ('f4', 1)})
    dtype([('col1', 'i1'), ('col2', '<f4')])
    

    这种形式不鼓励使用,因为在 Python 3.6 之前的 Python 版本中,Python 字典不保留顺序.:ref:字段标题 可以通过使用 3 元组来指定,见下文.

操作和显示结构化数据类型#

结构化数据类型的字段名称列表可以在 dtype 对象的 names 属性中找到:

>>> d = np.dtype([('x', 'i8'), ('y', 'f4')])
>>> d.names
('x', 'y')

每个单独字段的 dtype 可以通过名称查找:

>>> d['x']
dtype('int64')

字段名称可以通过将 names 属性赋值为一个相同长度的字符串序列来修改.

dtype 对象还有一个类似字典的属性,``fields``,其键是字段名称(以及 字段标题,见下文),其值是包含每个字段的 dtype 和字节偏移量的元组.:

>>> d.fields
mappingproxy({'x': (dtype('int64'), 0), 'y': (dtype('float32'), 8)})

对于非结构化数组,``names`` 和 fields 属性都将等于 None.推荐使用 if dt.names is not None 而不是 if dt.names 来测试 dtype 是否为结构化,以考虑具有 0 个字段的 dtype.

如果可能,结构化数据类型的字符串表示形式以”元组列表”形式显示,否则 numpy 会回退到使用更通用的字典形式.

自动字节偏移和对齐#

Numpy 使用两种方法之一来自动确定字段字节偏移量和结构化数据类型的整体 itemsize,具体取决于是否将 align=True 指定为 numpy.dtype 的关键字参数.

默认情况下 (align=False),numpy 会将字段打包在一起,使得每个字段从上一个字段结束的字节偏移处开始,并且字段在内存中是连续的.:

>>> def print_offsets(d):
...     print("offsets:", [d.fields[name][1] for name in d.names])
...     print("itemsize:", d.itemsize)
>>> print_offsets(np.dtype('u1, u1, i4, u1, i8, u2'))
offsets: [0, 1, 2, 6, 7, 15]
itemsize: 17

如果设置了 align=True ,numpy 将以许多 C 编译器填充 C 结构的方式填充结构.对齐的结构在某些情况下可以提高性能,但代价是增加了数据类型的大小.在字段之间插入填充字节,使得每个字段的字节偏移量是其对齐的倍数,这通常等于简单数据类型字段的大小(以字节为单位),请参见 PyArray_Descr.alignment .结构还将添加尾随填充,使其 itemsize 为最大字段对齐的倍数.:

>>> print_offsets(np.dtype('u1, u1, i4, u1, i8, u2', align=True))
offsets: [0, 1, 4, 8, 16, 24]
itemsize: 32

请注意,尽管几乎所有现代 C 编译器默认情况下都以这种方式填充,但 C 结构中的填充是依赖于 C 实现的,因此这种内存布局不能保证完全匹配 C 程序中相应结构体的布局.可能需要在 numpy 端或 C 端进行一些工作,以获得完全对应.

如果在基于字典的 dtype 规范中使用可选的 offsets 键指定了偏移量,设置 align=True 将检查每个字段的偏移量是否是其大小的倍数,并且 itemsize 是否是最大字段大小的倍数,如果不是,则引发异常.

如果结构化数组的字段偏移量和项目大小满足对齐条件,该数组将设置 ALIGNED 标志.

一个便利函数 numpy.lib.recfunctions.repack_fields 将一个对齐的数据类型或数组转换为打包的,反之亦然.它接受一个数据类型或结构化ndarray作为参数,并返回一个字段重新打包的副本,带有或不带填充字节.

字段标题#

除了字段名称外,字段还可以有一个相关的 标题 ,这是一个替代名称,有时用作字段的附加描述或别名.标题可以像字段名称一样用于索引数组.

在使用元组列表形式的 dtype 规范时添加标题,可以将字段名称指定为两个字符串的元组,而不是单个字符串,这将分别是字段的标题和字段名称.例如:

>>> np.dtype([(('my title', 'name'), 'f4')])
dtype([(('my title', 'name'), '<f4')])

在使用基于字典的第一种规范形式时,标题可以作为额外的 'titles' 键提供,如上所述.在使用第二种(不推荐)基于字典的规范时,可以通过提供一个 3 元素元组 (datatype, offset, title) 而不是通常的 2 元素元组来提供标题:

>>> np.dtype({'name': ('i4', 0, 'my title')})
dtype([(('my title', 'name'), '<i4')])

如果使用了任何标题,``dtype.fields`` 字典将包含标题作为键.这意味着实际上,带有标题的字段在字段字典中会被表示两次.这些字段的元组值还将有一个第三个元素,即字段标题.因此,并且由于 names 属性保留字段顺序而 fields 属性可能不会,建议使用 dtype 的 names 属性遍历 dtype 的字段,这样不会列出标题,如下所示:

>>> for name in d.names:
...     print(d.fields[name][:2])
(dtype('int64'), 0)
(dtype('float32'), 8)

联合类型#

结构化数据类型在 numpy 中实现,默认情况下具有基类型 numpy.void ,但可以使用 (base_dtype, dtype) 形式的 dtype 规范将其他 numpy 类型解释为结构化类型,如 数据类型对象 中所述.这里,``base_dtype`` 是所需的底层 dtype,字段和标志将从 dtype 复制.这种 dtype 类似于 C 语言中的 ‘union’.

索引和分配给结构化数组#

将数据分配给结构化数组#

有多种方法可以为结构化数组赋值:使用Python元组、使用标量值或使用其他结构化数组.

Python 原生类型(元组)的赋值#

为结构化数组赋值的最简单方法是使用 Python 元组.每个赋值应该是长度等于数组中字段数的元组,而不是列表或数组,因为这些会触发 numpy 的广播规则.元组的元素从左到右依次分配给数组的连续字段:

>>> x = np.array([(1, 2, 3), (4, 5, 6)], dtype='i8, f4, f8')
>>> x[1] = (7, 8, 9)
>>> x
array([(1, 2., 3.), (7, 8., 9.)],
     dtype=[('f0', '<i8'), ('f1', '<f4'), ('f2', '<f8')])

标量赋值#

分配给结构化元素的标量将被分配给所有字段.当标量被分配给结构化数组,或者当非结构化数组被分配给结构化数组时,会发生这种情况:

>>> x = np.zeros(2, dtype='i8, f4, ?, S1')
>>> x[:] = 3
>>> x
array([(3, 3., True, b'3'), (3, 3., True, b'3')],
      dtype=[('f0', '<i8'), ('f1', '<f4'), ('f2', '?'), ('f3', 'S1')])
>>> x[:] = np.arange(2)
>>> x
array([(0, 0., False, b'0'), (1, 1., True, b'1')],
      dtype=[('f0', '<i8'), ('f1', '<f4'), ('f2', '?'), ('f3', 'S1')])

结构化数组也可以分配给非结构化数组,但前提是结构化数据类型只有一个字段:

>>> twofield = np.zeros(2, dtype=[('A', 'i4'), ('B', 'i4')])
>>> onefield = np.zeros(2, dtype=[('A', 'i4')])
>>> nostruct = np.zeros(2, dtype='i4')
>>> nostruct[:] = twofield
Traceback (most recent call last):
...
TypeError: Cannot cast array data from dtype([('A', '<i4'), ('B', '<i4')]) to dtype('int32') according to the rule 'unsafe'

从其他结构化数组赋值#

两个结构化数组之间的赋值就好像源元素被转换为元组,然后赋值给目标元素.也就是说,源数组的第一个字段被赋值给目标数组的第一个字段,第二个字段同样如此,依此类推,不考虑字段名称.具有不同数量字段的结构化数组不能相互赋值.目标结构中不属于任何字段的字节不受影响.:

>>> a = np.zeros(3, dtype=[('a', 'i8'), ('b', 'f4'), ('c', 'S3')])
>>> b = np.ones(3, dtype=[('x', 'f4'), ('y', 'S3'), ('z', 'O')])
>>> b[:] = a
>>> b
array([(0., b'0.0', b''), (0., b'0.0', b''), (0., b'0.0', b'')],
      dtype=[('x', '<f4'), ('y', 'S3'), ('z', 'O')])

涉及子数组的赋值#

当分配给子数组字段时,分配的值将首先被广播到子数组的形状.

索引结构化数组#

访问单个字段#

结构化数组的各个字段可以通过使用字段名称索引数组来访问和修改.:

>>> x = np.array([(1, 2), (3, 4)], dtype=[('foo', 'i8'), ('bar', 'f4')])
>>> x['foo']
array([1, 3])
>>> x['foo'] = 10
>>> x
array([(10, 2.), (10, 4.)],
      dtype=[('foo', '<i8'), ('bar', '<f4')])

生成的数组是原始数组的视图.它共享相同的内存位置,并且写入视图将修改原始数组.:

>>> y = x['bar']
>>> y[:] = 11
>>> x
array([(10, 11.), (10, 11.)],
      dtype=[('foo', '<i8'), ('bar', '<f4')])

此视图具有与索引字段相同的 dtype 和 itemsize,因此它通常是一个非结构化数组,除了嵌套结构的情况.

>>> y.dtype, y.shape, y.strides
(dtype('float32'), (2,), (12,))

如果访问的字段是一个子数组,子数组的维度会被附加到结果的形状中:

>>> x = np.zeros((2, 2), dtype=[('a', np.int32), ('b', np.float64, (3, 3))])
>>> x['a'].shape
(2, 2)
>>> x['b'].shape
(2, 2, 3, 3)

访问多个字段#

可以使用多字段索引对结构化数组进行索引和赋值,其中索引是字段名称的列表.

警告

多字段索引的行为从 Numpy 1.15 到 Numpy 1.16 发生了变化.

使用多字段索引的结果是原始数组的视图,如下所示:

>>> a = np.zeros(3, dtype=[('a', 'i4'), ('b', 'i4'), ('c', 'f4')])
>>> a[['a', 'c']]
array([(0, 0.), (0, 0.), (0, 0.)],
     dtype={'names': ['a', 'c'], 'formats': ['<i4', '<f4'], 'offsets': [0, 8], 'itemsize': 12})

对视图的赋值会修改原始数组.视图的字段将按它们被索引的顺序排列.请注意,与单字段索引不同,视图的 dtype 与原始数组具有相同的 itemsize,并且在原始数组中的相同偏移位置具有字段,未索引的字段仅仅是缺失的.

警告

在 Numpy 1.15 中,使用多字段索引对数组进行索引会返回上述结果的副本,但字段在内存中打包在一起,就像通过 numpy.lib.recfunctions.repack_fields 传递一样.

自 Numpy 1.16 以来的新行为导致在未索引字段的位置比 1.15 多了额外的”填充”字节.你需要更新任何依赖数据具有”紧凑”布局的代码.例如,像这样的代码:

>>> a[['a', 'c']].view('i8')  # Fails in Numpy 1.16
Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
ValueError: When changing to a smaller dtype, its size must be a divisor of the size of original dtype

需要更改.自 Numpy 1.12 以来,此代码引发了 FutureWarning,类似代码自 1.7 以来引发了 FutureWarning.

在1.16中,在 numpy.lib.recfunctions 模块中引入了许多函数,以帮助用户适应这一变化.这些函数包括 numpy.lib.recfunctions.repack_fieldsnumpy.lib.recfunctions.structured_to_unstructurednumpy.lib.recfunctions.unstructured_to_structurednumpy.lib.recfunctions.apply_along_fieldsnumpy.lib.recfunctions.assign_fields_by_namenumpy.lib.recfunctions.require_fields.

函数 numpy.lib.recfunctions.repack_fields 总是可以用来重现旧的行为,因为它将返回结构化数组的打包副本.例如,上面的代码可以用以下代码替换:

>>> from numpy.lib.recfunctions import repack_fields
>>> repack_fields(a[['a', 'c']]).view('i8')  # supported in 1.16
array([0, 0, 0])

此外,numpy 现在提供了一个新函数 numpy.lib.recfunctions.structured_to_unstructured,对于希望将结构化数组转换为非结构化数组的用户来说,这是一个更安全和更高效的选择,因为上述视图通常就是为此目的而设计的.这个函数允许安全地转换为非结构化类型,考虑到填充,通常避免复制,并且还会根据需要转换数据类型,不像视图那样.代码如下:

>>> b = np.zeros(3, dtype=[('x', 'f4'), ('y', 'f4'), ('z', 'f4')])
>>> b[['x', 'z']].view('f4')
array([0., 0., 0., 0., 0., 0., 0., 0., 0.], dtype=float32)

可以通过替换来使其更安全:

>>> from numpy.lib.recfunctions import structured_to_unstructured
>>> structured_to_unstructured(b[['x', 'z']])
array([[0., 0.],
       [0., 0.],
       [0., 0.]], dtype=float32)

对具有多字段索引的数组进行赋值会修改原始数组:

>>> a[['a', 'c']] = (2, 3)
>>> a
array([(2, 0, 3.), (2, 0, 3.), (2, 0, 3.)],
      dtype=[('a', '<i4'), ('b', '<i4'), ('c', '<f4')])

这遵守上述结构化数组赋值规则.例如,这意味着可以使用适当的多字段索引来交换两个字段的值:

>>> a[['a', 'c']] = a[['c', 'a']]

使用整数索引获取结构化标量#

索引结构化数组的一个元素(使用整数索引)返回一个结构化标量:

>>> x = np.array([(1, 2., 3.)], dtype='i, f, f')
>>> scalar = x[0]
>>> scalar
np.void((1, 2.0, 3.0), dtype=[('f0', '<i4'), ('f1', '<f4'), ('f2', '<f4')])
>>> type(scalar)
<class 'numpy.void'>

与其他 numpy 标量不同,结构化标量是可变的,并且表现为原始数组的视图,因此修改标量将修改原始数组.结构化标量还支持按字段名称进行访问和赋值:

>>> x = np.array([(1, 2), (3, 4)], dtype=[('foo', 'i8'), ('bar', 'f4')])
>>> s = x[0]
>>> s['bar'] = 100
>>> x
array([(1, 100.), (3, 4.)],
      dtype=[('foo', '<i8'), ('bar', '<f4')])

类似于元组,结构化标量也可以用整数进行索引:

>>> scalar = np.array([(1, 2., 3.)], dtype='i, f, f')[0]
>>> scalar[0]
np.int32(1)
>>> scalar[1] = 4

因此,元组可以被认为是与 numpy 的结构化类型等效的本地 Python 类型,就像本地 Python 整数与 numpy 的整数类型等效一样.结构化标量可以通过调用 numpy.ndarray.item 转换为元组:

>>> scalar.item(), type(scalar.item())
((1, 4.0, 3.0), <class 'tuple'>)

查看包含对象的结构化数组#

为了防止在 对象 类型的字段中破坏对象指针,numpy 目前不允许包含对象的结构化数组的视图.

结构比较和提升#

如果两个空结构数组的dtypes相等,测试数组的相等性将产生一个布尔数组,其维度与原始数组相同,其中元素设置为 True ,其中相应结构的所有字段都相等:

>>> a = np.array([(1, 1), (2, 2)], dtype=[('a', 'i4'), ('b', 'i4')])
>>> b = np.array([(1, 1), (2, 3)], dtype=[('a', 'i4'), ('b', 'i4')])
>>> a == b
array([True, False])

NumPy 将提升单个字段数据类型以执行比较.因此,以下也是有效的(注意 'a' 字段的 'f4' 数据类型):

>>> b = np.array([(1.0, 1), (2.5, 2)], dtype=[("a", "f4"), ("b", "i4")])
>>> a == b
array([True, False])

要比较两个结构化数组,必须能够将它们提升为 numpy.result_typenumpy.promote_types 返回的公共 dtype.这要求字段数量、字段名称和字段标题必须完全匹配.当提升不可能时,例如由于字段名称不匹配,NumPy 将引发错误.两个结构化 dtype 之间的提升结果是一个确保所有字段为本地字节顺序的规范 dtype:

>>> np.result_type(np.dtype("i,>i"))
dtype([('f0', '<i4'), ('f1', '<i4')])
>>> np.result_type(np.dtype("i,>i"), np.dtype("i,i"))
dtype([('f0', '<i4'), ('f1', '<i4')])

从提升得到的 dtype 也保证是打包的,这意味着所有字段都是连续排列的,并且任何不必要的填充都被移除:

>>> dt = np.dtype("i1,V3,i4,V1")[["f0", "f2"]]
>>> dt
dtype({'names': ['f0', 'f2'], 'formats': ['i1', '<i4'], 'offsets': [0, 4], 'itemsize': 9})
>>> np.result_type(dt)
dtype([('f0', 'i1'), ('f2', '<i4')])

注意,结果打印时没有 offsetsitemsize 表示没有额外的填充.如果使用 align=True 创建结构化 dtype 以确保 dtype.isalignedstruct 为真,则此属性得以保留:

>>> dt = np.dtype("i1,V3,i4,V1", align=True)[["f0", "f2"]]
>>> dt
dtype({'names': ['f0', 'f2'], 'formats': ['i1', '<i4'], 'offsets': [0, 4], 'itemsize': 12}, align=True)

>>> np.result_type(dt)
dtype([('f0', 'i1'), ('f2', '<i4')], align=True)
>>> np.result_type(dt).isalignedstruct
True

在提升多个数据类型时,如果任何一个输入是::,则结果是对齐的

>>> np.result_type(np.dtype("i,i"), np.dtype("i,i", align=True))
dtype([('f0', '<i4'), ('f1', '<i4')], align=True)

当比较空结构化数组时,``<`` 和 > 运算符总是返回 False,并且不支持算术和位运算操作.

在 1.23 版本发生变更: 在 NumPy 1.23 之前,当类型提升失败时会给出警告并返回 False.此外,类型提升的限制更为严格:它会拒绝上述混合浮点数/整数比较的例子.

记录数组#

作为一种可选的便利,numpy 提供了一个 ndarray 子类,:class:numpy.recarray,它允许通过属性而不是仅通过索引访问结构化数组的字段.记录数组使用一种特殊的datatype,:class:numpy.record,它允许在从数组获得的结构化标量上通过属性访问字段.``numpy.rec`` 模块提供了从各种对象创建 recarrays 的函数.在 numpy.lib.recfunctions 中可以找到用于创建和操作结构化数组的额外辅助函数.

创建记录数组的最简单方法是使用 numpy.rec.array:

>>> recordarr = np.rec.array([(1, 2., 'Hello'), (2, 3., "World")],
...                    dtype=[('foo', 'i4'),('bar', 'f4'), ('baz', 'S10')])
>>> recordarr.bar
array([2., 3.], dtype=float32)
>>> recordarr[1:2]
rec.array([(2, 3., b'World')],
      dtype=[('foo', '<i4'), ('bar', '<f4'), ('baz', 'S10')])
>>> recordarr[1:2].foo
array([2], dtype=int32)
>>> recordarr.foo[1:2]
array([2], dtype=int32)
>>> recordarr[1].baz
b'World'

numpy.rec.array 可以将各种参数转换为记录数组,包括结构化数组:

>>> arr = np.array([(1, 2., 'Hello'), (2, 3., "World")],
...             dtype=[('foo', 'i4'), ('bar', 'f4'), ('baz', 'S10')])
>>> recordarr = np.rec.array(arr)

numpy.rec 模块提供了许多其他用于创建记录数组的便利函数,请参见 记录数组创建例程.

可以使用适当的 view 获得结构化数组的记录数组表示:

>>> arr = np.array([(1, 2., 'Hello'), (2, 3., "World")],
...                dtype=[('foo', 'i4'),('bar', 'f4'), ('baz', 'S10')])
>>> recordarr = arr.view(dtype=np.dtype((np.record, arr.dtype)),
...                      type=np.recarray)

为了方便,将一个 ndarray 视为类型 numpy.recarray 将自动转换为 numpy.record 数据类型,因此 dtype 可以省略不写:

>>> recordarr = arr.view(np.recarray)
>>> recordarr.dtype
dtype((numpy.record, [('foo', '<i4'), ('bar', '<f4'), ('baz', 'S10')]))

要返回到一个普通的 ndarray,dtype 和 type 都必须重置.以下视图实现了这一点,考虑到 recordarr 不是结构化类型的不寻常情况:

>>> arr2 = recordarr.view(recordarr.dtype.fields or recordarr.dtype, np.ndarray)

通过索引或属性访问的记录数组字段,如果字段具有结构化类型,则返回为记录数组,否则返回为普通ndarray.:

>>> recordarr = np.rec.array([('Hello', (1, 2)), ("World", (3, 4))],
...                 dtype=[('foo', 'S6'),('bar', [('A', int), ('B', int)])])
>>> type(recordarr.foo)
<class 'numpy.ndarray'>
>>> type(recordarr.bar)
<class 'numpy.rec.recarray'>

请注意,如果一个字段与 ndarray 属性同名,ndarray 属性将优先.这样的字段将无法通过属性访问,但仍可以通过索引访问.

Recarray 辅助函数#

用于操作结构化数组的实用工具集合.

这些函数中的大多数最初是由 John Hunter 为 matplotlib 实现的.它们已被重写和扩展以方便使用.

numpy.lib.recfunctions.append_fields(base, names, data, dtypes=None, fill_value=-1, usemask=True, asrecarray=False)[源代码][源代码]#

向现有数组添加新字段.

字段的名称通过 names 参数给出,相应的值通过 data 参数给出.如果只追加一个字段,`names`、datadtypes 不必是列表,只需是值.

参数:
base数组

要扩展的输入数组.

names字符串, 序列

字符串或字符串序列,对应于新字段的名称.

data数组或数组序列

存储要添加到基础字段的数组或数组序列.

dtypes数据类型的序列,可选

数据类型或数据类型序列.如果为 None,则从 data 中估计数据类型.

fill_value{float}, 可选

填充值用于在较短的数组上填充缺失的数据.

usemask{False, True}, 可选

是否返回一个掩码数组.

asrecarray{False, True}, 可选

是否返回一个 recarray(MaskedRecords).

numpy.lib.recfunctions.apply_along_fields(func, arr)[源代码][源代码]#

将函数 ‘func’ 作为对结构化数组字段的缩减操作应用.

这与 numpy.apply_along_axis 类似,但将结构化数组的字段视为额外的轴.所有字段首先按照 numpy.result_type 应用的字段 dtypes 的类型提升规则转换为通用类型.

参数:
func函数

在”字段”维度上应用的函数.该函数必须支持 axis 参数,如 numpy.meannumpy.sum 等.

arrndarray

要应用 func 的结构化数组.

返回:
outndarray

recution 操作的结果

示例

>>> import numpy as np
>>> from numpy.lib import recfunctions as rfn
>>> b = np.array([(1, 2, 5), (4, 5, 7), (7, 8 ,11), (10, 11, 12)],
...              dtype=[('x', 'i4'), ('y', 'f4'), ('z', 'f8')])
>>> rfn.apply_along_fields(np.mean, b)
array([ 2.66666667,  5.33333333,  8.66666667, 11.        ])
>>> rfn.apply_along_fields(np.mean, b[['x', 'z']])
array([ 3. ,  5.5,  9. , 11. ])
numpy.lib.recfunctions.assign_fields_by_name(dst, src, zero_unassigned=True)[源代码][源代码]#

通过字段名称将值从一个结构化数组分配到另一个数组.

通常在 numpy >= 1.14 中,将一个结构化数组赋值给另一个数组会按字段 “位置” 复制,这意味着源数组的第一个字段被复制到目标数组的第一个字段,依此类推,无论字段名称如何.

这个函数通过”按字段名称”复制,使得 dst 中的字段从 src 中同名字段赋值.这适用于嵌套结构.这是在 numpy >= 1.6 到 <= 1.13 中结构赋值的工作方式.

参数:
dstndarray
srcndarray

赋值期间的源数组和目标数组.

zero_unassignedbool, 可选

如果为 True,则在 src 中没有匹配字段的 dst 中的字段将填充值 0(零).这是 numpy <= 1.13 的行为.如果为 False,则这些字段不会被修改.

numpy.lib.recfunctions.drop_fields(base, drop_names, usemask=True, asrecarray=False)[源代码][源代码]#

返回一个新数组,其中删除了 drop_names 中的字段.

嵌套字段是支持的.

在 1.18.0 版本发生变更: drop_fields 如果所有字段都被删除,则返回一个包含0个字段的数组,而不是像以前那样返回 None.

参数:
base数组

输入数组

drop_names字符串或序列

要删除的字段名称对应的字符串或字符串序列.

usemask{False, True}, 可选

是否返回一个掩码数组.

asrecarray字符串或序列,可选

是否返回一个 recarray 或 mrecarray (asrecarray=True) 或者一个普通的 ndarray 或带掩码的数组,具有灵活的 dtype.默认是 False.

示例

>>> import numpy as np
>>> from numpy.lib import recfunctions as rfn
>>> a = np.array([(1, (2, 3.0)), (4, (5, 6.0))],
...   dtype=[('a', np.int64), ('b', [('ba', np.double), ('bb', np.int64)])])
>>> rfn.drop_fields(a, 'a')
array([((2., 3),), ((5., 6),)],
      dtype=[('b', [('ba', '<f8'), ('bb', '<i8')])])
>>> rfn.drop_fields(a, 'ba')
array([(1, (3,)), (4, (6,))], dtype=[('a', '<i8'), ('b', [('bb', '<i8')])])
>>> rfn.drop_fields(a, ['ba', 'bb'])
array([(1,), (4,)], dtype=[('a', '<i8')])
numpy.lib.recfunctions.find_duplicates(a, key=None, ignoremask=True, return_index=False)[源代码][源代码]#

在给定键的结构化数组中查找重复项

参数:
a类数组

输入数组

key{字符串, 无}, 可选

要检查重复项的字段名称.如果为 None,则通过记录进行搜索.

ignoremask{True, False}, 可选

是否应丢弃掩码数据或将其视为重复项.

return_index{False, True}, 可选

是否返回重复值的索引.

示例

>>> import numpy as np
>>> from numpy.lib import recfunctions as rfn
>>> ndtype = [('a', int)]
>>> a = np.ma.array([1, 1, 1, 2, 2, 3, 3],
...         mask=[0, 0, 1, 0, 0, 0, 1]).view(ndtype)
>>> rfn.find_duplicates(a, ignoremask=True, return_index=True)
(masked_array(data=[(1,), (1,), (2,), (2,)],
             mask=[(False,), (False,), (False,), (False,)],
       fill_value=(999999,),
            dtype=[('a', '<i8')]), array([0, 1, 3, 4]))
numpy.lib.recfunctions.flatten_descr(ndtype)[源代码][源代码]#

展平一个结构化数据类型描述.

示例

>>> import numpy as np
>>> from numpy.lib import recfunctions as rfn
>>> ndtype = np.dtype([('a', '<i4'), ('b', [('ba', '<f8'), ('bb', '<i4')])])
>>> rfn.flatten_descr(ndtype)
(('a', dtype('int32')), ('ba', dtype('float64')), ('bb', dtype('int32')))
numpy.lib.recfunctions.get_fieldstructure(adtype, lastname=None, parents=None)[源代码][源代码]#

返回一个字典,其中包含索引其父字段的列表的字段.

此函数用于简化访问嵌套在其他字段中的字段.

参数:
adtypenp.dtype

输入数据类型

lastname可选的

最后处理的字段名称(在递归期间内部使用).

parentsdictionary

父字段字典(在递归期间内部使用).

示例

>>> import numpy as np
>>> from numpy.lib import recfunctions as rfn
>>> ndtype =  np.dtype([('A', int),
...                     ('B', [('BA', int),
...                            ('BB', [('BBA', int), ('BBB', int)])])])
>>> rfn.get_fieldstructure(ndtype)
... # XXX: possible regression, order of BBA and BBB is swapped
{'A': [], 'B': [], 'BA': ['B'], 'BB': ['B'], 'BBA': ['B', 'BB'], 'BBB': ['B', 'BB']}
numpy.lib.recfunctions.get_names(adtype)[源代码][源代码]#

返回输入数据类型的字段名称作为元组.输入数据类型必须有字段,否则会引发错误.

参数:
adtypedtype

输入数据类型

示例

>>> import numpy as np
>>> from numpy.lib import recfunctions as rfn
>>> rfn.get_names(np.empty((1,), dtype=[('A', int)]).dtype)
('A',)
>>> rfn.get_names(np.empty((1,), dtype=[('A',int), ('B', float)]).dtype)
('A', 'B')
>>> adtype = np.dtype([('a', int), ('b', [('ba', int), ('bb', int)])])
>>> rfn.get_names(adtype)
('a', ('b', ('ba', 'bb')))
numpy.lib.recfunctions.get_names_flat(adtype)[源代码][源代码]#

返回输入数据类型的字段名称作为元组.输入数据类型必须有字段,否则会引发错误.嵌套结构会事先被展平.

参数:
adtypedtype

输入数据类型

示例

>>> import numpy as np
>>> from numpy.lib import recfunctions as rfn
>>> rfn.get_names_flat(np.empty((1,), dtype=[('A', int)]).dtype) is None
False
>>> rfn.get_names_flat(np.empty((1,), dtype=[('A',int), ('B', str)]).dtype)
('A', 'B')
>>> adtype = np.dtype([('a', int), ('b', [('ba', int), ('bb', int)])])
>>> rfn.get_names_flat(adtype)
('a', 'b', 'ba', 'bb')
numpy.lib.recfunctions.join_by(key, r1, r2, jointype='inner', r1postfix='1', r2postfix='2', defaults=None, usemask=True, asrecarray=False)[源代码][源代码]#

将数组 r1r2 按键 key 连接.

键应该是字符串或字符串序列,对应于用于连接数组的字段.如果在两个输入数组中找不到 key 字段,则会引发异常. r1r2 都不应该沿 key 有任何重复项:重复项的存在将使输出非常不可靠.请注意,算法不会查找重复项.

参数:
key{字符串, 序列}

一个字符串或一系列对应于用于比较的字段的字符串.

r1, r2数组

结构化数组.

jointype{‘inner’, ‘outer’, ‘leftouter’}, 可选

如果是’inner’,返回r1和r2的共同元素.如果是’outer’,返回共同元素以及r1中不在r2中的元素和r2中不在r1中的元素.如果是’leftouter’,返回共同元素和r1中不在r2中的元素.

r1postfix字符串,可选

附加到 r1 的字段名称的字符串,这些字段在 r2 中存在但在键中不存在.

r2postfix字符串,可选

字符串附加到 r2 的字段名称中,这些字段在 r1 中存在但在键中不存在.

defaults{字典}, 可选

字典将字段名称映射到相应的默认值.

usemask{True, False}, 可选

是否返回一个 MaskedArray(或者当 asrecarray==True 时返回 MaskedRecords)或一个 ndarray.

asrecarray{False, True}, 可选

是否返回一个 recarray(如果 usemask==True 则返回 MaskedRecords)或者只是一个灵活类型的 ndarray.

备注

  • 输出是按照键排序的.

  • 通过删除两个数组中不在键中的字段并连接结果,形成一个临时数组.然后对该数组进行排序,并选择公共条目.输出是通过用选定的条目填充字段来构造的.如果存在一些重复项,匹配不会被保留…

numpy.lib.recfunctions.merge_arrays(seqarrays, fill_value=-1, flatten=False, usemask=False, asrecarray=False)[源代码][源代码]#

按字段合并数组.

参数:
seqarraysndarrays 序列

数组序列

fill_value{float}, 可选

填充值用于在较短的数组上填充缺失的数据.

flatten{False, True}, 可选

是否折叠嵌套字段.

usemask{False, True}, 可选

是否返回一个掩码数组.

asrecarray{False, True}, 可选

是否返回一个 recarray(MaskedRecords).

备注

  • 如果没有掩码,缺失的值将根据其对应类型填充某些内容:

    • -1 用于整数

    • -1.0 用于浮点数

    • '-' 用于字符

    • '-1' 用于字符串

    • True 用于布尔值

  • XXX: 我只是通过经验获得了这些值

示例

>>> import numpy as np
>>> from numpy.lib import recfunctions as rfn
>>> rfn.merge_arrays((np.array([1, 2]), np.array([10., 20., 30.])))
array([( 1, 10.), ( 2, 20.), (-1, 30.)],
      dtype=[('f0', '<i8'), ('f1', '<f8')])
>>> rfn.merge_arrays((np.array([1, 2], dtype=np.int64),
...         np.array([10., 20., 30.])), usemask=False)
 array([(1, 10.0), (2, 20.0), (-1, 30.0)],
         dtype=[('f0', '<i8'), ('f1', '<f8')])
>>> rfn.merge_arrays((np.array([1, 2]).view([('a', np.int64)]),
...               np.array([10., 20., 30.])),
...              usemask=False, asrecarray=True)
rec.array([( 1, 10.), ( 2, 20.), (-1, 30.)],
          dtype=[('a', '<i8'), ('f1', '<f8')])
numpy.lib.recfunctions.rec_append_fields(base, names, data, dtypes=None)[源代码][源代码]#

向现有数组添加新字段.

字段的名称通过 names 参数给出,相应的值通过 data 参数给出.如果只追加一个字段,`names`、datadtypes 不必是列表,只需是值.

参数:
base数组

要扩展的输入数组.

names字符串, 序列

字符串或字符串序列,对应于新字段的名称.

data数组或数组序列

存储要添加到基础字段的数组或数组序列.

dtypes数据类型的序列,可选

数据类型或数据类型序列.如果为 None,则从 data 中估计数据类型.

返回:
appended_arraynp.recarray

参见

append_fields
numpy.lib.recfunctions.rec_drop_fields(base, drop_names)[源代码][源代码]#

返回一个新的 numpy.recarray,其中 drop_names 中的字段被删除.

numpy.lib.recfunctions.rec_join(key, r1, r2, jointype='inner', r1postfix='1', r2postfix='2', defaults=None)[源代码][源代码]#

在键上连接数组 r1r2.与 join_by 的替代方法,总是返回一个 np.recarray.

参见

join_by

等效函数

numpy.lib.recfunctions.recursive_fill_fields(input, output)[源代码][源代码]#

从输出中填充字段到输入中,支持嵌套结构.

参数:
inputndarray

输入数组.

outputndarray

输出数组.

备注

  • output 的大小应至少与 input 相同

示例

>>> import numpy as np
>>> from numpy.lib import recfunctions as rfn
>>> a = np.array([(1, 10.), (2, 20.)], dtype=[('A', np.int64), ('B', np.float64)])
>>> b = np.zeros((3,), dtype=a.dtype)
>>> rfn.recursive_fill_fields(a, b)
array([(1, 10.), (2, 20.), (0,  0.)], dtype=[('A', '<i8'), ('B', '<f8')])
numpy.lib.recfunctions.rename_fields(base, namemapper)[源代码][源代码]#

重命名来自灵活数据类型 ndarray 或 recarray 的字段.

嵌套字段是支持的.

参数:
basendarray

必须修改其字段的数据输入数组.

namemapperdictionary

字典映射旧字段名称到它们的新版本.

示例

>>> import numpy as np
>>> from numpy.lib import recfunctions as rfn
>>> a = np.array([(1, (2, [3.0, 30.])), (4, (5, [6.0, 60.]))],
...   dtype=[('a', int),('b', [('ba', float), ('bb', (float, 2))])])
>>> rfn.rename_fields(a, {'a':'A', 'bb':'BB'})
array([(1, (2., [ 3., 30.])), (4, (5., [ 6., 60.]))],
      dtype=[('A', '<i8'), ('b', [('ba', '<f8'), ('BB', '<f8', (2,))])])
numpy.lib.recfunctions.repack_fields(a, align=False, recurse=False)[源代码][源代码]#

在内存中重新打包结构化数组或 dtype 的字段.

结构化数据类型的内存布局允许字段位于任意字节偏移处.这意味着字段之间可以由填充字节分隔,它们的偏移量可以非单调递增,并且它们可以重叠.

此方法移除任何重叠,并在内存中重新排序字段,使它们的字节偏移量递增,并根据 align 选项添加或移除填充字节,该选项的行为类似于 numpy.dtypealign 选项.

如果 align=False,此方法会生成一个”紧凑”的内存布局,其中每个字段从前一个字段结束的字节开始,并且任何填充字节都会被移除.

如果 align=True,此方法会生成一个”对齐”的内存布局,其中每个字段的偏移量是其对齐的倍数,并且总项大小是最大对齐的倍数,通过根据需要添加填充字节来实现.

参数:
andarray 或 dtype

要重新打包字段的数组或 dtype.

align布尔值

如果为真,使用”对齐”的内存布局,否则使用”紧凑”的布局.

recurse布尔值

如果为真,也会重新打包嵌套结构.

返回:
repackedndarray 或 dtype

复制 a 并重新打包字段,如果不需要重新打包,则返回 a 本身.

示例

>>> import numpy as np
>>> from numpy.lib import recfunctions as rfn
>>> def print_offsets(d):
...     print("offsets:", [d.fields[name][1] for name in d.names])
...     print("itemsize:", d.itemsize)
...
>>> dt = np.dtype('u1, <i8, <f8', align=True)
>>> dt
dtype({'names': ['f0', 'f1', 'f2'], 'formats': ['u1', '<i8', '<f8'], 'offsets': [0, 8, 16], 'itemsize': 24}, align=True)
>>> print_offsets(dt)
offsets: [0, 8, 16]
itemsize: 24
>>> packed_dt = rfn.repack_fields(dt)
>>> packed_dt
dtype([('f0', 'u1'), ('f1', '<i8'), ('f2', '<f8')])
>>> print_offsets(packed_dt)
offsets: [0, 1, 9]
itemsize: 17
numpy.lib.recfunctions.require_fields(array, required_dtype)[源代码][源代码]#

通过按字段名称赋值,将结构化数组转换为新的dtype.

此函数通过名称从旧数组分配到新数组,因此输出数组中字段的值是源数组中具有相同名称的字段的值.这具有创建仅包含”required_dtype”所需字段的新ndarray的效果.

如果在 required_dtype 中的字段名称在输入数组中不存在,则该字段将在输出数组中创建并设置为 0.

参数:
andarray

数组转换

required_dtypedtype

输出数组的`数据类型`

返回:
outndarray

具有新数据类型的数组,字段值从输入数组中具有相同名称的字段复制

示例

>>> import numpy as np
>>> from numpy.lib import recfunctions as rfn
>>> a = np.ones(4, dtype=[('a', 'i4'), ('b', 'f8'), ('c', 'u1')])
>>> rfn.require_fields(a, [('b', 'f4'), ('c', 'u1')])
array([(1., 1), (1., 1), (1., 1), (1., 1)],
  dtype=[('b', '<f4'), ('c', 'u1')])
>>> rfn.require_fields(a, [('b', 'f4'), ('newf', 'u1')])
array([(1., 0), (1., 0), (1., 0), (1., 0)],
  dtype=[('b', '<f4'), ('newf', 'u1')])
numpy.lib.recfunctions.stack_arrays(arrays, defaults=None, usemask=True, asrecarray=False, autoconvert=False)[源代码][源代码]#

按字段将数组叠加

参数:
arrays数组或序列

输入数组的序列.

defaults字典,可选

字典将字段名称映射到相应的默认值.

usemask{True, False}, 可选

是否返回一个 MaskedArray(或者当 asrecarray==True 时返回 MaskedRecords)或一个 ndarray.

asrecarray{False, True}, 可选

是否返回一个 recarray(如果 usemask==True 则返回 MaskedRecords)或者只是一个灵活类型的 ndarray.

autoconvert{False, True}, 可选

是否自动将字段类型转换为最大值.

示例

>>> import numpy as np
>>> from numpy.lib import recfunctions as rfn
>>> x = np.array([1, 2,])
>>> rfn.stack_arrays(x) is x
True
>>> z = np.array([('A', 1), ('B', 2)], dtype=[('A', '|S3'), ('B', float)])
>>> zz = np.array([('a', 10., 100.), ('b', 20., 200.), ('c', 30., 300.)],
...   dtype=[('A', '|S3'), ('B', np.double), ('C', np.double)])
>>> test = rfn.stack_arrays((z,zz))
>>> test
masked_array(data=[(b'A', 1.0, --), (b'B', 2.0, --), (b'a', 10.0, 100.0),
                   (b'b', 20.0, 200.0), (b'c', 30.0, 300.0)],
             mask=[(False, False,  True), (False, False,  True),
                   (False, False, False), (False, False, False),
                   (False, False, False)],
       fill_value=(b'N/A', 1e+20, 1e+20),
            dtype=[('A', 'S3'), ('B', '<f8'), ('C', '<f8')])
numpy.lib.recfunctions.structured_to_unstructured(arr, dtype=None, copy=False, casting='unsafe')[源代码][源代码]#

将一个 n 维结构化数组转换为一个 (n+1) 维非结构化数组.

新的数组将有一个新的最后一维,其大小等于输入数组的字段元素数量.如果未提供,输出数据类型由应用于所有字段数据类型的 numpy 类型提升规则决定.

嵌套字段,以及任何子数组字段的每个元素,都算作一个字段元素.

参数:
arrndarray

要转换的结构化数组或 dtype.不能包含对象数据类型.

dtypedtype,可选

输出非结构化数组的 dtype.

copybool, 可选

如果为真,总是返回一个副本.如果为假,如果 dtype 和字段的步长合适且数组子类型是 numpy.ndarraynumpy.recarraynumpy.memmap 之一时,则返回一个视图.

在 1.25.0 版本发生变更: 如果字段由统一的步长分隔,现在可以返回一个视图.

casting{‘no’, ‘equiv’, ‘safe’, ‘same_kind’, ‘unsafe’}, 可选

请参阅 numpy.ndarray.astype 的转换参数.控制可能发生的数据转换类型.

返回:
unstructuredndarray

具有一个更多维度的非结构化数组.

示例

>>> import numpy as np
>>> from numpy.lib import recfunctions as rfn
>>> a = np.zeros(4, dtype=[('a', 'i4'), ('b', 'f4,u2'), ('c', 'f4', 2)])
>>> a
array([(0, (0., 0), [0., 0.]), (0, (0., 0), [0., 0.]),
       (0, (0., 0), [0., 0.]), (0, (0., 0), [0., 0.])],
      dtype=[('a', '<i4'), ('b', [('f0', '<f4'), ('f1', '<u2')]), ('c', '<f4', (2,))])
>>> rfn.structured_to_unstructured(a)
array([[0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0.]])
>>> b = np.array([(1, 2, 5), (4, 5, 7), (7, 8 ,11), (10, 11, 12)],
...              dtype=[('x', 'i4'), ('y', 'f4'), ('z', 'f8')])
>>> np.mean(rfn.structured_to_unstructured(b[['x', 'z']]), axis=-1)
array([ 3. ,  5.5,  9. , 11. ])
numpy.lib.recfunctions.unstructured_to_structured(arr, dtype=None, names=None, align=False, copy=False, casting='unsafe')[源代码][源代码]#

将一个 n 维非结构化数组转换为一个 (n-1) 维结构化数组.

输入数组的最后一个维度被转换为一个结构,其中字段元素的数量等于输入数组最后一个维度的大小.默认情况下,所有输出字段都具有输入数组的dtype,但可以提供具有相同数量字段元素的输出结构化dtype.

嵌套字段,以及任何子数组字段的每个元素,都算作字段元素的数量.

参数:
arrndarray

要转换的非结构化数组或数据类型.

dtypedtype,可选

输出数组的结构化数据类型

names字符串列表,可选

如果未提供 dtype,这指定了输出 dtype 的字段名称,按顺序排列.字段 dtypes 将与输入数组相同.

align布尔值,可选

是否创建对齐的内存布局.

copybool, 可选

请参阅 numpy.ndarray.astype 的 copy 参数.如果为真,总是返回一个副本.如果为假,并且 dtype 要求得到满足,则返回一个视图.

casting{‘no’, ‘equiv’, ‘safe’, ‘same_kind’, ‘unsafe’}, 可选

请参阅 numpy.ndarray.astype 的转换参数.控制可能发生的数据转换类型.

返回:
structuredndarray

维度较少的结构化数组.

示例

>>> import numpy as np
>>> from numpy.lib import recfunctions as rfn
>>> dt = np.dtype([('a', 'i4'), ('b', 'f4,u2'), ('c', 'f4', 2)])
>>> a = np.arange(20).reshape((4,5))
>>> a
array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14],
       [15, 16, 17, 18, 19]])
>>> rfn.unstructured_to_structured(a, dt)
array([( 0, ( 1.,  2), [ 3.,  4.]), ( 5, ( 6.,  7), [ 8.,  9.]),
       (10, (11., 12), [13., 14.]), (15, (16., 17), [18., 19.])],
      dtype=[('a', '<i4'), ('b', [('f0', '<f4'), ('f1', '<u2')]), ('c', '<f4', (2,))])