Getting indices of an array in Python

Question:

I have a numpy array A with True, False elements. I want to print all indices which have False element. But, I am getting an error. I present the expected output:

import numpy as np

A=np.array([[False],
       [False],
       [ True],
       [False],
       [False]])

for i in range(0,len(A)):
    if (A[i]==['False']): 
        print(i)

The error is :

FutureWarning: elementwise comparison failed; returning scalar instead, but in the future will perform elementwise comparison
  if (A[i]==['False']):

The expected output is :

[0,1,3,4]
Asked By: rajunarlikar123

||

Answers:

Rather than iterating over the array, you can build an index array using np.arange, and then slice the indices using the boolean array.

np.arange(len(A))[~A.ravel()]
# returns:
array([0, 1, 3, 4])

If you want it with the same dimensionality as A, you can use np.argwhere

np.argwhere(~A.ravel())
# returns:
array([[0],
       [1],
       [3],
       [4]], dtype=int64)
Answered By: James

you are comparing list with boolean value i.e True/False with list with string value i.e ‘False’, hence you are getting the error.

Change the if condition as follows (i.e. without quotation marks for False):

if (A[i] == [False])

Answered By: Jaydeep Jethwa

You can also use np.where:

A=np.array([[False],
            [False],
            [ True],
            [False],
            [False]])
print(np.where(np.squeeze(A)==False))

Note: np.squeeze just removes the last dimension of your array.
The output is array([0, 1, 3, 4] as expected.

Answered By: Nonlinear

.nonzero()
will give you those indices.

>>> A
array([[False],
       [False],
       [ True],
       [False],
       [False]])
>>> ~A
array([[ True],
       [ True],
       [False],
       [ True],
       [ True]])
>>>
>>> (~A).nonzero()[0]
array([0, 1, 3, 4])
>>>
>>>
>>> np.flatnonzero(~A)
array([0, 1, 3, 4])
Answered By: J_H

You could get those indices in one shot using argwhere:

indices = np.argwhere(A==False)[:,0]  # extract only row indexes from output

print(indices)
# [0 1 3 4]

Using np.where with unpacking could also work:

indices,_ = np.where(A==False)

print(indices)
# [0 1 3 4]
Answered By: Alain T.

You can use list comprehension as well.

enumerate is considered more pythonic than range(len(A))

[i for i,j in enumerate(A) if A[i]==[False]] 

#[0, 1, 3, 4]
Answered By: God Is One

What’s wrong in you code?

In every iteration of your loop your arrays are of type bool, and you are trying to compare with a list(str). For Numpy to make the comparison it must cast types. But Numpy will only perform the comparison if it can safely cast dtypes (see this answer). Although Python 3 can cast bool('anything') to True, Numpy don’t find it safe. Why? I don’t know, but see how this can be funny:

>>> bool('False') == True
True

And how to make element-wise comparison using two different dtype arrays? choose one type to cast

Note that you’ll get the same warning if you: np.array(['False']) == False.

For element-wise comparison you can use np.equal(array1, array2, dtype=your_type):

>>> compare = np.array(len(A)*(('False',),))
>>> compare
array([['False'],
       ['False'],
       ['False'],
       ['False'],
       ['False']], dtype='<U5')
>>> np.equal(A, compare, dtype=bool)
UFuncTypeError: Cannot cast ufunc 'equal' input 1 from dtype('<U5') to dtype('bool') with casting rule 'same_kind'

With that it throws an error you can handle if it’d be the case.

Therefore the comparison can’t be performed since the types can’t be cast. Which can be checked using np.can_cast:

>>> np.can_cast('<U5', bool)
False

How to fix your code?

There are already so many great answers, and you can simply choose any and you’ll probably be ok. But here is my contribution in case you want to maintain a similar syntax:

for idx, element in enumerate(A):
    if not element:
        print(idx)

Here, enumerate concatenates every element of A with an counting index, and the not element will return True every time element is False.

But in case of best performance always prefer using Numpy’s functions:

>>> compare = np.array(len(A)*((False,),))
>>> np.where(np.equal(A, compare))[0]
array([0, 1, 3, 4])
Answered By: Vagner Bessa
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.