Python structured array to array

Structured arrays

Здесь x — одномерный массив длины два, тип данных которого представляет собой структуру с тремя полями: 1. Строка длиной 10 или меньше с именем «имя», 2. 32-битное целое число с именем «возраст» и 3. a 32-битное число с плавающей запятой с именем «вес».

Если вы индексируете x в позиции 1, вы получите структуру:

Вы можете получать доступ и изменять отдельные поля структурированного массива,индексируя их по имени поля:

>>> x['age'] array([9, 3], dtype=int32) >>> x['age'] = 5 >>> x array([('Rex', 5, 81.), ('Fido', 5, 27.)], dtype=[('name', '), ('age', '), ('weight', ')])

Структурированные типы данных разработаны таким образом,чтобы имитировать «структуры» в языке C,и имеют схожую структуру памяти.Они предназначены для взаимодействия с кодом на языке Си и для низкоуровневого манипулирования структурированными буферами,например,для интерпретации двоичных блоков.Для этих целей они поддерживают такие специализированные возможности,как подмассивы,вложенные типы данных и объединения,а также позволяют контролировать расположение структуры в памяти.

Пользователи,желающие манипулировать табличными данными,например,хранящимися в файлах csv,могут найти другие проекты pydata,такие как xarray,pandas или DataArray.Они предоставляют высокоуровневый интерфейс для анализа табличных данных и лучше оптимизированы для этого.Например,C-struct-подобная компоновка памяти структурированных массивов в numpy может привести к плохому поведению кэша в сравнении.

Structured Datatypes

Структурированный тип данных можно рассматривать как последовательность байтов определенной длины (размер элемента структуры), которая интерпретируется как набор полей. Каждое поле имеет имя, тип данных и смещение в байтах внутри структуры. Тип данных поля может быть любым типом данных numpy, включая другие структурированные типы данных, а также может быть типом данных подмассива, который ведет себя как ndarray указанной формы. Смещения полей произвольны, и поля могут даже перекрываться. Эти смещения обычно автоматически определяются numpy, но также могут быть указаны.

Создание структурированных типов данных

Структурированные типы данных могут быть созданы с помощью функции numpy.dtype . Есть 4 альтернативные формы спецификации, которые различаются по гибкости и лаконичности. Они дополнительно задокументированы на справочной странице по объектам типа данных , и в итоге они:

    Список кортежей,по одному кортежу на поле Каждый кортеж имеет форму (fieldname, datatype, shape) где форма не является обязательной. fieldname — это строка (или кортеж, если используются заголовки , см. Заголовки полей ниже), datatype может быть любой объект, конвертируемый в тип данных, а shape — кортеж целых чисел, определяющий форму подмассива.

>>> np.dtype([('x', 'f4'), ('y', np.float32), ('z', 'f4', (2, 2))]) dtype([('x', '), ('y', '), ('z', ', (2, 2))])

Если fieldname является пустой строкой » , полю будет присвоено имя по умолчанию в форме f# , где # — это целочисленный индекс поля, отсчитываемый от 0 слева:

>>> np.dtype([('x', 'f4'), ('', 'i4'), ('z', 'i8')]) dtype([('x', '), ('f1', '), ('z', ')])
>>> np.dtype('i8, f4, S3') dtype([('f0', '), ('f1', '), ('f2', 'S3')]) >>> np.dtype('3int8, float32, (2, 3)float64') dtype([('f0', 'i1', (3,)), ('f1', '), ('f2', ', (2, 3))])
>>> np.dtype('names': ['col1', 'col2'], 'formats': ['i4', 'f4']>) dtype([('col1', '), ('col2', ')]) >>> np.dtype('names': ['col1', 'col2'], . 'formats': ['i4', 'f4'], . 'offsets': [0, 4], . 'itemsize': 12>) dtype('names': ['col1', 'col2'], 'formats': [', '], 'offsets': [0, 4], 'itemsize': 12>)
>>> np.dtype('col1': ('i1', 0), 'col2': ('f4', 1)>) dtype([('col1', 'i1'), ('col2', ')])

Манипулирование и отображение структурированных типов данных

Список имен полей структурированного типа данных можно найти в names атрибутов объекта DTYPE:

>>> d = np.dtype([('x', 'i8'), ('y', 'f4')]) >>> d.names ('x', 'y')

Имена полей можно изменить, присвоив атрибуту names последовательность строк одинаковой длины.

Объект dtype также имеет атрибут, подобный словарю, fields , ключами которого являются имена полей (и заголовки полей , см. Ниже), а значениями являются кортежи, содержащие dtype и байтовое смещение каждого поля.

>>> d.fields mappingproxy('x': (dtype('int64'), 0), 'y': (dtype('float32'), 8)>)

И names и атрибуты fields будут равны None для неструктурированных массивов. Рекомендуемый способ проверить, структурирован ли dtype, — это if dt.names is not None а не if dt.names , чтобы учесть dtypes с 0 полями.

Строковое представление структурированного типа данных отображается в форме «список кортежей»,если это возможно,иначе numpy возвращается к использованию более общей формы словаря.

Автоматическое смещение и выравнивание байтов

Numpy использует один из двух методов для автоматического определения смещения байтов поля и общего размера элемента структурированного типа данных в зависимости от того, было ли указано align=True в качестве аргумента ключевого слова для numpy.dtype .

По умолчанию ( align=False ) numpy будет упаковывать поля вместе, так что каждое поле начинается с байтового смещения, в котором закончилось предыдущее поле, а поля в памяти являются смежными.

>>> def print_offsets(d): . print("offsets:", [d.fields[name][1] for name in d.names]) . print("itemsize:", d.itemsize) >>> print_offsets(np.dtype('u1, u1, i4, u1, i8, u2')) offsets: [0, 1, 2, 6, 7, 15] itemsize: 17

Если установлено align=True , numpy будет дополнять структуру так же, как многие компиляторы C дополняют C-структуру. В некоторых случаях выровненные структуры могут повысить производительность за счет увеличения размера типа данных. Байты заполнения вставляются между полями таким образом, что смещение каждого поля в байтах будет кратно выравниванию этого поля, которое обычно равно размеру поля в байтах для простых типов данных, см . PyArray_Descr.alignment . Структура также будет иметь завершающие отступы, чтобы ее размер элемента был кратным выравниванию самого большого поля.

>>> print_offsets(np.dtype('u1, u1, i4, u1, i8, u2', align=True)) offsets: [0, 1, 4, 8, 16, 24] itemsize: 32

Обратите внимание,что,хотя почти все современные компиляторы языка C по умолчанию выполняют такую разбивку,разбивка в структурах языка C зависит от реализации языка C,поэтому не гарантируется точное соответствие расположения памяти соответствующей структуре в программе на языке C.Для получения точного соответствия может потребоваться некоторая работа как на стороне numpy,так и на стороне C.

Если смещения были указаны с помощью дополнительного ключа offsets в спецификации dtype на основе словаря, установка align=True проверит, что смещение каждого поля кратно его размеру, а размер элемента кратен наибольшему размеру поля, и вызовет исключение. если не.

Если смещения полей и размер элементов структурированного массива удовлетворяют условиям выравнивания, для массива будет установлен flag ALIGNED .

Удобная функция numpy.lib.recfunctions.repack_fields преобразует выровненный dtype или массив в упакованный и наоборот. Он принимает либо dtype, либо структурированный ndarray в качестве аргумента и возвращает копию с переупакованными полями, с байтами заполнения или без них.

Field Titles

Помимо имен полей, поля могут также иметь связанный заголовок , альтернативное имя, которое иногда используется как дополнительное описание или псевдоним для поля. Заголовок может использоваться для индексации массива, как и имя поля.

Для добавления заголовков при использовании формы list-of-tuples спецификации dtype,имя поля может быть указано как кортеж из двух строк вместо одной строки,которые будут заголовком и именем поля соответственно.Например:

>>> np.dtype([(('my title', 'name'), 'f4')]) dtype([(('my title', 'name'), ')])

При использовании первой формы спецификации на основе словаря заголовки могут быть предоставлены как дополнительный ключ ‘titles’ как описано выше. При использовании второй (нежелательной) спецификации на основе словаря заголовок может быть предоставлен путем предоставления трехэлементного кортежа (datatype, offset, title) вместо обычного двухэлементного кортежа:

>>> np.dtype('name': ('i4', 0, 'my title')>) dtype([(('my title', 'name'), ')])

dtype.fields словарь будет содержать названия в качестве ключей, если используются какие — либо титулы. Фактически это означает, что поле с заголовком будет дважды представлено в словаре полей. Значения кортежа для этих полей также будут иметь третий элемент — заголовок поля. Из — за этого, и потому , что names атрибутов сохраняет порядок полей , а fields атрибута не может, рекомендуется перебирать полей DTYPE с использованием names атрибут DTYPE, который не будет список названий, как:

>>> for name in d.names: . print(d.fields[name][:2]) (dtype('int64'), 0) (dtype('float32'), 8)
NumPy 1.23

Массивы NumPy со структурированным dtype можно также рассматривать как recarray,где доступ к полю осуществляется,если бы оно было атрибутом.

Структурированные типы данных реализованы в numpy, чтобы по умолчанию иметь базовый numpy.void, но можно интерпретировать другое использование (base_dtype, форма спецификации

В качестве дополнительного удобства numpy предоставляет подкласс ndarray, numpy.recarray, который позволяет получить доступ к полям, структурированным по атрибутам, а не только по индексу.

Источник

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

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

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

byte b1
int i1, i2, i4, i8
float f2, f4, f8
complex c8, c16
string a

Например, если необходимо определить 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', '), ('f1', 'S6'), ('f2', '), ('f3', ')]) 

Тип данных можно указать и явно с помощью 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', '), ('f1', 'S6'), ('f2', '), ('f3', ')]) 

В обоих случаях будет одинаковый результат. В массиве имеется последовательность 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', '), ('position', 'S6'), ('value', '), ('complex', ')]) 

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

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

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

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

Источник

Читайте также:  Attach file code in html
Оцените статью