Якщо ви зацікавлені в якнайшвидшому виконанні, ви заздалегідь знаєте, яке значення (-и) шукати, і ваш масив - 1D, або вас іншим чином цікавить результат на сплющеному масиві (у такому випадку вхід функції повинен бути, np.flatten(arr)
а не просто arr
), тоді Numba - ваш друг:
import numba as nb
@nb.jit
def count_nb(arr, value):
result = 0
for x in arr:
if x == value:
result += 1
return result
або, для дуже великих масивів, де паралелізація може бути корисною:
@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
Бенчмаркінг цих проти np.count_nonzero()
(що також має проблему створення тимчасового масиву, якого можна уникнути) та np.unique()
рішення на базі
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
для введення, генерованого за допомогою:
def gen_input(n, a=0, b=100):
return np.random.randint(a, b, n)
отримуються наступні сюжети (другий ряд сюжетів - це масштабування при більш швидкому підході):
Показано, що рішення на основі Numba помітно швидше, ніж аналоги NumPy, і для дуже великих входів паралельний підхід швидший, ніж наївний.
Повний код доступний тут .