Структурированный массив numpy, как правильно присвоить тип

Мои попытки создать структурированные массивы терпят неудачу:

Я создаю форму массива (4,5)

sample = np.array([[0.01627555, 1.55885081, 1.99043222, 0.00898849, 1.43987417],
       [0.01875182, 0.97853587, 2.09924081, 0.00474326, 1.31002428],
       [0.01905054, 1.74849054, 1.78033106, 0.01303594, 1.28518933],
       [0.01753927, 1.22486495, 1.88287677, 0.01823483, 1.36472148]])

назначьте dtype для каждого из пяти столбцов:

sample.dtype = [('X', 'f4'), ('Y', 'f4'), ('Z', 'f4'), ('f', 'f4'), ('g', 'f4' )]

я бы ожидал:

sample['X']
> array([0.01627555, 0.01875182, 0.01905054, 0.01753927], dtype=float32)

Однако то, что я делаю, дает

array([[-1.6328180e-12,  1.9988040e+00],
       [ 7.9082486e+13,  2.0124049e+00],
       [ 7.7365790e-24,  1.9725413e+00],
       [ 3.6306835e+36,  1.9853595e+00]], dtype=float32)

Я знаю, как это сделать в пандах и т. д., Но в этом случае мне нужен структурированный массив. Что я делаю не так?

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
0
58
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вам нужно переформатировать массив с помощью np.core.records.array в список кортежей, чтобы преобразовать его в recarray

dtype = [('X', 'f4'), ('Y', 'f4'), ('Z', 'f4'), ('f', 'f4'), ('g', 'f4' )]

arr = np.core.records.array(tuple(sample.T), dtype=dtype)

Выход:

>>> arr  # note the recarray
rec.array([(0.01627555, 1.5588508, 1.9904323, 0.00898849, 1.4398742),
           (0.01875182, 0.9785359, 2.0992408, 0.00474326, 1.3100243),
           (0.01905054, 1.7484906, 1.780331 , 0.01303594, 1.2851893),
           (0.01753927, 1.224865 , 1.8828768, 0.01823483, 1.3647215)],
          dtype=[('X', '<f4'), ('Y', '<f4'), ('Z', '<f4'), ('f', '<f4'), ('g', '<f4')])

>>> arr['X']  # note you still have ndarray
array([0.01627555, 0.01875182, 0.01905054, 0.01753927], dtype=float32)

На главной structured array странице документации представлены recfunctions:

https://numpy.org/doc/stable/user/basics.rec.html#module-numpy.lib.recfunctions

In [2]: import numpy.lib.recfunctions as rf

Определите объект dtype:

In [11]: dt = np.dtype([('X', 'f4'), ('Y', 'f4'), ('Z', 'f4'), ('f', 'f4'), ('g', 'f4' )])                              

rf имеет функцию, предназначенную для выполнения такого преобразования:

In [13]: arr = rf.unstructured_to_structured(sample, dtype=dt)                                                          
In [14]: arr                                                                                                            
Out[14]:                                                                                                                
    array([(0.01627555, 1.5588508, 1.9904323, 0.00898849, 1.4398742),                                                              
    (0.01875182, 0.9785359, 2.0992408, 0.00474326, 1.3100243),                                                              
    (0.01905054, 1.7484906, 1.780331 , 0.01303594, 1.2851893),                                                              
    (0.01753927, 1.224865 , 1.8828768, 0.01823483, 1.3647215)],                                                            
    dtype=[('X', '<f4'), ('Y', '<f4'), ('Z', '<f4'), ('f', '<f4'), ('g', '<f4')])                                     

Вы также можете создать структурированный массив со списком кортежей, который будет очень похож на показанное выше отображение массива.

 In [16]: np.array([tuple(x) for x in sample], dtype=dt)   

В другом ответе используется функция records для создания массива из списка массивов, по одному на поле:

 np.core.records.fromarrays(list(sample.T), dtype=dt)                                                              

Как и многие функции rf, эта функция создает «пустой» массив с нужным dtype и формой и копирует в него значения по имени поля:

In [31]: dt.names                                                                                                       
Out[31]: ('X', 'Y', 'Z', 'f', 'g')                                                                                      
In [32]: res = np.zeros(4, dtype=dt)                                                                                    
In [33]: for i,name in enumerate(dt.names):                                                                                 
    ...:     res[name] = sample[:,i] 

Другие вопросы по теме