Найти количество ненулевых элементов, примыкающих к нулям в двумерном массиве - PullRequest
5 голосов
/ 28 марта 2019

Учитывая матрицу, я хочу посчитать количество заполненных элементов (ненулевых ячеек), смежных с пустыми (нулевыми) ячейками, где смежность находится вдоль строк (влево / вправо).

Я пытался игратьс np.roll и вычитая матрицы, но я не уверен, как закодировать это без циклов.

Например, учитывая матрицу:

arr = 
[[1 1 0 0 0 0 0 0 1 0]
 [1 1 0 0 0 0 0 1 1 1]
 [0 1 1 0 0 0 0 0 0 0]
 [0 1 1 0 0 0 0 0 0 0]
 [0 1 1 0 0 0 0 0 0 0]
 [0 0 1 0 0 0 0 0 0 0]
 [0 0 1 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0]]

У нас есть 12 ненулевыхэлементы, смежные с нулями.

Ответы [ 2 ]

3 голосов
/ 28 марта 2019

Вы должны иметь возможность сделать что-то вроде

ar = a[:,1:] & ~a[:,:-1]
al = a[:,:-1] & ~a[:,1:]
al[:, 0].sum() + (al[:, 1:] | ar[:, :-1]).sum() + ar[:, -1].sum()  # 12

Здесь идея состоит в том, что ar отслеживает те 1, которые находятся справа от 0, тогда как al отслеживаетте 1, которые находятся слева от 0, и тогда мы позаботимся о том, чтобы не удваивать счет.

Если вы не возражаете против работы с транспонированием, все становится немного более кратким:

b = a.T
br = b[1:] & ~b[:-1]
bl = b[:-1] & ~b[1:]
bl[0].sum() + (bl[1:] | br[:-1]).sum() + br[-1].sum()  # Also 12

Возможно, более читаемой версией, в которой не нужно обрабатывать два ребра по отдельности, будет расширение как b[1:], так и b[:-1] на один столбец:

edge = np.ones(9, int)
(b & ~(np.vstack([b[1:], edge]) & np.vstack([edge, b[:-1]]))).sum()  # Also 12
3 голосов
/ 28 марта 2019

Подход № 1

Мы можем использовать 2D convolution, чтобы решить его с соответствующим ядром ([1,1,1]) или ([1,0,1]) на маске zerosи ищите, чтобы свертки суммировались как >=1, что сигнализирует по крайней мере один ноль в каждом скользящем окне из трех элементов и с дополнительной проверкой того, что текущий элемент ненулевой, подтверждает, что есть по крайней мере один соседний 0.

Реализация будет выглядеть примерно так -

In [245]: a  # input array
Out[245]: 
array([[1, 1, 0, 0, 0, 0, 0, 0, 1, 0],
       [1, 1, 0, 0, 0, 0, 0, 1, 1, 1],
       [0, 1, 1, 0, 0, 0, 0, 0, 0, 0],
       [0, 1, 1, 0, 0, 0, 0, 0, 0, 0],
       [0, 1, 1, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]])

In [246]: from scipy.signal import convolve2d

In [248]: k = [[1,1,1]] # kernel for convolution

In [249]: ((convolve2d(a==0,k,'same')>=1) & (a!=0)).sum()
Out[249]: 12

Подход № 2

Другой подход будет использовать slicing, как мыищите одноразовые смещенные элементы вдоль каждой строки для совпадений нулей и ненулей для левой и правой сторон LHS и RHS и, наконец, суммируйте их -

maskRHS = (a[:,1:]==0) & (a[:,:-1]!=0)
maskLHS = (a[:,1:]!=0) & (a[:,:-1]==0)
maskRHS[:,1:] |= maskLHS[:,:-1]
out = maskRHS.sum() + maskLHS[:,-1].sum()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...