Преобразование массива numpy в структурированный массив

#python #arrays #python-3.x #numpy #structured-array

#python #массивы #python-3.x #numpy #структурированный массив

Вопрос:

Допустим, у меня есть следующий массив:

 arr = np.array([[1,2], [3,4]], dtype='u1')
  

и я хочу преобразовать его в структурированный массив, подобный этому:

 strarr = np.array([(1,2), (3,4)], dtype=[('a', 'u1'), ('b', 'u1')])
  

Если я просто попробую

 arr.astype([('a', 'u1'), ('b', 'u1')])
  

он возвращает

 >>> array([[(1, 1), (2, 2)],
       [(3, 3), (4, 4)]], dtype=[('a', 'u1'), ('b', 'u1')])
  

Как я могу преобразовать массив так, чтобы он использовал все элементы строки для заполнения полей (при условии, что числа совпадают) вместо дублирования каждого элемента?

Ответ №1:

Для этого существуют специальные вспомогательные функции:

 >>> from numpy.lib.recfunctions import unstructured_to_structured
  

Итак,

 >>> import numpy as np
>>> arr = np.array([[1,2], [3,4]], dtype='u1')
>>> unstructured_to_structured(arr, dtype=np.dtype([('a', 'u1'), ('b', 'u1')]))
array([(1, 2), (3, 4)], dtype=[('a', 'u1'), ('b', 'u1')])
  

Вы также можете создать представление:

 >>> arr.ravel().view(dtype=np.dtype([('a', 'u1'), ('b', 'u1')]))
array([(1, 2), (3, 4)], dtype=[('a', 'u1'), ('b', 'u1')])
  

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

Ответ №2:

Предполагается, что данные для структурированного массива представляют собой список кортежей:

 In [5]: arr = np.array([[1,2], [3,4]], dtype='u1')
In [6]: alist = [tuple(i) for i in arr]
In [7]: alist
Out[7]: [(1, 2), (3, 4)]
In [9]: np.array(alist, dtype=[('a', 'u1'), ('b', 'u1')])
Out[9]: array([(1, 2), (3, 4)], dtype=[('a', 'u1'), ('b', 'u1')])
  

Обратите внимание, что входные данные отражают отображение выходных данных.

В этом случае также возможно представление (базовые данные не изменяются):

 In [10]: arr.view(dtype=[('a', 'u1'), ('b', 'u1')])
Out[10]: 
array([[(1, 2)],
       [(3, 4)]], dtype=[('a', 'u1'), ('b', 'u1')])
In [11]: _.ravel()      # but needs a shape correction
Out[11]: array([(1, 2), (3, 4)], dtype=[('a', 'u1'), ('b', 'u1')])