Изменение значений с помощью прихотливой индексации
Аналогично тому, как «прихотливую» индексацию можно использовать для доступа к частям массива, ее можно применять и для модификации частей массива. Например, допустим, что у нас есть массив индексов и нам нужно присвоить соответствующим элементам массива какие-то значения:
x = np.arange(10)
i = np.array([2, 1, 8, 4])
x[i] = 99
print(x)
[ 0 99 99 3 99 5 6 7 99 9]
Для этого можно использовать любой из операторов присваивания. Например:
x[i] -= 10
print(x)
[ 0 89 89 3 89 5 6 7 89 9]
Замечу, однако, что повторяющиеся индексы при подобных операциях могут привести к некоторым потенциально неожиданным результатам. Рассмотрим следующий пример:
x = np.zeros(10)
x[[0, 0]] = [4, 6]
print(x)
[ 6. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
Куда пропало 4? В результате этой операции сначала выполняется присваивание x[0] = 4 с последующим присваиванием x[0] = 6. В итоге x[0] содержит значение 6.
Довольно логично, но рассмотрим такую операцию:
i = [2, 3, 3, 4, 4, 4]
x[i] += 1
x
Out: array([ 6., 0., 1., 1., 1., 0., 0., 0., 0., 0.])
Можно было ожидать, что x[3] будет содержать значение 2, а x[4] – значение 3, так как именно столько раз повторяется каждый из этих индексов. Почему же это не так? По сути, не из-за того, что выражение x[i] += 1 задумывалось как сокращенная форма записи для x[i] = x[i] + 1. Вычисляется выражение x[i] + 1, после чего результат присваивается соответствующим индексам элементам в массиве x. Получается, что это не выполняемый несколько раз инкремент, а присваивание, приводящее к интуитивно не очевидным результатам.
Что же делать, если требуется другое поведение при повторяющейся операции? В этом случае можно воспользоваться методом at() универсальных функций и сделать следующее:
x = np.zeros(10)
np.add.at(x, i, 1)
print(x)
[ 0. 0. 1. 2. 3. 0. 0. 0. 0. 0.]
Метод at() применяет соответствующий оператор к элементам с заданными индексами (в данном случае i) с использованием заданного значения (в данном случае 1). Аналогичный по духу метод универсальных функций reduceat(), о котором можно прочитать в документации библиотеки NumPy.
Достарыңызбен бөлісу: |