如何获取嵌套 numpy 结构化数组的字段(高级索引)

How to get field of nested numpy structured array (advanced indexing)

我有一个复杂的嵌套结构化数组(通常用作重新数组)。这个例子是简化的,但在实际情况中有多个级别。

c = [('x','f8'),('y','f8')]
A = [('data_string','|S20'),('data_val', c, 2)]
zeros = np.zeros(1, dtype=A)
print(zeros["data_val"]["x"])

我正在尝试索引嵌套数组数据类型的“x”数据类型,但没有 定义前面的命名字段。我希望像 print(zeros[:,"x"]) 这样的东西能让我切分所有顶级数据,但它不起作用。

有没有办法通过访问字段名称对嵌套结构化数组进行精美索引?

语句 zeros['data_val'] 在数组中创建了一个 view,此时它可能已经不连续了。您可以提取 x 的多个值,因为 c 是数组类型,这意味着 x 具有明确定义的步幅和形状。 zeros[:, 'x'] 语句的语义非常不清楚。例如,没有 xdata_string 会怎样?我希望有一个错误;您可能会期待其他东西。

我能看到索引被简化的唯一方法是,如果您直接将 c 扩展为 A,有点像 C 中的匿名结构,只是您不能轻易做到用一个数组。

我不知道显示结果数组是否有助于您形象化嵌套。

In [279]: c = [('x','f8'),('y','f8')]
     ...: A = [('data_string','|S20'),('data_val', c, 2)]
     ...: arr = np.zeros(2, dtype=A)
In [280]: arr
Out[280]: 
array([(b'', [(0., 0.), (0., 0.)]), (b'', [(0., 0.), (0., 0.)])],
      dtype=[('data_string', 'S20'), ('data_val', [('x', '<f8'), ('y', '<f8')], (2,))])

请注意 ()[] 的嵌套如何反映字段的嵌套。

arr.dtype 只能直接访问顶级字段名称:

In [281]: arr.dtype.names
Out[281]: ('data_string', 'data_val')
In [282]: arr['data_val']
Out[282]: 
array([[(0., 0.), (0., 0.)],
       [(0., 0.), (0., 0.)]], dtype=[('x', '<f8'), ('y', '<f8')])

但是访问一个字段后,我们可以查看它的字段:

In [283]: arr['data_val'].dtype.names
Out[283]: ('x', 'y')
In [284]: arr['data_val']['x']
Out[284]: 
array([[0., 0.],
       [0., 0.]])

记录号索引是独立的,可以是通常意义上的多维:

In [285]: arr[1]['data_val']['x'] = [1,2]
In [286]: arr[0]['data_val']['y'] = [3,4]
In [287]: arr
Out[287]: 
array([(b'', [(0., 3.), (0., 4.)]), (b'', [(1., 0.), (2., 0.)])],
      dtype=[('data_string', 'S20'), ('data_val', [('x', '<f8'), ('y', '<f8')], (2,))])

由于 data_val 字段具有 (2,) 形状,我们可以 mix/match 该索引具有 arr 的 (2,) 形状:

In [289]: arr['data_val']['x']
Out[289]: 
array([[0., 0.],
       [1., 2.]])
In [290]: arr['data_val']['x'][[0,1],[0,1]]
Out[290]: array([0., 2.])
In [291]: arr['data_val'][[0,1],[0,1]]
Out[291]: array([(0., 3.), (2., 0.)], dtype=[('x', '<f8'), ('y', '<f8')])

我提到字段索引就像 dict 索引。请注意字段的显示:

In [294]: arr.dtype.fields
Out[294]: 
mappingproxy({'data_string': (dtype('S20'), 0),
              'data_val': (dtype(([('x', '<f8'), ('y', '<f8')], (2,))), 20)})

每条记录存储为一个 52 字节的块:

In [299]: arr.itemsize
Out[299]: 52
In [300]: arr.dtype.str
Out[300]: '|V52'

其中 20 个是 data_string,32 个是 2 个 c 字段

In [303]: arr['data_val'].dtype.str
Out[303]: '|V16'

您可以请求一个字段列表,并获得一种特殊的 view。它的 dtype 显示有点不同

In [306]: arr[['data_val']]
Out[306]: 
array([([(0., 3.), (0., 4.)],), ([(1., 0.), (2., 0.)],)],
      dtype={'names': ['data_val'], 'formats': [([('x', '<f8'), ('y', '<f8')], (2,))], 'offsets': [20], 'itemsize': 52})

In [311]: arr['data_val'][['y']]
Out[311]: 
array([[(3.,), (4.,)],
       [(0.,), (0.,)]],
      dtype={'names': ['y'], 'formats': ['<f8'], 'offsets': [8], 'itemsize': 16})

每个 'data_val' 从 52 字节记录的 20 字节开始。每个 'y' 在其 16 字节记录中开始 8 个字节。