How to count the number of true elements in a NumPy bool array
Asked Answered
S

6

251

I have a NumPy array 'boolarr' of boolean type. I want to count the number of elements whose values are True. Is there a NumPy or Python routine dedicated for this task? Or, do I need to iterate over the elements in my script?

Stentorian answered 3/12, 2011 at 1:13 Comment(1)
For pandas: #26054349Childlike
A
353

You have multiple options. Two options are the following.

boolarr.sum()
numpy.count_nonzero(boolarr)

Here's an example:

>>> import numpy as np
>>> boolarr = np.array([[0, 0, 1], [1, 0, 1], [1, 0, 1]], dtype=np.bool)
>>> boolarr
array([[False, False,  True],
       [ True, False,  True],
       [ True, False,  True]], dtype=bool)

>>> boolarr.sum()
5

Of course, that is a bool-specific answer. More generally, you can use numpy.count_nonzero.

>>> np.count_nonzero(boolarr)
5
Avow answered 3/12, 2011 at 1:22 Comment(9)
Thanks, David. They look neat. About the method with sum(..), is True always equal to 1 in python (or at least in numpy)? If it is not guaranteed, I will add a check, 'if True==1:' beforehand. About count_nonzero(..), unfortunately, it seems not implemented in my numpy module at version 1.5.1, but I may have a chance to use it in the future.Stentorian
@Stentorian Regarding bool: boolean values are treated as 1 and 0 in arithmetic operations. See "Boolean Values" in the Python Standard Library documentation. Note that NumPy's bool and Python bool are not the same, but they are compatible (see here for more information).Avow
@Stentorian Regarding numpy.count_nonzero not being in NumPy v1.5.1: you are right. According to this release announcement, it was added in NumPy v1.6.0.Avow
Thank you very much for the replies with the links!Stentorian
FWIW, numpy.count_nonzero is about a thousand times faster, in my Python interpreter, at least. python -m timeit -s "import numpy as np; bools = np.random.uniform(size=1000) >= 0.5" "np.count_nonzero(bools)" vs. python -m timeit -s "import numpy as np; bools = np.random.uniform(size=1000) >= 0.5" "sum(bools)"Homs
@Homs you are right. But you should compare to np.sum(bools) instead! However, np.count_nonzero(bools) is still ~12x faster.Milkmaid
If I try either of those, it works as long as my answer is non-zero. But if I get 0 and I'm doing it in a pivot table, my answer is always False.Layby
If you intend to check if there are more 1 or more elements in the array after true values have been counted, you can do this with np.any(bools)Lynx
@DavidAlber numpy.count_nonzero returns wrong results for masked array. If masked array has some mask values and all True values in other cells, it's different from np.sum(). Is it bug or expected result?Standley
I
34

That question solved a quite similar question for me and I thought I should share :

In raw python you can use sum() to count True values in a list :

>>> sum([True,True,True,False,False])
3

But this won't work :

>>> sum([[False, False, True], [True, False, True]])
TypeError...
Inflow answered 26/11, 2012 at 14:21 Comment(3)
You should "flatten" the array of arrays first. unfortunately, there's no builtin method, see #2158895Trella
Thanks Guillaume! Works with Pandas dataframes as well.Octarchy
The raw built-in sum is much slower for Pandas DataFrames and numpy arrays than their respective sum methods.Nicknack
I
5

In terms of comparing two numpy arrays and counting the number of matches (e.g. correct class prediction in machine learning), I found the below example for two dimensions useful:

import numpy as np
result = np.random.randint(3,size=(5,2)) # 5x2 random integer array
target = np.random.randint(3,size=(5,2)) # 5x2 random integer array

res = np.equal(result,target)
print result
print target
print np.sum(res[:,0])
print np.sum(res[:,1])

which can be extended to D dimensions.

The results are:

Prediction:

[[1 2]
 [2 0]
 [2 0]
 [1 2]
 [1 2]]

Target:

[[0 1]
 [1 0]
 [2 0]
 [0 0]
 [2 1]]

Count of correct prediction for D=1: 1

Count of correct prediction for D=2: 2

Intrusive answered 6/6, 2017 at 18:29 Comment(0)
S
2
b[b].size

where b is the Boolean ndarray in question. It filters b for True, and then count the length of the filtered array.

This probably isn't as efficient np.count_nonzero() mentioned previously, but is useful if you forget the other syntax. Plus, this shorter syntax saves programmer time.

Demo:

In [1]: a = np.array([0,1,3])

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

In [3]: a[a>=1].size
Out[3]: 2

In [5]: b=a>=1

In [6]: b
Out[6]: array([False,  True,  True])

In [7]: b[b].size
Out[7]: 2
Soundproof answered 13/3, 2021 at 20:39 Comment(0)
W
0
boolarr.sum(axis=1 or axis=0)

axis = 1 will output number of trues in a row and axis = 0 will count number of trues in columns so

boolarr[[true,true,true],[false,false,true]]
print(boolarr.sum(axis=1))

will be (3,1)

Wader answered 25/10, 2020 at 9:29 Comment(0)
T
0

For 1D array, this is what worked for me:

import numpy as np
numbers= np.array([3, 1, 5, 2, 5, 1, 1, 5, 1, 4, 2, 1, 4, 5, 3, 4, 
                  5, 2, 4, 2, 6, 6, 3, 6, 2, 3, 5, 6, 5])

numbersGreaterThan2= np.count_nonzero(numbers> 2)
Tabular answered 30/3, 2022 at 14:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.