Нам нужно замаскировать индексы с указанным mask
, а затем индексировать в arr
и назначить новые значения. Для индексации мы можем использовать tuple(masked_indices)
для индексации или использовать два столбца индекса-массива для целочисленной индексации, что дает нам два метода.
Метод № 1:
arr[tuple(idx[bool_idx].T)] *= -1
Метод № 2:
idx_masked = idx[bool_idx]
arr[idx_masked[:,0],idx_masked[:,1]] *= -1
Почему оригинальный метод не сработал?
На LHS вы делали arr[idx[:,0],idx[:,1]][bool_idx]
, что в сущности состоит из двух шагов: arr[idx[:,0],idx[:,1]]
, который под капотом называет arr.__getitem__(indexer)
*. Когда индексатор является срезом, регулярность элементов позволяет NumPy возвращать представление (путем изменения шагов и смещения). Когда индексатор является произвольной логической маской или произвольным массивом целых чисел, в общем случае не существует регулярности для выбранных элементов, поэтому нет способа вернуть представление. Давайте назовем arr[idx[:,0],idx[:,1]]
как arr2
.
На следующем шаге, с объединенными arr[idx[:,0],idx[:,1]][bool_idx]
, то есть arr2[bool_idx]
, под капотами он вызывает arr2.__setitem__(mask)
, который реализован для изменения arr2
и, как таковой, не распространяется на arr
.
* Вдохновение от - https://stackoverflow.com/a/38768993/.
Подробнее о __getitem__
, __setitem__
.
Почему методы, опубликованные в этом посте, работают?
Поскольку оба непосредственно использовали indexer
на arr
с arr.__setitem__(indexer)
, который изменяет arr
.