10

I have a 4x1 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.

1
  • 1
    Where's that other thread? Commented Jul 10, 2017 at 2:13

4 Answers 4

15

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.

Sign up to request clarification or add additional context in comments.

5 Comments

I don't understand what the i and j do here.
theta.shape returns (4,1) because of the reshaping you did. Hence, two indices are necessary
i and j being arrays is rather ugly, though, especially since Emily said she's only interested in the first minimum value if there are duplicates. Your code results in index arrays of all occurrences.
The question asks for the index of the minimum non-zero value. However, I have updated my answer with how to get the value as well.
If i try this answer on a bigger array, say an image array, then it returns an array of indices and not just a single index of the first value found minimum. Any solution how to do that?
6
#!/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

Comments

2

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.

Comments

0

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)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.