Структурирование массивов NumPy / np 8

В предыдущих примерах вы видели только одно- или двухмерные массивы. Но NumPy позволяет создавать массивы, которые будут более сложными не только в плане размера, но и по своей структуре. Они называются структурированными массивами. В них вместо отдельных элементов содержатся structs или записи.

Например, можно создать простой массив, состоящий из structs в качестве элементов. Благодаря параметру dtype можно определить условия, которые будут представлять элементы struct, а также тип данных и порядок.

byteb1
inti1, i2, i4, i8
floatf2, f4, f8
complexc8, c16
stringa<n>

Например, если необходимо определить struct, содержащий целое число, строку длиной 6 символов и булево значение, потребуется обозначить три типа данных в dtype в нужном порядке.

Примечание: результат dtype и другие атрибуты формата могут отличаться на разных операционных системах и дистрибутивах Python.

>>> structured = np.array([(1, 'First', 0.5, 1+2j),(2, 'Second', 1.3, 2-2j), (3, 'Third', 0.8, 1+3j)], dtype=('i2, a6, f4, c8'))
>>> structured
array([(1, b'First', 0.5, 1+2.j),
       (2, b'Second', 1.3, 2.-2.j),
       (3, b'Third', 0.8, 1.+3.j)],
      dtype=[('f0', '<i2'), ('f1', 'S6'), ('f2', '<f4'), ('f3', '<c8')])

Тип данных можно указать и явно с помощью int8, uint8, float16, complex16 и так далее.

>>> structured = np.array([(1, 'First', 0.5, 1+2j),(2, 'Second', 1.3,2-2j), (3, 'Third', 0.8, 1+3j)],dtype=('int16, a6, float32, complex64'))
>>> structured
array([(1, b'First', 0.5, 1.+2.j),
       (2, b'Second', 1.3, 2.-2.j),
       (3, b'Third', 0.8, 1.+3.j)],
      dtype=[('f0', '<i2'), ('f1', 'S6'), ('f2', '<f4'), ('f3', '<c8')])

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

Указывая соответствующий индекс, вы получаете нужную строку, включающую struct.

>>> structured[1]
(2, 'bSecond', 1.3, 2.-2.j)

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

>>> structured['f1']
array([b'First', b'Second', b'Third'],
      dtype='|S6')

Имена присваиваются автоматически с символом f (он значит field (поле)) и увеличивающимся целым числом, обозначающим позицию в последовательности. Но было бы куда удобнее иметь более логичные имена. Это можно сделать в момент создания массива:

>>> structured = np.array([(1,'First',0.5,1+2j),
    (2,'Second',1.3,2-2j), (3,'Third',0.8,1+3j)],
    dtype=[('id','i2'),('position','a6'),('value','f4'),('complex','c8')])
>>> structured
array([(1, b'First', 0.5, 1.+2.j),
       (2, b'Second', 1.3, 2.-2.j),
       (3, b'Third', 0.8, 1.+3.j)],
      dtype=[('id', '<i2'), ('position', 'S6'), ('value', '<f4'), ('complex', '<c8')])

Или позже, переопределив кортежи имен, присвоенных атрибуту dtype структурированного массива:

>>> structured.dtype.names = ('id','order','value','complex')

Теперь можно использовать понятные имена для разных типов полей:

>>> structured['order'] 
array([b'First', b'Second', b'Third'], dtype='|S6')