Почему numpy не позволяет присваивать дважды индексированный массив numpy? - PullRequest
0 голосов
/ 18 сентября 2018

Я бы хотел присвоить значения массива arr_2 другому массиву arr_1.Тем не менее, я хочу сделать это на основе 2 критериев отбора.В качестве рабочего примера я определяю свои критерии выбора как таковые

import numpy as np

# An array of -1 values of shape(10,): [-1 -1 -1 -1 -1 -1 -1 -1 -1 -1]
arr_1 = np.zeros(10, dtype=int) - 1
# An array of 0-9 values of shape(10,): [0 1 2 3 4 5 6 7 8 9]
arr_2 = np.arange(10)

# Create an initial selection of values we want to change
# In this example: even indices: [ T F T F T F T F T F]
selection_a = np.arange(10) % 2 == 0

# Create a second selection based on selection_a: [F F F T T]
selection_b = arr_2[selection_a] > 5

На основе этих двух критериев выбора я хотел бы присвоить значения arr_2, где оба условия выполняются для массива arr_1.Т.е. эквивалентно [F F F F F F T F T F].

arr_1[selection_a][selection_b] = arr_2[selection_a][selection_b]

Если я проверяю обе стороны уравнения перед присваиванием, они дают ожидаемые значения:

print(arr_1[selection_a][selection_b]) # yields [-1 -1]
print(arr_2[selection_a][selection_b]) # yields [ 6, 8]

Однако само присвоениене присваивает значения, т.е. arr_1 остается без изменений.Мой вопрос: почему это так?

NB : я знаю, что в большинстве (и, может быть, даже во всех случаях) это можно обойти, создав единый критерий, однако я хочузнаю, почему использование двух отдельных критериев не работает.

Если что-то неясно, пожалуйста, дайте мне знать, и я постараюсь уточнить.

Редактировать

Я исследовал этонемного дальше, и проблема, кажется, находится в левой части уравнения, так как что-то вроде

arr_1[selection_a][selection_b] = 5

тоже не работает.

Ответы [ 4 ]

0 голосов
/ 18 сентября 2018

Поскольку условия selection_a и selection_b не зависят друг от друга, вы можете просто создать комбинированную маску

selection_c = (np.arange(10) % 2 == 0) & (arr_2 >  5)

и использовать ее как

arr_1[selection_c] = 5
0 голосов
/ 18 сентября 2018

Добавление к решению Pierre de Buyl , если вы хотите получить желаемый результат изменения массива arr_1.Вы можете использовать np.where следующим образом:

arr_1[selection_a] = np.where(arr_2[selection_a]>5,arr_2[selection_a],arr_1[selection_a])

arr_1

Что дает

array([-1, -1, -1, -1, -1, -1,  6, -1,  8, -1])
0 голосов
/ 18 сентября 2018

Это связано с = в python, интерпретируемым как .__setitem__(), который может выбирать адреса памяти из назначенной переменной.Тем не менее, он не делает это рекурсивно, поэтому пока

a[boolean_mask] = 0 

работает, так как индексирование указывает на память в a,

a[mask1][mask2] = 0

, как индексированиеуказывает на память в a[mask1], которая является копией.

0 голосов
/ 18 сентября 2018

Однократное использование операторов [...] создает выделение в массиве, из которого вы можете читать и в которое вы можете писать. Повторное использование [...] считывает значения без проблем. Но что касается записи, второй доступ будет к временному массиву, созданному для соответствия правилам выбора (то есть временному объекту (2,), который является копией исходных данных) в вашей ситуации.

Редактировать: Булево индексирование является частью так называемого «Расширенного индексирования». Сохранение индексации на простые фрагменты позволяет избежать этих проблем с копированием.

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