4

在 NumPy 文档和其他 StackOverflow 问题中,提到了嵌套的 NumPy 结构化标量。在我所看到的任何地方,他们似乎都将嵌套结构化标量描述为包含另一个标量(显然)的标量,但内部标量始终是另一个 dtype。我想做的是能够拥有一个 NumPy dtype,它具有作为它的字段之一,它是自己的 dtype。

一个简单的例子是表示树节点的 dtype,它将存储一些值(如整数)和另一个表示它的父节点的树节点。

似乎这应该使用 numpy.void 来完成,但我无法使用如下的 dtype 来完成:

node_dtype = np.dtype([("parent", np.void), ("info", np.uint8)])
4

3 回答 3

2

np.void

我想你认为它np.void会起作用,因为type结构化数组记录是void

In [32]: node_dtype = np.dtype([("parent", np.void), ("info", np.uint8)])
In [33]: np.zeros(3, node_dtype)
Out[33]: 
array([(b'', 0), (b'', 0), (b'', 0)],
      dtype=[('parent', 'V'), ('info', 'u1')])
In [34]: type(_[0])
Out[34]: numpy.void

但请注意

In [35]: __['parent']
Out[35]: array([b'', b'', b''], dtype='|V0')

该字段占用 0 个字节。

In [36]: np.zeros(3, np.void)
Out[36]: array([b'', b'', b''], dtype='|V0')
In [37]: np.zeros(3, np.void(0))
Out[37]: array([b'', b'', b''], dtype='|V0')
In [38]: np.zeros(3, np.void(5))
Out[38]: 
array([b'\x00\x00\x00\x00\x00', b'\x00\x00\x00\x00\x00',
       b'\x00\x00\x00\x00\x00'], dtype='|V5')
In [39]: _[0] = b'12345'

np.void通常需要一个参数,一个指定长度的整数。

虽然可以嵌套 dtypes,但结果必须仍然有一个 known itemsize

In [57]: dt0 = np.dtype('i,f')
In [58]: dt1 = np.dtype([('f0','U3'), ('nested',dt0)])
In [59]: dt1
Out[59]: dtype([('f0', '<U3'), ('nested', [('f0', '<i4'), ('f1', '<f4')])])
In [60]: dt1.itemsize
Out[60]: 20

结果数组将有一个已知大小的数据缓冲区,足以容纳字节arr.size项。arr.itemsize

对象数据类型

object您可以使用dtype 字段构造结构化数组

In [61]: arr = np.empty(3, 'O,i')
In [62]: arr
Out[62]: 
array([(None, 0), (None, 0), (None, 0)],
      dtype=[('f0', 'O'), ('f1', '<i4')])
In [63]: arr[1]['f0']=arr[0]
In [64]: arr[2]['f0']=arr[1]
In [65]: arr
Out[65]: 
array([(None, 0), ((None, 0), 0), (((None, 0), 0), 0)],
      dtype=[('f0', 'O'), ('f1', '<i4')])
In [66]: arr[0]['f1']=100
In [67]: arr
Out[67]: 
array([(None, 100), ((None, 100),   0), (((None, 100), 0),   0)],
      dtype=[('f0', 'O'), ('f1', '<i4')])
In [68]: arr[1]['f1']=200
In [69]: arr[2]['f1']=300
In [70]: arr
Out[70]: 
array([(None, 100), ((None, 100), 200), (((None, 100), 200), 300)],
      dtype=[('f0', 'O'), ('f1', '<i4')])

我不知道这是否会是一个特别有用的结构。一份清单可能一样好

In [71]: arr.tolist()
Out[71]: [(None, 100), ((None, 100), 200), (((None, 100), 200), 300)]
于 2018-05-12T16:59:20.773 回答
1

为我尝试这个崩溃的 numpy:

>>> import numpy as np
>>>
# normal compound dtype, no prob
>>> L = [('f1', int), ('f2', float), ('f3', 'U4')]
>>> np.dtype(L)
dtype([('f1', '<i8'), ('f2', '<f8'), ('f3', '<U4')])
>>> 
# dtype containing itself
>>> L.append(('f4', L))
>>> L
[('f1', <class 'int'>), ('f2', <class 'float'>), ('f3', 'U4'), ('f4', [...])]
>>> np.dtype(L)
Speicherzugriffsfehler (Speicherabzug geschrieben)
# and that is German for segfault (core dumped)

考虑到解释这个结构的概念问题,更不用说自动为它设计一个内存布局,我并不惊讶它不起作用,但显然它不应该崩溃。

于 2018-05-12T11:56:55.760 回答
1

我忍不住玩了@hpaulj 非常简洁的解决方案。

有一件事情让我很伤心,我觉得知道这件事很有用。

它不起作用——或者至少不起作用——批量:

>>> import numpy as np
>>> 
>>> arr = np.empty(4, 'O,i')
>>> arr['f1'] = np.arange(4)
>>> 
# assign one by one:
# ------------------
>>> for i in range(4): arr[i]['f0'] = arr[(i+1) % 4]
... 
# inddividual elements link up nicely:
>>> arr[0]['f0']['f0'] is arr[1]['f0']
True
>>> print([(a['f1'], a['f0']['f1'], a['f0']['f0']['f1']) for a in arr])
[(0, 1, 2), (1, 2, 3), (2, 3, 0), (3, 0, 1)]
# but don't try it in bulk:
>>> print(arr['f1'], arr['f0']['f1'])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: only integers, slices (`:`), ellipsis (`...`), numpy.newaxis (`None`) and integer or boolean arrays are valid indices
>>> 
>>> arr = np.empty(4, 'O,i')
>>> arr['f1'] = np.arange(4)
>>> 
# assign in bulk:
# ---------------
>>> arr['f0'][[3,0,1,2]] = arr
>>> 
# no linking up:
>>> arr[0]['f0']['f0'] is arr[1]['f0']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: tuple indices must be integers or slices, not str
>>> print([(a['f1'], a['f0']['f1'], a['f0']['f0']['f1']) for a in arr])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 1, in <listcomp>
TypeError: tuple indices must be integers or slices, not str
于 2018-05-13T00:12:39.617 回答