Как найти, где в массиве numpy нулевому элементу предшествуют как минимум N-1 последовательных нулей? - PullRequest
0 голосов
/ 17 января 2019

Учитывая простой массив (пусть это будет битовый массив для простоты), как я могу построить новый массив той же формы, где 1 стоит точно в тех местах, где в исходном массиве был ноль, которому предшествует по крайней мере N-1 последовательных нулей?

Например, как лучше всего реализовать функцию nzeros, имеющую два аргумента, пустой массив и минимальное требуемое количество последовательных нулей:

import numpy as np
a = np.array([0, 0, 0, 0, 1, 0, 0, 0, 1, 1])
b = nzeros(a, 3)

Функция nzeros(a, 3) должна вернуть

array([0, 0, 1, 1, 0, 0, 0, 1, 0, 0])

Ответы [ 2 ]

0 голосов
/ 17 января 2019

Использование для цикла:

def nzeros(a, n):
  #Create a numpy array of zeros of length equal to n
  b = np.zeros(n)

  #Create a numpy array of zeros of same length as array a
  c = np.zeros(len(a), dtype=int)

  for i in range(0,len(a) - n):
    if (b == a[i : i+n]).all():  #Check if array b is equal to slice in a
      c[i+n-1] = 1

  return c

Пример вывода:

print(nzeros(a, 3))
[0 0 1 1 0 0 0 1 0 0]
0 голосов
/ 17 января 2019

Подход № 1

Мы можем использовать 1D свертка -

def nzeros(a, n):
    # Define kernel for 1D convolution
    k = np.ones(n,dtype=int)

    # Get sliding summations for zero matches with that kernel
    s = np.convolve(a==0,k)

    # Look for summations that are equal to n value, which will occur for
    # n consecutive 0s. Remember that we are using a "full" version of
    # convolution, so there's one-off offsetting because of the way kernel
    # slides across input data. Also, we need to create 1s at places where
    # n consective 0s end, so we would need to slice out ending elements.
    # Thus, we would end up with the following after int dtype conversion
    return (s==n).astype(int)[:-n+1]

Пробный прогон -

In [46]: a
Out[46]: array([0, 0, 0, 0, 1, 0, 0, 0, 1, 1])

In [47]: nzeros(a,3)
Out[47]: array([0, 0, 1, 1, 0, 0, 0, 1, 0, 0])

In [48]: nzeros(a,2)
Out[48]: array([0, 1, 1, 1, 0, 0, 1, 1, 0, 0])

Подход № 2

Еще один способ решения проблемы, который можно рассматривать как вариант подхода свертки 1D, заключается в использовании erosion, потому что если вы посмотритена выходах мы можем просто разрушить маску 0s от стартов до n-1 мест.Таким образом, мы можем использовать scipy.ndimage.morphology's binary_erosion, что также позволяет нам указывать часть центра ядра с его аргументом origin, поэтому мы будем избегать нарезки.Реализация будет выглядеть примерно так -

from scipy.ndimage.morphology import binary_erosion

out = binary_erosion(a==0,np.ones(n),origin=(n-1)//2).astype(int)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...