2D булева маска в numpy дает разные результаты (упорядочение маски по сравнению с исходными индексами) - PullRequest
0 голосов
/ 09 ноября 2018

Я играю с разными методами индексации. У меня есть следующий рабочий пример:

import numpy as np

x = np.random.rand(321,321)
a = range(0, 300)
b = range(1, 301)
mask = np.zeros(x.shape, dtype=bool)
# a and b are lists 
mask[a, b] = True
assert x[a, b].shape == x[mask].shape  # passes
assert np.isclose(np.sum(x[mask]), np.sum(x[a, b]))  # passes
assert np.allclose(x[mask], x[a, b])  # fails sometimes

Когда я пробую его с другим x для проекта, последнее утверждение не выполняется. Вот неудачный случай:

import numpy as np

x = np.random.rand(431,431)
a = [0, 1, 1, 1, 2, 2, 2, 3]
b = [1, 0, 2, 4, 3, 1, 11, 2]

mask = np.zeros(x.shape, dtype=bool)
# a and b are lists 
mask[a, b] = True
assert x[a, b].shape == x[mask].shape  # passes
assert np.isclose(np.sum(x[mask]), np.sum(x[a, b]))  # passes
assert np.allclose(x[mask], x[a, b])  # fails

Может кто-нибудь объяснить, почему возникает эта ошибка? Я предполагаю, что это потому, что маска индексирует в x не так, как (a, b), но не знаю как.

Я хочу сделать это, потому что я хотел бы легко получить x[~mask]

Любое понимание будет оценено!

Ответы [ 3 ]

0 голосов
/ 09 ноября 2018

Как упомянул @hpaulj, порядок массивов другой:

import numpy as np
np.random.seed(42)

x = np.random.rand(431,431)
a = [0, 1, 1, 1, 2, 2, 2, 3]
b = [1, 0, 2, 4, 3, 1, 11, 2]

mask = np.zeros(x.shape, dtype=bool)
# a and b are lists
mask[a, b] = True

print(x[mask])
print(x[a, b])

выход

[0.95071431 0.76151063 0.10112268 0.70096913 0.44076275 0.55964033
 0.40873417 0.20015024]
[0.95071431 0.76151063 0.10112268 0.70096913 0.55964033 0.44076275
 0.40873417 0.20015024]

Причина в том, что маска возвращается в порядке строки (в стиле C) (см. документы ) и для многомерного индексирования :

если индексные массивы имеют совпадающую форму и существует индексный массив для каждого измерения индексируемого массива результирующий массив имеет той же формы, что и индексные массивы, а значения соответствуют Индекс установлен для каждой позиции в массивах индексов.

В вашем случае порядок многомерной индексации:

[(0, 1), (1, 0), (1, 2), (1, 4), (2, 3), (2, 1), (2, 11), (3, 2)]

а из маски есть:

[(0, 1), (1, 0), (1, 2), (1, 4), (2, 1), (2, 3), (2, 11), (3, 2)]
0 голосов
/ 09 ноября 2018

x[a, b] выбирает элементы из x в порядке, заданном a и b. x[a[i], b[i]] придет раньше x[a[i+1], b[i+1]] в результате.

x[mask] выбирает элементы в порядке, указанном путем итерации по mask в главном порядке строк, чтобы найти True ячеек. Это тот же порядок, что и x[a, b], если zip(a, b) уже лексикографически отсортирован.

В вашем неудачном примере, 2, 3 предшествует 2, 1 в a и b, но итерируя по mask в главном порядке строк, вы найдете True в 2, 1 перед 2, 3 , Таким образом, x[mask] имеет x[2, 1] перед x[2, 3], в то время как x[a, b] имеет эти элементы наоборот.

0 голосов
/ 09 ноября 2018

Проблема с вашим примером заключается в том, как вы определили a и b. Если бы вы распечатали x[a, b] и x[mask], вы заметили бы, что 5-й и 6-й элементы на x[a, b] будут переключаться с 5-м и 6-м значениями в x[mask]. Причина этого в том, что вы устанавливаете каждое значение в mask на True, используя a и b для индексации, поэтому порядок не имеет значения, но вы используете a и b для индексации x в своем утверждении так что порядок имеет значение там. Когда вы выполняете индексирование, numpy берет каждое значение из a, чтобы получить соответствующую строку из вашей матрицы, и использует значение из того же индекса в b, чтобы индексировать в эту строку. Чтобы проиллюстрировать использование массива 3x8:

a = [0, 1, 1, 1, 2, 2, 2]
b = [1, 0, 2, 4, 3, 1, 7]

x = [[1, 2, 3, 4, 5, 6, 7, 8],
    [9, 10, 11, 12, 13, 14, 15, 16],
    [17, 18, 19, 20, 21, 22, 23, 24]]

x[a, b] = [2, 9, 11, 13, 20, 18, 24]
mask[a, b] = [2, 9, 11, 13, 18, 20, 24]

Хороший способ исправить это - сначала определить a и b как список кортежей, отсортировать их сначала по их «a-значению», а затем по «b-значению» и использовать их из там. Таким образом, вы можете гарантировать заказ.

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