85

Is there an efficient Numpy mechanism to retrieve the integer indexes of locations in an array based on a condition is true as opposed to the Boolean mask array?

For example:

x=np.array([range(100,1,-1)])
#generate a mask to find all values that are a power of 2
mask=x&(x-1)==0
#This will tell me those values
print x[mask]

In this case, I'd like to know the indexes i of mask where mask[i]==True. Is it possible to generate these without looping?

Rich
  • 12,068
  • 9
  • 62
  • 94

4 Answers4

109

Another option:

In [13]: numpy.where(mask)
Out[13]: (array([36, 68, 84, 92, 96, 98]),)

which is the same thing as numpy.where(mask==True).

Steve Tjoa
  • 59,122
  • 18
  • 90
  • 101
37

You should be able to use numpy.nonzero() to find this information.

aganders3
  • 5,838
  • 26
  • 30
  • 1
    use numpy.nonzero()[0] otherwise you get two arrays. One with indices and one with values. If you want to use the indices to continue, this is easier. It only gives you an array with the indices. – Florida Man Jul 12 '16 at 08:22
  • 6
    @FloridaMan: `numpy.nonzero` does not give a tuple with an array of values as the second component. The tuple is used in case the Boolean array is multidimensional. From the docs: “Returns a tuple of arrays, one for each dimension […]”. – equaeghe Feb 21 '19 at 21:25
2
np.arange(100,1,-1)
array([100,  99,  98,  97,  96,  95,  94,  93,  92,  91,  90,  89,  88,
        87,  86,  85,  84,  83,  82,  81,  80,  79,  78,  77,  76,  75,
        74,  73,  72,  71,  70,  69,  68,  67,  66,  65,  64,  63,  62,
        61,  60,  59,  58,  57,  56,  55,  54,  53,  52,  51,  50,  49,
        48,  47,  46,  45,  44,  43,  42,  41,  40,  39,  38,  37,  36,
        35,  34,  33,  32,  31,  30,  29,  28,  27,  26,  25,  24,  23,
        22,  21,  20,  19,  18,  17,  16,  15,  14,  13,  12,  11,  10,
         9,   8,   7,   6,   5,   4,   3,   2])

x=np.arange(100,1,-1)

np.where(x&(x-1) == 0)
(array([36, 68, 84, 92, 96, 98]),)

Now rephrase this like :

x[x&(x-1) == 0]
Mad Physicist
  • 107,652
  • 25
  • 181
  • 264
user2290820
  • 2,709
  • 5
  • 34
  • 62
2

If you prefer the indexer way, you can convert your boolean list to numpy array:

print x[nd.array(mask)]
Serhiy
  • 4,357
  • 5
  • 37
  • 53