简体   繁体   中英

How to get indices of elements below 'a diagonal' in numpy array

The title is a bit misleading, I hope it will be clear from the picture and description. I have an array (or arrays) of 0s and 1s where the ones form a kind of a diagonal in the array/matrix as seen on the following figure.

在此处输入图片说明

I would like to get to know the indices of the elements with a value of 0 below this 'diagonal'. How can I do that? The diagonal is not necessarily a diagonal (as seen), however, it is continuous and intercepts (ie there is always a separation between the upper and lower triangle). I have been thinking of some smart mask but since the zeros up and down are the same zeros and there is not necessarily a clear threshold (eg above 1 in columns), I couldn't solve it.

An example array is this:

example = np.array(
      [[0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 1., 1.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 1., 1., 1.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 1., 1., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 1., 1., 1., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 1., 1., 1., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 1., 1., 1., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 1., 1., 1., 1., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 1., 1., 1., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 1., 1., 1., 1., 1., 0., 0., 0., 0., 0., 0., 0.],
       [0., 1., 1., 1., 1., 1., 0., 0., 0., 0., 0., 0., 0., 0.],
       [1., 1., 1., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [1., 1., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [1., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]])

This would yield indices like:

[ 2, 12],
[ 2, 13],
[ 3, 11],
[ 3, 12],
[ 3, 13],
...
[13,  1],
[13,  2],
[13,  3],
[13,  4],
[13,  5],
..
[13, 12],
[13, 13]

Thanks.

You can use np.cumsum to add up the values going along the row to that point; you want the indices where your array is equal to zero but the cumulative sum going along the row is greater than zero.

np.argwhere((example == 0) & (np.cumsum(example,axis=1) > 0))

giving:

array([[ 2, 12],
       [ 2, 13],
       [ 3, 11],
       [ 3, 12],
       [ 3, 13],
...etc...

Note also that accumulating down a column would work equally (but may be marginally more expensive for a large array, in terms of efficiency of memory access). This would use axis=0 instead of axis=1 .

One way using scipy.ndimage.label :

conn = [[0,1,0], [1,1,1], [0,1,0]]
arr, _ = label(1-example, conn)

This will automatically label the flipped ones, considering all the connected non-zeros (calculated using conn ) as a single label. Note that conn is a cross-like array; non-zeros are considered as a whole if they are adjacent by up-down and left-right, but not diagonally.:

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

Then you can find the second label (ie lower triangle-like)

np.argwhere(arr==2)

Output:

array([[ 2, 12],
       [ 2, 13],
       [ 3, 11],
       ...
       [13, 11],
       [13, 12],
       [13, 13]], dtype=int64)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM