Обновление элементов в многоиндексированных np.array - PullRequest
1 голос
/ 23 марта 2019

У меня есть двумерный массив NumPy и мне нужно обновить выбор элементов через несколько уровней индексации.Очевидный способ сделать это для меня не работает, так как кажется, что numpy обновляет только копию массива, а не сам массив:

import numpy as np

# Create an array and indices that should be updated
arr = np.arange(9).reshape(3,3)
idx = np.array([[0,2], [1,1],[2,0]])
bool_idx = np.array([True, True, False])

# This line does not work as intended since the original array stays unchanged
arr[idx[:,0],idx[:,1]][bool_idx] = -1 * arr[idx[:,0],idx[:,1]][bool_idx]

Вот результат:

>>> arr
array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]])

Тем не менее, я ожидал этот вывод:

>>> arr
array([[0, 1, -2],
       [3, -4, 5],
       [6, 7, 8]])

Ответы [ 2 ]

1 голос
/ 23 марта 2019

Вам просто нужно внести небольшое изменение в вашу собственную попытку - вам нужно применить массив логических индексов к каждому из ваших выражений целочисленных индексов. Другими словами, это должно работать:

arr[idx[:,0][bool_idx],idx[:,1][bool_idx]] *= -1

(я только что переместил [bool_idx] в квадратные скобки, чтобы применить его к обоим выражениям целочисленного индекса - idx[:,0] и idx[:,1])

1 голос
/ 23 марта 2019

Нам нужно замаскировать индексы с указанным 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.

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