Как чисто индексировать массивы numpy массивами (или что-нибудь еще, что поддерживает добавление, чтобы оно могло быть смещено)

Самый простой способ объяснить мой вопрос может быть с примером, поэтому позвольте мне определить некоторые массивы:

>>> test = arange(25).reshape((5,5))
>>> test
array([[ 0,  1,  2,  3,  4],
      [ 5,  6,  7,  8,  9],
      [10, 11, 12, 13, 14],
      [15, 16, 17, 18, 19],
      [20, 21, 22, 23, 24]])
>>> Xinds = array([1,2,3])
>>> Yinds = array([1,2,3])

Теперь, если мне нужны элементы в строках 1, 2 и 3 и в столбце 0, я мог бы пойти:

>>> test[Yinds,0]
array([ 5, 10, 15])

Если бы мне нужны элементы в строках 1, 2 и 3 и все столбцы, я мог бы пойти:

>>> test[Yinds, :]
array([[ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14],
       [15, 16, 17, 18, 19]])

Однако, если я попытаюсь расширить это, чтобы получить элементы в строках 1, 2 и 3 и столбцы 1, 2 и 3, - удивите! - Вместо этого я получаю элементы в (1,1), (2,2) и (3,3)

>>> test[Yinds, Xinds]
array([ 6, 12, 18])

Вместо того, что я хочу:

>>> test[Yinds, :][:, Xinds]
array([[ 6,  7,  8],
       [11, 12, 13],
       [16, 17, 18]])
>>> test[1:4,1:4]
array([[ 6,  7,  8],
       [11, 12, 13],
       [16, 17, 18]])

Я понимаю, что могу определить срез, но я хочу иметь возможность добавлять смещение к индексам (например, Yinds + offset), и это невозможно сделать с помощью срезов.

Я мог бы сделать что-то вроде

>>> xStart = 1
>>> xEnd   = 4
>>> yStart = 1
>>> yEnd   = 4

>>> offset = 1
>>> test[yStart+offset:yEnd+offset, xStart+offset:xEnd+offset]
...

или

>>> Xinds = array([1,4])
>>> Yinds = array([1,4])

>>> offset = 1
>>> test[slice(*(Yinds+offset)), slice(*(Xinds+offset))]
...

Но ни один из них не является чистым.

Обезьяна, исправляющая оператор добавления в срез, кажется, не является опцией, и наследование от среза для добавления оператора тоже не работает; Я получаю ошибку: "Тип" срез "не является приемлемым базовым типом". (* Grumble * Это не проблема в Ruby * Grumble *)

Итак, мой вопрос: какой самый чистый способ доступа к (более чем одному размерному) подматрицу с чем-то, что можно сохранить и смещать?

Параметры до сих пор:

  • test [Yinds + offset,:] [:, Xinds + offset]
  • test [yStart + offset: yEnd + offset, xStart + offset: xEnd + offset]
  • test [slice (* (Yinds + offset)), slice (* (Xinds + offset))]

Ответ 1

Я не совсем уверен, чего вы хотите, но, может быть, ix_ поможет? Я думаю, что видел людей, которые знают больше о numpy, чем я использую его в подобных контекстах.

>>> from numpy import array, arange, ix_
>>> a = arange(25).reshape(5,5)
>>> Xinds = array([1,2,3])
>>> Yinds = array([1,2,3])
>>> a
array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14],
       [15, 16, 17, 18, 19],
       [20, 21, 22, 23, 24]])
>>> a[ix_(Xinds, Yinds)]
array([[ 6,  7,  8],
       [11, 12, 13],
       [16, 17, 18]])
>>> a[ix_(Xinds+1, Yinds)]
array([[11, 12, 13],
       [16, 17, 18],
       [21, 22, 23]])
>>> Y2inds = array([1,3,4])
>>> a[ix_(Xinds, Y2inds)]
array([[ 6,  8,  9],
       [11, 13, 14],
       [16, 18, 19]])
>>> a[ix_(Xinds, Y2inds-1)]
array([[ 5,  7,  8],
       [10, 12, 13],
       [15, 17, 18]])