2014-10-16 6 views
1

У меня есть два массива.Индексирование 2d массива с 3d-массивом в numpy

"a", массив 2d numpy.

import numpy.random as npr 

a = array([[5,6,7,8,9],[10,11,12,14,15]]) 
array([[ 5, 6, 7, 8, 9], 
     [10, 11, 12, 14, 15]]) 

«IDX», 3d-NumPy массив, составляющий три варианта индекса, которые я хочу использовать для индекса «а».

idx = npr.randint(5, size=(nsamp,shape(a)[0], shape(a)[1])) 
array([[[1, 2, 1, 3, 4], 
     [2, 0, 2, 0, 1]], 

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

     [[2, 1, 0, 1, 4], 
     [1, 1, 0, 1, 0]]]) 

Теперь я хочу, чтобы индекс «а» три раза с индексами в «IDX», чтобы получить объект следующим образом:

array([[[6, 7, 6, 8, 9], 
     [12, 10, 12, 10, 11]], 

     [[5, 5, 8, 7, 5], 
     [11, 14, 12, 10, 14]], 

     [[7, 6, 5, 6, 9], 
     [11, 11, 10, 11, 10]]]) 

Наивный «а [IDX]» не работает. Любые идеи о том, как это сделать? (Я использую Python 3.4 и Numpy 1.9)

+0

Surly это было объяснено много раз. Вы должны проиндексировать индексирование индекса во второе измерение, поэтому это будет нечто вроде 'a [indx, [[[0], [1]]]]' ... – seberg

ответ

3

Вы можете использовать choose, чтобы сделать выбор из a:

>>> np.choose(idx, a.T[:,:,np.newaxis]) 
array([[[ 6, 7, 6, 8, 9], 
     [12, 10, 12, 10, 11]], 

     [[ 5, 5, 8, 7, 5], 
     [11, 14, 12, 10, 14]], 

     [[ 7, 6, 5, 6, 9], 
     [11, 11, 10, 11, 10]]]) 

Как вы можете видеть, a должен быть преобразован из массива с формой (2, 5) в массив с формой (5, 2, 1). Это по существу так, что он доступен для вещания с idx, который имеет форму (3, 2, 5).

(я узнал этот метод от @ immerrr Ответит здесь: https://stackoverflow.com/a/26225395/3923281)

+0

Спасибо! Отлично работает – roschu

+1

В подтверждение того, что 'выбрать' сложно, мне потребовалось некоторое время, чтобы понять, что происходит :) Говоря о вещании, я не думаю, что' (5, 2, 1) 'транслируется с' (3, 2, 5). Он работает, потому что 'select'" отслаивается "от первой оси, используя значения в индексаторе. Таким образом, заданные 'x = aT [:,:, np.newaxis]', 'idx' должны быть широковещательными с помощью' x [0] ', что и есть, потому что' x [0] .shape == (2, 1) '. – immerrr

+1

Спасибо @immerrr - снова посмотрев на это, я согласен, что мое объяснение 'select' немного неточно. Я затачиваю его, когда у меня будет шанс в ближайшие пару дней. –

0

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

import numpy 

a = numpy.array([[5,6,7,8,9],[10,11,12,14,15]]) 

idx = numpy.random.randint(5, size=(3, a.shape[0], a.shape[1])) 

print a.take(idx) 
+0

Благодарим за помощь! – roschu

+3

'take' теряет структуру' a'. Если idx - все нули, 'take' будет создавать массив, полный' 5', тогда как он должен быть '[[5 ...], [10 ...], [5 ...], [10 ... ], [5 ...], [10 ...]] ' – immerrr