Python: маскировка многомерного массива

Что эквивалентно реализации pythonic для следующего простого фрагмента кода в Matlab.

Matlab:


B = 2D array of integers as indices [1...100]
A = 2D array of numbers: [10x10]
A[B] = 0

который работает хорошо, например, для B[i]=42 он находит позицию 2 столбца 5 для установки. В Python это вызывает ошибку: вне границ, что логично. Однако для перевода приведенного выше кода Matlab на Python мы ищем питонические способы. Пожалуйста, также рассмотрите проблему для более высоких измерений, таких как:


B = 2D array of integers as indices [1...3000]
C = 3D array of numbers: [10x10x30]
C[B] = 0

Один из способов, которым мы думали об этом, - преобразовать элементы массива индексов в i,j вместо абсолютной позиции. То есть позиции с 42 по divmod(42,m=10)[::-1] >>> (2,4). Таким образом, у нас будет nx2 >>> ii,jj векторов индексов, которые можно легко использовать для индексации A. Мы подумали, что это может быть лучшим способом, эффективным также для более высоких измерений в Python.


person Developer    schedule 20.01.2012    source источник
comment
В Python это вызывает ошибку: выход за пределы, что логично... что вызывает это? Можете ли вы показать, что вы пробовали в Python?   -  person Laurence Gonsalves    schedule 20.01.2012
comment
Почему вы используете 2D-массив в качестве индекса другого 2D-массива?   -  person Sufian Latif    schedule 20.01.2012
comment
@LaurenceGonsalves Как упоминалось в вопросе, A.shape = (10,10), поэтому индексирование по A[42] незаконно! Это не относится к коду Matlab, поскольку он автоматически сопоставляет 42 со строкой 2 и столбцом 4.   -  person Developer    schedule 20.01.2012
comment
@FlopCoder Потому что я перевожу уже написанный код. Мне нравится логика Python, которая true вызывает ошибку.   -  person Developer    schedule 20.01.2012


Ответы (1)


Вы можете использовать .ravel() для массива (A) перед его индексацией, а затем .reshape() после.

В качестве альтернативы, поскольку вы знаете A.shape, вы можете использовать np.unravel_index в другом массиве (B) перед индексацией.

Пример 1:

>>> import numpy as np
>>> A = np.ones((5,5), dtype=int)
>>> B = [1, 3, 7, 23]
>>> A
array([[1, 1, 1, 1, 1],
       [1, 1, 1, 1, 1],
       [1, 1, 1, 1, 1],
       [1, 1, 1, 1, 1],
       [1, 1, 1, 1, 1]])
>>> A_ = A.ravel()
>>> A_[B] = 0
>>> A_.reshape(A.shape)
array([[1, 0, 1, 0, 1],
       [1, 1, 0, 1, 1],
       [1, 1, 1, 1, 1],
       [1, 1, 1, 1, 1],
       [1, 1, 1, 0, 1]])

Пример 2:

>>> b_row, b_col = np.vstack([np.unravel_index(b, A.shape) for b in B]).T
>>> A[b_row, b_col] = 0
>>> A
array([[1, 0, 1, 0, 1],
       [1, 1, 0, 1, 1],
       [1, 1, 1, 1, 1],
       [1, 1, 1, 1, 1],
       [1, 1, 1, 0, 1]])

Обнаружено позже: вы можете использовать numpy.put

>>> import numpy as np
>>> A = np.ones((5,5), dtype=int)
>>> B = [1, 3, 7, 23]
>>> A.put(B, [0]*len(B))
>>> A
array([[1, 0, 1, 0, 1],
       [1, 1, 0, 1, 1],
       [1, 1, 1, 1, 1],
       [1, 1, 1, 1, 1],
       [1, 1, 1, 0, 1]])
person wim    schedule 20.01.2012
comment
Спасибо за примеры. Я собирался попросить вас продемонстрировать ваше решение на примере, ...вау! вы сделали, прежде чем я опубликовать его. С этими примерами идея теперь ясна. Оба метода полезны. - person Developer; 20.01.2012