numpy 如何创建嵌套的rec数组

5n0oy7gb  于 2023-03-08  发布在  其他
关注(0)|答案(2)|浏览(118)

给定以下数组:

name = np.array(['a', 'b', 'c'])
val = np.array([0.4, 0.5, 0.6])
alt = np.array([1.1, 2.1, 3.1])
b = np.array([17.2])

如何将它们组合成一个如下所示的rearray(或结构化数组,同样的东西):[('a', 'b', 'c'), (0.4, 0.5, 0.6), (1.1, 2.1, 3.1), (17.2)]。其中print(arr["name"])返回('a', 'b', 'c')
实际数据有十几个数组,总有一个数组(b)大小只有1;其他的都有相同的大小,但是大小会有所不同。所以,我正在寻找一个解决方案,可以扩展到这些条件。谢谢。

hzbexzde

hzbexzde1#

定义数据类型:

In [41]: dt = np.dtype([('name','U10'),('val','f'),('alt','f'),('b','f')])

制作所需形状和dtype的零数组:

In [43]: arr = np.zeros(3, dt)

将数组复制到其各自的字段:

In [44]: arr['name']=name; arr['val']=val; arr['alt']=alt    
In [45]: arr['b']=b

结果是:

In [46]: arr
Out[46]: 
array([('a', 0.4, 1.1, 17.2), ('b', 0.5, 2.1, 17.2),
       ('c', 0.6, 3.1, 17.2)],
      dtype=[('name', '<U10'), ('val', '<f4'), ('alt', '<f4'), ('b', '<f4')])

这看起来和你想要的不一样,但是它是一个有效的结构化数组,你的不是。通过字段名访问可以达到你的目的:

In [47]: arr['name']
Out[47]: array(['a', 'b', 'c'], dtype='<U10')

b值已被复制,不能制作"不规则"结构数组:

In [48]: arr['b']
Out[48]: array([17.2, 17.2, 17.2], dtype=float32)

另一个答案是创建一个dict,它给出了相同的"键"结果,但是是一个不同的结构,但它可能是您真正想要的。
有一些辅助函数可以从一组数组中创建一个rearray,但是它们的作用是一样的,而且它们(可能)不会直接使用单个元素b
你可以用下面的语句来创建元组列表:

In [53]: from itertools import zip_longest
In [54]: [ijk for ijk in zip_longest(name,val,alt,b)]
Out[54]: [('a', 0.4, 1.1, 17.2), ('b', 0.5, 2.1, None), ('c', 0.6, 3.1, None)]
In [55]: np.array(_, dt)
Out[55]: 
array([('a', 0.4, 1.1, 17.2), ('b', 0.5, 2.1,  nan),
       ('c', 0.6, 3.1,  nan)],
      dtype=[('name', '<U10'), ('val', '<f4'), ('alt', '<f4'), ('b', '<f4')])

虽然b填充None/nan可能不是您想要的。
你可以把数组组合成一个对象dtype数组,但是元素不能通过名称访问。这需要一个dict

In [64]: barr = np.array([name, val, alt, b], dtype=object)
In [65]: barr
Out[65]: 
array([array(['a', 'b', 'c'], dtype='<U1'), array([0.4, 0.5, 0.6]),
       array([1.1, 2.1, 3.1]), array([17.2])], dtype=object)
disbfnqx

disbfnqx2#

下面的解决方案生成的输出与您所说的所需内容非常匹配(但它不是NumPy记录数组):

import numpy as np

name = np.array(['a', 'b', 'c'])
val = np.array([0.4, 0.5, 0.6])
alt = np.array([1.1, 2.1, 3.1])
b = np.array([17.2])

arr = {}
for var in ['name', 'val', 'alt', 'b']:
    arr[var] = eval(var)

print(arr["name"])

这将打印['a' 'b' 'c']。注意,这里的arr是一个简单的字典。
使用NumPy的numpy.recarray的另一个答案如下:

import numpy as np

# initialization
name = np.array(['a', 'b', 'c'])
val = np.array([0.4, 0.5, 0.6])
alt = np.array([1.1, 2.1, 3.1])
b = np.array([17.2])

# processing
b = np.array([b[0]] * len(name))  # make b longer
fields = ['name', 'val', 'alt', 'b']
dt = np.dtype([('name', '<U12')] + list((colname, 'f8') for colname in fields[1:]))
arr = np.array(list(zip(name, val, alt, b)), dt)

print(arr["name"])  # output: ['a' 'b' 'c']

这里,arr的计算结果如下:

array([('a', 0.4, 1.1, 17.2), ('b', 0.5, 2.1, 17.2),
       ('c', 0.6, 3.1, 17.2)],
      dtype=[('name', '<U12'), ('val', '<f8'), ('alt', '<f8'), ('b', '<f8')])

相关问题