Путаница с индексами в массивах numpy - PullRequest
15 голосов
/ 27 января 2011

Я действительно смущен логикой индекса массивов с несколькими измерениями. Вот пример:

import numpy as np
A = np.arange(18).reshape(3,2,3)
[[[ 0,  1,  2],
  [ 3,  4,  5]],

 [[ 6,  7,  8],
  [ 9, 10, 11]],

 [[12, 13, 14],
  [15, 16, 17]]])

это дает мне массив формы (3,2,3), вызывайте их (x, y, z) для аргумента Теперь я хочу массив B с элементами из A, соответствующими x = 0,2, y = 0,1 и z = 1,2. Как

array([[[ 1,  2],
        [4,  5]],

       [[13, 14],
        [16, 17]]])

Наивно думал, что

B=A[[0,2],[0,1],[1,2]]

сделает работу. Но это дает

array([  2, 104]) 

и не работает.

A[[0,2],:,:][:,:,[1,2]]

делает работу. Но мне все еще интересно, что не так с моей первой попыткой. И какой лучший способ сделать то, что я хочу сделать?

Ответы [ 3 ]

17 голосов
/ 27 января 2011

Существует два типа индексации в NumPy basic и advanced .Базовое индексирование использует кортежи срезов для индексации и не копирует массив, а скорее создает представление с откорректированным strides.В отличие от расширенного индексирования также используются списки или массивы индексов и копируется массив.

Ваша первая попытка

B = A[[0, 2], [0, 1], [1, 2]]

использует расширенное индексирование.При расширенном индексировании все списки индексов сначала транслируются в одну и ту же форму, и эта форма используется для выходного массива.В этом случае они уже имеют одинаковой формы, поэтому трансляция ничего не делает.Выходной массив также будет иметь эту форму двух записей.Первая запись выходного массива получается с использованием всех первых индексов трех списков, а вторая - с использованием всех вторых индексов:

B = numpy.array([A[0, 0, 1], A[2, 1, 2]])

Ваш второй подход

B = A[[0,2],:,:][:,:,[1,2]]

делаетработать, но это неэффективно.Он использует расширенную индексацию дважды, поэтому ваши данные будут скопированы дважды.

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

A[np.ix_([0,2],[0,1],[1,2])]

, как указано nikow.Это скопирует данные только один раз.

В вашем примере вы можете уйти, вообще не копируя данные, используя только базовую индексацию:

B = A[::2, :, 1:2]
7 голосов
/ 27 января 2011

Я рекомендую следующий расширенный учебник, который объясняет различные методы индексации: NumPy MedKit

Как только вы поймете мощные способы индексирования массивов (и как они могут быть объединены), это будет иметь смысл. Если ваша первая попытка была действительной, то это вступило бы в противоречие с некоторыми другими методами индексации (сокращение ваших возможностей в других случаях).

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

 A[[0,2],:,1:]

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

A[np.ix_([0,2],[0,1],[1,2])]

, что удобно в более общих случаях, когда последние индексы не являются непрерывными. np.ix_ просто создает три индексных массива.

Как указал Свен в своем ответе, в этом конкретном случае есть более эффективный способ (использование представления вместо скопированной версии).

Редактировать: Как указал Свен, мой ответ содержал некоторые ошибки, которые я удалил. Я все еще думаю, что его ответ лучше, но, к сожалению, я не могу сейчас удалить свой.

0 голосов
/ 01 июля 2014
A[(0,2),:,1:]

Если вы хотели

array([[[ 1,  2],
        [ 4,  5]],

       [[13, 14],
        [16, 17]]])

A [индексы, которые вы хотите, строки, которые вы хотите, столбцы, которые вы хотите]

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...