Модификация замаскированного массива Numpy

В настоящее время у меня есть код, который проверяет, равен ли данный элемент в массиве = 0, и если да, то установите для значения значение «уровень» (temp_board — это массив 2D numpy, index_to_watch содержит 2D-координаты, которые следует отслеживать для нулей).

    indices_to_watch = [(0,1), (1,2)]
    for index in indices_to_watch:
        if temp_board[index] == 0:
            temp_board[index] = level

Я хотел бы преобразовать это в более похожий на numpy подход (удалить for и использовать только функции numpy), чтобы ускорить это. Вот что я пробовал:

    masked = np.ma.array(temp_board, mask=(a!=0), hard_mask=True)
    masked.put(indices_to_watch, level)

Но, к сожалению, замаскированный массив при выполнении put() хочет иметь одномерные размеры (совершенно странно!), есть ли другой способ обновления элементов массива, которые равны 0 и имеют конкретные индексы?

Или, может быть, использование маскированных массивов — не выход?


person Krzysztof Krasoń    schedule 21.02.2010    source источник


Ответы (3)


Предполагая, что не так уж неэффективно узнать, где temp_board находится 0, вы можете делать то, что хотите, вот так:

# First figure out where the array is zero
zindex = numpy.where(temp_board == 0)
# Make a set of tuples out of it
zindex = set(zip(*zindex))
# Make a set of tuples from indices_to_watch too
indices_to_watch = set([(0,1), (1,2)])
# Find the intersection.  These are the indices that need to be set
indices_to_set = indices_to_watch & zindex
# Set the value
temp_board[zip(*indices_to_set)] = level

Если вы не можете сделать вышеперечисленное, то вот способ, но я не уверен, что он самый Pythonic:

indices_to_watch = [(0,1), (1,2)]

Сначала преобразуйте в массив numpy:

indices_to_watch = numpy.array(indices_to_watch)

Затем сделайте его индексируемым:

index = zip(*indices_to_watch)

Затем проверьте условие:

indices_to_set = numpy.where(temp_board[index] == 0)

Затем выясните фактические индексы для установки:

final_index = zip(*indices_to_watch[indices_to_set])

Наконец, установите значения:

temp_board[final_index] = level
person Alok Singhal    schedule 23.02.2010
comment
Спасибо :) Я попробовал numpy.where(), но не подумал объединить его с пересечением set - person Krzysztof Krasoń; 23.02.2010

Я не уверен, что следую всем деталям вашего вопроса. Если я правильно понял, то похоже, что это простая индексация Numpy. Приведенный ниже код проверяет массив (A) на наличие нулей и там, где он их находит, заменяет их на «уровень».

import numpy as NP
A = NP.random.randint(0, 10, 20).reshape(5, 4) 
level = 999
ndx = A==0
A[ndx] = level
person doug    schedule 21.02.2010

Вы должны попробовать что-то в этом роде:

temp_board[temp_board[field_list] == 0] = level
person Olivier Verdier    schedule 21.02.2010
comment
к сожалению, temp_board[field_list] == ​​0 возвращает маску меньше размера temp_board - person Krzysztof Krasoń; 21.02.2010