Как вернуть массив numpy со значениями, полученными из исходного массива максимальных значений различных массивов одинаковой формы - PullRequest
0 голосов
/ 17 февраля 2020

У меня проблемы с написанием этого вопроса, поэтому, может быть, лучше просто проиллюстрировать. Короче говоря, у меня есть два набора из трех массивов одинаковой формы. Используя первый набор, для каждого элемента я хотел бы найти, какой массив имеет максимальное значение в этой позиции, и вернуть значение из второго набора. Несмотря на то, что в примере каждый массив 3 x 3 имеет форму отдельного объекта, они также могут быть легко (3, 3, 3).

Набор для поиска максимального значения:

import numpy as np
A1 = np.array([[13, 16, 17], [32, 16, 11], [46, 30, 14]], dtype='uint8')
B1 = np.array([[31, 46, 41], [19, 29, 45], [36, 30, 46]], dtype='uint8')
C1 = np.array([[36, 35, 26], [19, 40, 24], [5, 20, 46]], dtype='uint8') 

Набор для использования в качестве возвращаемого значения:

A2 = np.array([[1, 1, 4], [3, 1, 4], [1, 3, 2]], dtype='uint8')
B2 = np.array([[2, 3, 1], [4, 4, 2], [1, 1, 3]], dtype='uint8')
C2 = np.array([[3, 2, 3], [1, 2, 3], [2, 4, 4]], dtype='uint8')

Если это двухэтапное решение, первое вернет массив, подобный:

mx1
array([['C', 'B', 'B'],
       ['A', 'C', 'B'],
       ['A', 'A', 'B']], dtype='<U1')

Тогда желаемый результат будет:

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

Обратите внимание, что в случае значения ie для максимального значения (последние два элемента) значение из первого обнаруженного массива является принятым значением.

Я думал, что это будет простая задача с использованием некоторых типов np.max и np.where magi c, но я не могу правильно решить эту проблему.

1 Ответ

0 голосов
/ 17 февраля 2020
import numpy as np

A1 = np.array([[13, 16, 17], [32, 16, 11], [46, 30, 14]], dtype='uint8')
B1 = np.array([[31, 46, 41], [19, 29, 45], [36, 30, 46]], dtype='uint8')
C1 = np.array([[36, 35, 26], [19, 40, 24], [5, 20, 46]], dtype='uint8') 

A2 = np.array([[1, 1, 4], [3, 1, 4], [1, 3, 2]], dtype='uint8')
B2 = np.array([[2, 3, 1], [4, 4, 2], [1, 1, 3]], dtype='uint8')
C2 = np.array([[3, 2, 3], [1, 2, 3], [2, 4, 4]], dtype='uint8')

D=np.array([A1,B1,C1])
F=np.array([A2,B2,C2])

amax=np.argmax(D,axis=0)
# array( [[2, 1, 1],
#         [0, 2, 1],
#         [0, 0, 1]] )

#There should be a better way to do this.
idx=np.array([ (y,x[0],x[1]) for x,y in np.ndenumerate(amax)])
# array([[2, 0, 0],
#        [1, 0, 1],
#        [1, 0, 2],
#        [0, 1, 0],
#        [2, 1, 1],
#        [1, 1, 2],
#        [0, 2, 0],
#        [0, 2, 1],
#        [1, 2, 2]] )

flat_answer=F[(idx[:,0],idx[:,1 ],idx[:,2])]
# array( [3, 3, 1, 3, 2, 2, 1, 3, 3] )

answer = np.reshape(flat_answer,np.shape(amax)))
# array( [[3, 3, 1],
#         [3, 2, 2],
#         [1, 3, 3]] )

Хитрость в том, чтобы создать трехмерный массив в форме A1, A2, A3. затем используйте argmax() для получения правильного индекса.

Я уверен, что существует "умный" numpy способ индексации для уменьшения размера F на основе результата argmax() , Но моя работа заключалась в том, чтобы использовать ndenumerate() и составлять списки для построения уплощенного массива с правильными значениями с помощью многомерного индексирования , а затем снова изменить его на (3,3).


Правка, лучшее объяснение:

ndenumerate() возвращает генератор кортежей с координатой и значением для каждой позиции в массиве, ie. для массива

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

Он вернет кортежи:

( ( 0, 0 ), 1 )
( ( 0, 1 ), 2 )
( ( 1, 0 ), 3 )
( ( 1, 1 ), 4 )

Но значения amax уже являются координатами в 3-м измерении D и F, поэтому мы объединяем выходные данные ndenumerate(amax), чтобы построить координаты F

ndenumerate        coordinate
((x1, x2 ), v ) -> (v, x1, x2)

Последние 2 строки кода, используйте координаты для проецирования ответов из массива 3x3x3 F в 3x3 answer с использованием numpy правил индексирования.

Это эквивалентно выполнению следующего отображения:

clearer_answer = np.zeros(np.shape(amax))
for x,y in np.ndenumerate(amax):
    clearer_answer[x] = F[(y,x[0],x[1])]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...