Индексировать трехмерный массив с помощью двумерного массива - PullRequest
0 голосов
/ 08 марта 2019

Я пытаюсь манипулировать индексом и исходным массивом так, чтобы:

result [i] [j] [k] = source [i] [indices [i] [j] [k]]

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

Пример функциональности:

source = [[0.0  0.1  0.2  0.3]
          [1.0  1.1  1.2  1.3]
          [2.0  2.1  2.2  2.3]]

indices = [[[3 1 0 1]
            [3 0 0 3]]

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

           [[1 1 0 1]
            [0 1 2 2]]]

# result[i][j][k] = source[i][indices[i][j][k]]

result = [[[0.3  0.1  0.0  0.1]
           [0.3  0.0  0.0  0.3]]

          [[1.0  1.1  1.0  1.2]
           [1.3  1.2  1.1  1.1]]

          [[2.1  2.1  2.0  2.1]
           [2.0  2.1  2.2  2.2]]]

1 Ответ

0 голосов
/ 08 марта 2019

Решение с использованием расширенного индексирования Integer:

Дано:

source = [[0.0,  0.1,  0.2,  0.3],
          [1.0,  1.1,  1.2,  1.3],
          [2.0,  2.1,  2.2,  2.3]]

indices = [[[3, 1, 0, 1],
           [3, 0, 0, 3]],
          [[0, 1, 0, 2],
          [3, 2, 1, 1]],
          [[1, 1, 0, 1],
          [0, 1, 2, 2]]]

Используйте это:

import numpy as np
nd_source = np.array(source)

source_rows = len(source)      # == 3, in above example
source_cols = len(source[0])   # == 4, in above example

row_indices = np.arange(source_rows).reshape(-1,1,1)
result = nd_source [row_indices, indices]

Результат:

print (result)
[[[0.3 0.1 0.  0.1]
  [0.3 0.  0.  0.3]]

 [[1.  1.1 1.  1.2]
  [1.3 1.2 1.1 1.1]]

 [[2.1 2.1 2.  2.1]
  [2.  2.1 2.2 2.2]]]

Пояснение:

Для использования Integer Advanced Indexing применяются следующие ключевые правила:

  1. Мы должны предоставить индексные массивы, состоящие из целочисленных индексов.
  2. Мы должны предоставить столько индексных массивов, сколько имеется измерений в исходном массиве.
  3. Форма этих индексных массивов должна быть одинаковой или, по крайней мере, все они должны быть транслируемыми в одну конечную форму.

Как работает Integer Advanced Indexing:

Учитывая, что исходный массив имеет n измерения, и поэтому мы предоставили n массивы целочисленных индексов:

  1. Все эти индексные массивы, если они не будут иметь одинаковую однородную форму, будут транслироваться в единой однородной форме.
  2. Чтобы получить доступ к любому элементу в исходном массиве, нам, очевидно, нужен набор из n индексов. Поэтому, чтобы сгенерировать массив результатов из исходного массива, нам нужно несколько n-кортежей, по одному n-кортежу для каждой позиции элемента массива конечных результатов. Для каждой позиции элемента результирующего массива n-кортеж индексов будет построен из соответствующих позиций элементов в широковещательных индексных массивах. (Помните, что результирующий массив имеет точно такую ​​же форму, что и переданные индексные массивы, как уже упоминалось выше).
  3. Таким образом, путем обхода индексных массивов в тандеме , мы получаем все n-кортежи, которые нам нужны для генерации результирующего массива, в той же форме, что и широковещательные индексные массивы.

Применение этого объяснения к приведенному выше примеру:

  1. Наш исходный массив - nd_source = np.array(source), то есть 2d.
  2. Наша конечная форма результата (3,2,4).

  3. Поэтому нам необходимо предоставить индексные массивы 2, и эти индексные массивы должны либо иметь конечную форму результата (3,2,4), либо передаваться в формате (3,2,4).

  4. Наш первый индексный массив - row_indices = np.arange(source_rows).reshape(-1,1,1). (source_rows - это число строк в источнике, которое в данном примере равно 3). Этот индексный массив имеет форму (3,1,1) и фактически выглядит как [[[0]],[[1]],[[2]]]. Это может быть передано в конечную форму результата (3,2,4), а транслируемый массив выглядит как [[[0,0,0,0],[0,0,0,0]],[[1,1,1,1],[1,1,1,1]],[[2,2,2,2],[2,2,2,2]]].

  5. Наш второй индексный массив - indices. Хотя это не массив, а всего лишь список списков, numpy достаточно гибок, чтобы автоматически преобразовывать его в соответствующий ndarray, когда мы передаем его в качестве массива индекса отправки. Обратите внимание, что этот массив уже имеет конечную желаемую форму результата (3,2,4) даже без какой-либо широковещательной передачи.

  6. Обход этих двух индексных массивов в тандеме (один широковещательный массив, а другой как есть), numpy генерирует все 2 кортежа, необходимые для доступа к нашему исходному 2d массиву nd_source, и сформировать окончательный результат в форме (3,2,4).

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