How to find index of minimum non zero element with numpy?

Question:

I have a 4×1 array that I want to search for the minimum non zero value and find its index. For example:

theta = array([0,1,2,3]).reshape(4,1)

It was suggested in a similar thread to use nonzero() or where(), but when I tried to use that in the way that was suggested, it creates a new array that doesn’t have the same indices as the original:

np.argmin(theta[np.nonzero(theta)])

gives an index of zero, which clearly isn’t right. I think this is because it creates a new array of non zero elements first. I am only interested in the first minimum value if there are duplicates.

Asked By: Emily

||

Answers:

np.nonzero(theta) returns the index of the values that are non-zero. In your case, it returns,

[1,2,3]

Then, theta[np.nonzero(theta)] returns the values

[1,2,3]

When you do np.argmin(theta[np.nonzero(theta)]) on the previous output, it returns the index of the value 1 which is 0.

Hence, the correct approach would be:

i,j = np.where( theta==np.min(theta[np.nonzero(theta)])) where i,j are the indices of the minimum non zero element of the original numpy array

theta[i,j] or theta[i] gives the respective value at that index.

Answered By: Sriram Sitharaman

I think you @Emily were very close to the correct answer. You said:

np.argmin(theta[np.nonzero(theta)]) gives an index of zero, which clearly isn’t right. I think this is because it creates a new array of non zero elements first.

The last sentence is correct => the first one is wrong since it is expected to give the index in the new array.

Let’s now extract the correct index in the old (original) array:

nztheta_ind = np.nonzero(theta)
k = np.argmin(theta[nztheta_ind])
i = nztheta_ind[0][k]
j = nztheta_ind[1][k]

or:

[i[k] for i in nztheta_ind]

for arbitrary dimensionality of original array.

Answered By: AGN Gazer
#!/usr/bin/env python

# Solution utilizing numpy masking of zero value in array

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

print "your array: ",a

# the non-zero minimum value
minval = np.min(ma.masked_where(a==0, a)) 
print "non-zero minimum: ",minval

# the position/index of non-zero  minimum value in the array
minvalpos = np.argmin(ma.masked_where(a==0, a))  
print "index of non-zero minimum: ", minvalpos
Answered By: Jay M.

ndim Solution

i = np.unravel_index(np.where(theta!=0, theta, theta.max()+1).argmin(), theta.shape)

Explaination

  1. Masking the zeros out creates t0. There are other ways, see the perfplot.
  2. Finding the minimum location, returns the flattened (1D) index.
  3. unravel_index fixes this problem, and hasn’t been suggested yet.
theta = np.triu(np.random.rand(4,4), 1)  # example array

t0 = np.where(theta!=0, theta, np.nan)   # 1
i0 = np.nanargmin(t0)                    # 2
i = np.unravel_index(i0, theta.shape)    # 3

print(theta, i, theta[i])                #

perfplot
mask: i = np.unravel_index(np.ma.masked_where(a==0, a).argmin(), a.shape)
nan: i = np.unravel_index(np.nanargmin(np.where(a!=0, a, np.nan)), a.shape)
max: i = np.unravel_index(np.where(a!=0, a, a.max()+1).argmin(), a.shape)

Answered By: A. West

@ Jay M, that worked for me, just putting it here if I am doing it right

 j,k = unravel_index(argmin(ma.masked_where(V==0, V)),V.shape)

V[j,k] is my 2D array.

Answered By: Ani
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.