Неожиданное поведение при индексировании 2D np.array с двумя булевыми массивами

two_d = np.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]])

first = np.array((True, True, False, False, False))
second = np.array((False, False, False, True, True))

Теперь, когда я ввожу:

two_d[first, second]

Я получаю:

array([3,9])

который не имеет для меня большого смысла. Может ли кто-нибудь объяснить это просто?

Ответ 1

При задании нескольких булевых массивов для индексирования NumPy связывает индексы значений True. Первое истинное значение в first в паре с первым истинным значением в second и т.д. Затем NumPy извлекает элементы в каждом из этих индексов (x, y).

Это означает, что two_d[first, second] эквивалентно:

two_d[[0, 1], [3, 4]]

Другими словами, вы извлекаете значения по индексу (0, 3) и индексу (1, 4); 3 и 9. Обратите внимание, что если два массива имеют разные значения истинных значений, ошибка будет повышена!

В документах для расширенной индексации кратко укажите это поведение и предложите np.ix_ как "менее удивительную" альтернативу:

Объединение нескольких булевых индексирующих массивов или логических с целым индексирующим массивом лучше всего понять с помощью аналогии obj.nonzero(). Функция ix_ также поддерживает логические массивы и будет работать без каких-либо неожиданностей.

Следовательно, вы можете искать:

>>> two_d[np.ix_(first, second)]
array([[3, 4],
       [8, 9]])

Ответ 2

Отметьте документацию по булевской индексации.

two_d[first, second] совпадает с two_d[first.nonzero(), second.nonzero()], где:

>>> first.nonzero()
(array([0, 1]),)
>>> second.nonzero()
(array([3, 4]),)

Используется как индексы, это будет выбирать 3 и 9, потому что

>>> two_d[0,3]
3
>>> two_d[1,4]
9

и

>>> two_d[[0,1],[3,4]]
array([3, 9])

Также mildy related: Индексирование NumPi с помощью List?