Lowest initial row indices for at least 2 consecutive non-zero values ​​per column

Given the sample matrix:

A =
     0     0     0     0    -4     3
     0     2     1     0     0     0
     0     5     0     8     7     0
     0     9    10     3     1     2

      

I want to find the smallest starting locations (row indices) for each column A

where at least two consecutive non-zero values ​​are found. The result will look like this:

Output = [0, 2, 0, 3, 3, 0]

      

0

the output indicates that the condition minimum 2 consecutive non-zero values

does not hold.

Also, can this be generalized to the case of finding the initial indices of the minimum N

consecutive nonzero values?

+3


source to share


1 answer


At least 2 consecutive non-zero case values

%// Mask of non-zeros in input, A
mask = A~=0

%// Find starting row indices alongwith boolean valid flags for minimum two 
%// consecutive nonzeros in each column
[valid,idx] = max(mask(1:end-1,:) & mask(2:end,:),[],1)

%// Use the valid flags to set invalid row indices to zeros
out = idx.*valid

      

Example run -

A =
     0     0     0     0    -4     3
     0     2     1     0     0     0
     0     5     0     8     7     0
     0     9    10     3     1     2
mask =
     0     0     0     0     1     1
     0     1     1     0     0     0
     0     1     0     1     1     0
     0     1     1     1     1     1
valid =
     0     1     0     1     1     0
idx =
     1     2     1     3     3     1
out =
     0     2     0     3     3     0

      


General case



For the general case, the minimum N sequential case without zero can be used 2D convolution

with kernel as column vectors, e.g N

.:

mask = A~=0  %// Mask of non-zeros in input, A

%// Find starting row indices alongwith boolean valid flags for minimum N 
%// consecutive nonzeros in each column
[valid,idx] = max(conv2(double(mask),ones(N,1),'valid')==N,[],1)

%// Use the valid flags to set invalid row indices to zeros
out = idx.*valid

      

Note that the 2D convolution can be replaced with a split version of the convolution as pointed out in Luis's comments, and it seems to be a little faster. More information on this can be obtained on this link

. So,

conv2(double(mask),ones(N,1),'valid')

can be replaced with conv2(ones(N,1),1,double(mask),'valid')

.

Example run -

A =
     0     0     0     0     0     3
     0     2     1     0     1     2
     0     5     0     8     7     9
     0     9     0     3     1     2
mask =
     0     0     0     0     0     1
     0     1     1     0     1     1
     0     1     0     1     1     1
     0     1     0     1     1     1
N =
     3
valid =
     0     1     0     0     1     1
idx =
     1     2     1     1     2     1
out =
     0     2     0     0     2     1

      

+4


source







All Articles