Как мне распаковать массив nupy массив кортежей в ndarray? - PullRequest
1 голос
/ 25 апреля 2019

У меня есть двумерный массив с элементами типа np.void, которые по сути являются кортежами.Есть ли эффективный способ распаковать значения в этих кортежах в 3-е измерение без циклического прохождения каждого элемента массива?

Например, двумерный массив выглядит примерно так:

a = np.array([[(1, 2,  3), (1, 2,  3), (1, 2, 3)],
       [(1, 2,  3), (1, 2, 3), (1, 2, 3)],
       [(1, 2, 3), (1, 2, 3), (1, 2, 3)]],
      dtype=[('B4', '<u2'), ('B3', '<u2'), ('B2', '<u2')])

Где,

a.shape = (3,3)
a[0,0] = (1,2,3)

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

b.shape = (3,3,3)
b[0,0,0] = 1
b[0,0,1] = 2
b[0,0,2] = 3

другими словами,

b[:,:,0] == 
array([[1, 1, 1],
       [1, 1, 1],
       [1, 1, 1]])
b[:,:,1] == 
array([[2, 2, 2],
       [2, 2, 2],
       [2, 2, 2]])
b[:,:,2] == 
array([[3, 3, 3],
       [3, 3, 3],
       [3, 3, 3]])

Я знаю, что должен быть более эффективный способ сделать это, кроме циклического прохождения каждого элемента, но я не очень разбираюсь в работе с элементами np.void.

Спасибо

Чтобы уточнить, a more efficient solution значение по сравнению с чем-то вроде

new_array = np.zeros((a.shape + (3,)))
for i in range(a.shape[0]):
    for j in range(a.shape[-1]):
        new_array[i, j, 0] = a[i, j][0]
        new_array[i, j, 1] = a[i, j][1]
        new_array[i, j, 2] = a[i, j][2]

Ответы [ 2 ]

0 голосов
/ 25 апреля 2019
In [601]: a = np.array([[(1, 2,  3), (1, 2,  3), (1, 2, 3)], 
     ...:        [(1, 2,  3), (1, 2, 3), (1, 2, 3)], 
     ...:        [(1, 2, 3), (1, 2, 3), (1, 2, 3)]], 
     ...:       dtype=[('B4', '<u2'), ('B3', '<u2'), ('B2', '<u2')])                 
In [602]: a.dtype                                                                    
Out[602]: dtype([('B4', '<u2'), ('B3', '<u2'), ('B2', '<u2')])
In [603]: a.shape                                                                    
Out[603]: (3, 3)

Это структурированный массив с составным dtype. Кортежи отображают отдельные элементы массива 2d.

В последних версиях numpy добавлена ​​функция удобного преобразования структурированных массивов в неструктурированные:

In [606]: b=rf.structured_to_unstructured(a)                                         
In [607]: b                                                                          
Out[607]: 
array([[[1, 2, 3],
        [1, 2, 3],
        [1, 2, 3]],

       [[1, 2, 3],
        [1, 2, 3],
        [1, 2, 3]],

       [[1, 2, 3],
        [1, 2, 3],
        [1, 2, 3]]], dtype=uint16)
In [608]: b[:,:,1]                                                                   
Out[608]: 
array([[2, 2, 2],
       [2, 2, 2],
       [2, 2, 2]], dtype=uint16)

a имеет 3 поля. Отдельные поля могут быть доступны по имени:

In [610]: a['B4']                                                                    
Out[610]: 
array([[1, 1, 1],
       [1, 1, 1],
       [1, 1, 1]], dtype=uint16)

Это означает, что вы можете создать трехмерный массив, объединив 3 отдельных поля:

np.stack([a['B4'],a['B3'],a['B2']]) 

Это похоже на ваше последнее решение, но без итерации i,j.


Подход view в другом ответе в этом случае работает, поскольку все поля имеют одинаковые dtype, <u2. Это означает, что одни и те же базовые данные можно просматривать как отдельные элементы <u2 или группы из 3 из них.

rf.structured_to_unstructured работает в более общих случаях, когда view не работает, например, сочетание dtypes (например, с плавающей точкой и целых чисел).

0 голосов
/ 25 апреля 2019

Вы можете просмотреть в качестве стандартного массива numpy, чтобы обеспечить индексацию, к которой вы стремитесь.

b = a.view('(3,)<u2')

array([[[1, 2, 3],
        [1, 2, 3],
        [1, 2, 3]],

       [[1, 2, 3],
        [1, 2, 3],
        [1, 2, 3]],

       [[1, 2, 3],
        [1, 2, 3],
        [1, 2, 3]]], dtype=uint16)

>>> b.shape
(3, 3, 3)
>>> b[:, :, 0]
array([[1, 1, 1],
       [1, 1, 1],
       [1, 1, 1]], dtype=uint16)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...