numpy.mask_indices

numpy.mask_indices(n, mask_func, k=0)[source]

Функция mask_indices() индексы элементов квадратного массива выбранные по некоторому условию (маске массива).

Параметры:
n - целое положительное число.
Определяет размер квадратного массива для которого будут возвращены индексы.
mask_func - вызываемая функция.
Функция которая может принимать параметры n и k (последний не является обязательным), и по данным параметрам возвращать массив размером (n, n). Примером таких функций может служить tril или triu.
k - целое положительное число.
Определяет "смещение" функции, т.е. данный параметр не влияет на размер возвращаемого массива, а только на его содержание.
Возвращает:
tuple - кортеж массивов NumPy
кортеж массивов с индексами удовлетворяющих маске элементов квадратного массива.
Смотрите так же:
diag_indices_from, diag, diagflat, diagonal

Замечание

Данная функция в своем теле создает массив заполненный единицами размером (n, n). После создания он передается функции mask_func, которая помимо данного массива может принимать еще один целочисленный параметр k, который определяет "смещение". Все это значит, что для функции mask_func абсолютно неважно значение элементов, а важен лишь их индекс и заданное смещение.

Функция mask_func в конечном итоге должна выдать массив размером (n, n), в котором нулевые и ненулевые элементы играют роль логического условия: нулевой элемент маски - значит что mask_indices() не возвращает его индекс, а ненулевой возвращает.

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



Примеры

Допустим у нас есть следующая функция маскирования:

>>> import numpy as np
>>> 
>>> def mask(m, k=0):
...     s = m.shape(0)
...     l = s
...     for i in range(s):
...         for j in range(l):
...             if i == (j + k): m[i][j] = 0
...     return m

Что бы взглянуть на результат ее работы создадим единичный массив и передадим его функции:

>>> np.ones((6, 6))
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., 1., 1., 1., 1., 1.],
       [1., 1., 1., 1., 1., 1.]])
>>> 
>>> mask(np.ones((6, 6)))
array([[0., 1., 1., 1., 1., 1.],
       [1., 0., 1., 1., 1., 1.],
       [1., 1., 0., 1., 1., 1.],
       [1., 1., 1., 0., 1., 1.],
       [1., 1., 1., 1., 0., 1.],
       [1., 1., 1., 1., 1., 0.]])

Как видим, все элементы находящиеся на диагонали стали равны 0, но мы можем передать данной функции еще и "смещение" k, которое в нашем случае приводит к смещению диагонали:

>>> mask(np.ones((6, 6)), k = 2)
array([[1., 1., 1., 1., 1., 1.],
       [1., 1., 1., 1., 1., 1.],
       [0., 1., 1., 1., 1., 1.],
       [1., 0., 1., 1., 1., 1.],
       [1., 1., 0., 1., 1., 1.],
       [1., 1., 1., 0., 1., 1.]])
>>> 
>>> mask(np.ones((6, 6)), k = -2)
array([[1., 1., 0., 1., 1., 1.],
       [1., 1., 1., 0., 1., 1.],
       [1., 1., 1., 1., 0., 1.],
       [1., 1., 1., 1., 1., 0.],
       [1., 1., 1., 1., 1., 1.],
       [1., 1., 1., 1., 1., 1.]])

Итак, маскирующая функция есть, теперь переходим к mask_indices():

>>> ind = np.mask_indices(6, mask)
>>> ind
(array([0, 0, 0, ..., 5, 5, 5], dtype=int32), array([1, 2, 3, ..., 2, 3, 4], dtype=int32))

Сейчас данная функция вернула индексы ненулевых элементов массива возвращаемого функцией mask(). Эти индексы мы можем применить для любого другого массива той же формы, например:

>>> b = np.arange(36).reshape(6, 6)
>>> b
array([[ 0,  1,  2,  3,  4,  5],
       [ 6,  7,  8,  9, 10, 11],
       [12, 13, 14, 15, 16, 17],
       [18, 19, 20, 21, 22, 23],
       [24, 25, 26, 27, 28, 29],
       [30, 31, 32, 33, 34, 35]])
>>> 
>>> b[ind]
array([ 1,  2,  3, ..., 32, 33, 34])
>>> 
>>> b[ind].size    #  узнаем количество элементов
30
>>> 
>>> b[ind].reshape(6, 5)
array([[ 1,  2,  3,  4,  5],
       [ 6,  8,  9, 10, 11],
       [12, 13, 15, 16, 17],
       [18, 19, 20, 22, 23],
       [24, 25, 26, 27, 29],
       [30, 31, 32, 33, 34]])

Можем передать параметр k:

>>> ind = np.mask_indices(6, mask, -2)
>>> ind
(array([0, 0, 0, ..., 5, 5, 5], dtype=int32), array([0, 1, 3, ..., 3, 4, 5], dtype=int32))
>>> 
>>> b[ind].size    #  узнаем количество элементов
32
>>> b[ind].reshape(2, 4, 4)
array([[[ 0,  1,  3,  4],
        [ 5,  6,  7,  8],
        [10, 11, 12, 13],
        [14, 15, 17, 18]],

       [[19, 20, 21, 22],
        [24, 25, 26, 27],
        [28, 29, 30, 31],
        [32, 33, 34, 35]]])

Действительно, элементов ([2, 9, 16, 23]) с смещенной диагонали исходного массива нет.