Полностью вложенные структурированные скаляры NumPy - PullRequest
0 голосов
/ 12 мая 2018

В документах NumPy и других вопросах StackOverflow упоминаются вложенные структурированные скаляры NumPy.Везде, где я видел это, они, кажется, описывают вложенный структурированный скаляр как скаляр, который содержит другой скаляр (очевидно), но внутренний скаляр всегда имеет другой тип d.То, что я хотел бы сделать, это иметь возможность иметь dum типа NumPy, который имеет в качестве одного из своих полей собственный dtype.

Простым примером этого будет dtype для представления узла дерева, где он будет хранить некоторое значение (например, целое число) и другой узел дерева, представляющий его родителя.

Кажется, это должно быть сделано с помощью numpy.void, но я не смог сделать это с помощью dtype, как показано ниже:

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

Ответы [ 3 ]

0 голосов
/ 12 мая 2018

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,результат должен все еще иметь известный 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

Вы можете создать структурированный массив с 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)]
0 голосов
/ 13 мая 2018

Я не мог не поиграть с очень аккуратным решением @ 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
0 голосов
/ 12 мая 2018

Попытка этого разбитого 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)

Учитывая концептуальные проблемы в интерпретации этой структуры, не говоря уже о том, чтобы автоматически придумывать схему памяти для нее, я не удивлен, что она не работает, хотя, очевидно, она не должна падать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...