Невозможно присвоить значения массиву с использованием трехмерного маскирования и индексации. - PullRequest
1 голос
/ 26 июня 2019

У меня есть 3D-массив, который является маской.Кроме того, у меня есть некоторые индексы, которые кодируют, где (позиция массива) должны быть сохранены некоторые значения.

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

Я не вижу, чего мне здесь не хватает.Я также попытался numpy.put без удачи.

import numpy as np

# Initialize output matrix (here the results will be stored)
results = np.zeros((67, 67, 45))

# define the mask - where to put the calculated values in the results array
mask = np.random.randint(2, size=(67, 67, 45)).astype(bool)

# store the results only in these positions
index_keep = range(0, 13732)

values = np.ones((13732,))

results[mask][index_keep] = values.copy()

# the results array is still empty
print(results.sum())
#0

Ответы [ 2 ]

3 голосов
/ 26 июня 2019

Когда вы индексируете массив с помощью логической маски, элементы извлекаются и помещаются в одномерный массив.Это в значительной степени должно было иметь место, так как выбранные элементы маски не являются равномерно распределенными по нашему в любом измерении.Выражение results[mask] = value эквивалентно results.__setitem__(mask, value): явно модификация на месте result.Однако results[mask][index_keep] = value эквивалентно result.__getitem__(mask).__setitem__(index_keep, value).Операция на месте происходит с временным массивом, который полностью отбрасывается.

Решение состоит в том, чтобы поиграть с индексом, чтобы получить один вызов __setitem__ для нужного объекта.Один из способов сделать это - применить index_keep к mask.Сначала вам нужно будет преобразовать mask в линейные индексы, например, с помощью np.flatnonzero:

result.ravel()[np.flatnonzero(mask)[index_keep]] = value

Это будет работать до тех пор, пока ravel возвращаетвид, который он должен в большинстве случаев.Если result является непрерывным массивом, это будет работать постоянно.Он не будет работать, если result уже является подмножеством массива большего размера.

Преимущество этого подхода состоит в том, что он использует только один индексный массив и работает для любого числа измерений.Использование np.where может быть адаптировано для того же, но требует большего временного хранения.Недостатком, конечно, является то, что этот подход ограничен непрерывными массивами.

PS Вам почти наверняка не нужно копировать value.Его элементы не будут изменены, и назначение уже сделает копию в соответствующих местах result.Создание копии просто создает ненужный временный массив, который будет немедленно отброшен.

2 голосов
/ 26 июня 2019

Вы можете использовать numpy.where на вашем mask, что позволит вам получить представление вашего массива results для индексации.

x, y, z = np.where(mask)

results[x[index_keep], y[index_keep], z[index_keep]] = values
...