#python #arrays #numpy
#питон #массивы #тупой
Вопрос:
У меня есть массив A. У меня есть еще один массив, который я называю switch. Переключатель массива — это массив логических значений (и np.nan, которые соответствуют расположению массивов np.nan 3 x 3 в A), который определяет, какой массив 3 x 3 в A будет выбран для операции.
Пример:
switch = np.array([ True, False, False, False, np.nan])
a = np.array([[[ 0., 0., 0.],
[ 9., 0., 0.],
[ 3., 15., 0.]],
[[ 0., 0., 0.],
[ 9., 0., 0.],
[ 3., 15., 0.]],
[[ 0., 27., 0.],
[ 0., 0., 0.],
[12., 18., 0.]],
[[ 0., 0., 6.],
[12., 0., 27.],
[ 0., 0., 0.]],
[[ np.nan, np.nan, np.nan],
[np.nan, np.nan, np.nan],
[ np.nan, np.nan, np.nan]]])
Окончательный выбранный массив, основанный на приведенном выше примере, должен быть:
np.array([[[ 0., 0., 0.],
[ 9., 0., 0.],
[ 3., 15., 0.]],
[[ np.nan, np.nan, np.nan],
[np.nan, np.nan, np.nan],
[ np.nan, np.nan, np.nan]],
[[ np.nan, np.nan, np.nan],
[np.nan, np.nan, np.nan],
[ np.nan, np.nan, np.nan]],
[[ np.nan, np.nan, np.nan],
[np.nan, np.nan, np.nan],
[ np.nan, np.nan, np.nan]],
[[ np.nan, np.nan, np.nan],
[np.nan, np.nan, np.nan],
[ np.nan, np.nan, np.nan]]])
Я могу сделать это, используя цикл for и выполняя итерацию по каждому массиву 3 x 3 в A с использованием управляющих операторов if / else, но мне интересно, есть ли способ сделать это, используя встроенную функциональность в numpy. Циклы For и операторы if /else, вероятно, намного медленнее, чем манипулирование массивом. Я повозился, но до сих пор не смог найти оптимального решения numpy.
Я могу реструктурировать переключатель массива, но массив A я не могу изменить структуру / форму.
Комментарии:
1. Уместно: thedailywtf.com/articles/What_Is_Truth_0x3f_
2. Что вы на самом деле пробовали? Numpy поддерживает прямое логическое индексирование
Ответ №1:
Вы можете использовать np.where
:
out = np.where(switch[:,None,None], a, np.nan)
Или используйте маскировку:
out = a.copy()
out[switch!=True] = np.nan
Выходной сигнал:
array([[[ 0., 0., 0.],
[ 9., 0., 0.],
[ 3., 15., 0.]],
[[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan]],
[[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan]],
[[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan]],
[[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan]]])
Комментарии:
1. Первый метод не работает, но второй метод работает. Есть мысли, почему первое не работает? Я знаю, что nan не является правильной маской bool, но именно так поступают мои данные.
2. Это работает в моей системе с numpy 1.19.2. Возможно, явно использовать
switch==True
вместоswitch
helps.
Ответ №2:
Это было бы намного проще, если бы вы использовали правильную логическую маску. Numpy допускает логическую индексацию, но помещение an nan
в массив превращает его в a float
.
Для этого конкретного примера не имеет значения, какое значение принимают NAN, поэтому вы можете сделать
switch = switch.astype(bool)
result = np.full_like(a, np.nan)
result[switch] = a[switch]