Объяснение индексации многомерного массива Python - PullRequest
0 голосов
/ 13 февраля 2019

Может кто-нибудь объяснить мне, что здесь происходит?Я понимаю, что здесь происходит: https://docs.scipy.org/doc/numpy-1.15.0/user/basics.indexing.html#index-arrays,, но не понимаю этот фрагмент кода.

import numpy as np
y = np.zeros((3,3))
y = y.astype(np.int16)
y[1,1] = 1
x = np.ones((3,3))
t = (1-y).astype(np.int16)
print(t)
print(x[t])
x[(1-y).astype(np.int16)] = 0
print(x)

вывод:

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

[[[1. 1. 1.]
  [1. 1. 1.]
  [1. 1. 1.]]

 [[1. 1. 1.]
  [1. 1. 1.]
  [1. 1. 1.]]

 [[1. 1. 1.]
  [1. 1. 1.]
  [1. 1. 1.]]]

[[0. 0. 0.]
 [0. 0. 0.]
 [1. 1. 1.]]

1 Ответ

0 голосов
/ 13 февраля 2019
import numpy as np              # Line 01
y = np.zeros((3,3))             # Line 02
y = y.astype(np.int16)          # Line 03
y[1,1] = 1                      # Line 04
x = np.ones((3,3))              # Line 05
t = (1-y).astype(np.int16)      # Line 06
print(t)                        # Line 07
print(x[t])                     # Line 08
x[(1-y).astype(np.int16)] = 0   # Line 09
print(x)                        # Line 10

Строка 02:

Создает двумерный 3 x 3-мерный массив нулей.y - это имя, которое указывает на этот ndarray.

Строка 03:

Устанавливает тип данных каждого элемента y, чтобы16-разрядное целое число.

Строка 04:

Устанавливает элемент y на пересечении среднего ряда и среднего столбца на 1.

Строка 05:

Создает двумерный массив из 3 x 3 единиц.x - это имя, которое указывает на этот ndarray.

Строка 06:

Вычитание (1-t) приводит к нескольким скалярным вычитаниям (1- elem), где elem - каждый элемент t.Результатом будет другой ndarray, имеющий ту же форму, что и t, и имеющий результат вычитания (1- elem), в качестве его значений.То есть значения ndarray (1-t) будут:

[[1-t[0,0], 1-t[0,1], 1-t[0,2]],
 [1-t[1,0], 1-t[1,1], 1-t[1,2]],
 [1-t[2,0], 1-t[2,1], 1-t[2,2]]]

, поскольку t полон нулей, а одиночный 1 на пересечении среднего ряда и среднего столбца, (1-t) будет двумерным ndarray, полным единиц, с одинокой 0 на пересечении среднего ряда и среднего столбца.

Строка 07:

Печать t

Строка 08:

Здесь все немного сложнее.То, что здесь происходит, называется «Комбинированное расширенное и базовое индексирование» (https://docs.scipy.org/doc/numpy-1.13.0/reference/arrays.indexing.html#combining-advanced-and-basic-indexing).. Давайте рассмотрим подробности, шаг за шагом. Во-первых, обратите внимание, что x, это двумерный ndarray, принимая другое целое числоndarray t в качестве индекса. Поскольку для x необходимо указать два индекса, t будет принят за первый из этих двух индексов, а второй индекс будет неявно принят за :.x[t] сначала интерпретируется как x[t,:]. Наличие этих двух индексов, где один индекс представляет собой массив целых чисел t, а другой индекс представляет собой срез :, приводит к ситуации, которая называется «комбинированная».Расширенное и базовое индексирование ".

Теперь, что именно происходит в этом" комбинированном "сценарии? Здесь говорится: во-первых, форма результата будет получать вклады из первого индекса t, а также извторой индекс :. Теперь t имеет форму (3,3), и, следовательно, вклад t в форму результата x[t,:] состоит в том, чтобы предоставить самый крайний (самый левый)размеры формы результата.Следовательно, форма результата будет начинаться с (3,3,).Теперь вклад : в форму x[t,:] основан на ответе на вопрос: к какому измерению x применяется :?Ответ - второе измерение (поскольку : является вторым индексом в x[t,:]).Следовательно, вклад : в результирующую форму x[t,:] равен 3 (поскольку 3 - это длина второго измерения x).Напомним, что мы пришли к выводу, что результирующая форма x[t] будет такой же, как x[t,:], что в свою очередь будет (3,3,3).Это означает, что x[t] будет трехмерным массивом, хотя x сам по себе является только двумерным массивом.

Обратите внимание, что в форме (3,3,3) результата первые два 3 s были добавлены расширенным индексом t, а последний 3 был внесен неявным базовым индексом :.Эти два индекса t и : также используют различные способы для получения своих соответствующих вкладов.Вклад 3,3, полученный от индекса t, является просто формой самого t.Его не волнует положение t среди индексов в выражении x[t,:] (не имеет значения, происходит ли t до того, как : или : появится до t).Вклад 3, полученный из индекса :, представляет собой длину второго измерения x, и мы рассматриваем второе измерение x, потому что : это второй индекс в выражении x[t,:].Если бы x имел форму (3,5) вместо (3,3), тогда форма x[t,:] была бы (3,3,5) вместо (3,3,3).

Теперь, когда мы вывели форму результата x[t] как (3,3,3), давайте перейдем к пониманию того, как сами значения будут определены,в результате.Значения в результате, очевидно, являются значениями в позициях [0,0,0], [0,0,1], [0,1,2], [0,1,0], [0,1,1], [0,1,2], [0,2,0], [0,2,1], [0,2,2] и так далее.Давайте пройдемся по одному из примеров этих позиций, и вы, надеюсь, получите дрейф.Для нашего примера, давайте посмотрим на позицию [0,1,2] в результате.Чтобы получить значение для этой позиции, мы сначала индексируем в массив t, используя 0 и 1. То есть мы находим t[0,1], что будет 1 (см. Вывод print(t)).Это 1, которое было получено в t[0,1], должно быть принято за наш первый индекс в x.Второй индекс в x будет 2 (помните, что мы обсуждаем позицию [0,1,2] в результате и пытаемся определить значение в этой позиции).Теперь, учитывая эти первый и второй индексы в x, мы получаем из x значение, которое нужно заполнить в позиции [0,1,2] из x[t].

Теперь, x просто полон единиц,Таким образом, x[t] будет состоять только из них, хотя форма x[t] равна (3,3,3).Чтобы действительно проверить ваше понимание того, что я уже сказал, вам нужно заполнить x различными значениями: поэтому временно закомментируйте строку 05 и поставьте на ее место следующую строку:

x = np.arange(9).reshape((3,3))    # New version of Line 05

Теперь вы обнаружите, что print(x[t]) в строке 08 дает вам:

[[[3 4 5]
  [3 4 5]
  [3 4 5]]

 [[3 4 5]
  [0 1 2]
  [3 4 5]]

 [[3 4 5]
  [3 4 5]
  [3 4 5]]]

Против этого вывода проверьте ваше понимание того, что я описал выше, о том, как получатся значения в результатеопределяется.(То есть, если вы поняли приведенное выше объяснение x[t], вы сможете вручную пересоздать тот же вывод, что и выше, для print (x[t]).

Строка 09:

Учитывая определение t в строке 06, строка 09 эквивалентна x[t], что, как мы видели выше, эквивалентно x[t, :] = 0.

.Эффект присваивания x[t, :] = 0 такой же, как эффект x[0:2, :] = 0.

Почему это так? Просто потому, что в x[t, :]:

  1. Сгенерированы значения индексаиндексом t являются 0 с и 1 с (поскольку t является целочисленным индексным массивом, состоящим только из 0 с и 1 с)
  2. Значения индекса, сгенерированныеиндексами : являются 0, 1 и 2.
  3. Мы имеем в виду только те позиции в пределах x, которые соответствуют комбинациям этих значений индекса. То есть x[t, :]относится только к тем позициям x[i,j], где i принимает значения 0 или 1, а j принимает значения 0, 1 или 2.x[t, :] относится только к позициям x[0,0], x[0,1], x[0,2], x[1,0], x[1,1], x[1,2], внутри массива x.
  4. Итак, оператор присваиванияx[t, :] = 0 присваивает значение 0 в этих позициях в x.По сути, мы присваиваем значение 0 во все три столбца в первых двух строках x, и мы оставляем третий ряд x без изменений.

Строка10:

Печатает значение x после указанного выше назначения.

...