If you are interested in the fastest execution, you know in advance which value(s) to look for, and your array is 1D, or you are otherwise interested in the result on the flattened array (in which case the input of the function should be np.flatten(arr)
rather than just arr
), then Numba is your friend:
import numba as nb
@nb.jit
def count_nb(arr, value):
result = 0
for x in arr:
if x == value:
result += 1
return result
or, for very large arrays where parallelization may be beneficial:
@nb.jit(parallel=True)
def count_nbp(arr, value):
result = 0
for i in nb.prange(arr.size):
if arr[i] == value:
result += 1
return result
Benchmarking these against np.count_nonzero()
(which also has a problem of creating a temporary array which may be avoided) and np.unique()
-based solution
import numpy as np
def count_np(arr, value):
return np.count_nonzero(arr == value)
import numpy as np
def count_np2(arr, value):
uniques, counts = np.unique(a, return_counts=True)
counter = dict(zip(uniques, counts))
return counter[value] if value in counter else 0
for input generated with:
def gen_input(n, a=0, b=100):
return np.random.randint(a, b, n)
the following plots are obtained (the second row of plots is a zoom on the faster approach):
Showing that Numba-based solution are noticeably faster than the NumPy counterparts, and, for very large inputs, the parallel approach is faster than the naive one.
Full code available here.