Skip to content Skip to sidebar Skip to footer

Find The Nearest Nonzero Element And Corresponding Index In A 2d NumPy Array

Let's say I have a 2d array named array and a 2d index:(x,y) and I want to get the nearest nonzero element to (x,y), and get the corresponding index of the element in np.nonzero(ar

Solution 1:

Approach #1 : Here's one approach -

def nearest_nonzero_idx(a,x,y):
    idx = np.argwhere(a)

    # If (x,y) itself is also non-zero, we want to avoid those, so delete that
    # But, if we are sure that (x,y) won't be non-zero, skip the next step
    idx = idx[~(idx == [x,y]).all(1)]

    return idx[((idx - [x,y])**2).sum(1).argmin()]

Sample run -

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

In [65]: x,y =(3,5)

In [66]: nearest_nonzero(a,x,y)
Out[66]: array([5, 5])

Approach #2 : Here's another approach with focus on performance that avoids the second step from previous approach of skipping the (x,y) point from the array of non-zero indices by temporarily setting the point to 0, getting those non-zero indices and then setting back the original value into it. Also, we could use np.nonzero to store the row, col indices and then perform the distance computing with those.

Thus, the implementation would be -

def nearest_nonzero_idx_v2(a,x,y):
    tmp = a[x,y]
    a[x,y] = 0
    r,c = np.nonzero(a)
    a[x,y] = tmp
    min_idx = ((r - x)**2 + (c - y)**2).argmin()
    return r[min_idx], c[min_idx]

Runtime test

In [110]: a
Out[110]: 
array([[3, 2, 3, 3, 0, 2, 4, 2, 1],
       [0, 3, 4, 3, 4, 3, 3, 2, 0],
       [1, 3, 0, 0, 0, 0, 0, 0, 0],
       [0, 1, 2, 0, 0, 2, 0, 0, 2],
       [3, 0, 0, 0, 0, 0, 0, 0, 1],
       [0, 0, 2, 2, 4, 4, 3, 4, 3],
       [2, 2, 2, 1, 0, 0, 1, 1, 1],
       [3, 4, 3, 1, 0, 4, 0, 4, 2]])

In [111]: x,y =(3,5)

In [112]: nearest_nonzero_idx(a,x,y)
Out[112]: array([1, 5])

In [113]: nearest_nonzero_idx_v2(a,x,y)
Out[113]: (1, 5)

In [114]: %timeit nearest_nonzero_idx(a,x,y)
10000 loops, best of 3: 23.1 µs per loop

In [115]: %timeit nearest_nonzero_idx_v2(a,x,y)
100000 loops, best of 3: 4.85 µs per loop

Post a Comment for "Find The Nearest Nonzero Element And Corresponding Index In A 2d NumPy Array"