Старе питання, але я хотів би запропонувати власне рішення, яке виявиться найшвидшим, використовувати звичайне, listа не np.arrayяк вхідне (або перенести до списку спочатку), грунтуючись на моєму тестуванні.
Перевірте це, якщо ви також зіткнулися.
def count(a):
results = {}
for x in a:
if x not in results:
results[x] = 1
else:
results[x] += 1
return results
Наприклад,
>>>timeit count([1,1,1,2,2,2,5,25,1,1]) would return:
100000 петель, найкраще 3: 2,26 мкс на цикл
>>>timeit count(np.array([1,1,1,2,2,2,5,25,1,1]))
100000 петель, найкраще 3: 8,8 мкс на цикл
>>>timeit count(np.array([1,1,1,2,2,2,5,25,1,1]).tolist())
100000 петель, найкраще 3: 5,85 мкс на цикл
Хоча прийнята відповідь була б повільнішою, а scipy.stats.itemfreqрішення - ще гіршою.
Більш поглиблене тестування не підтвердило сформульоване очікування.
from zmq import Stopwatch
aZmqSTOPWATCH = Stopwatch()
aDataSETasARRAY = ( 100 * abs( np.random.randn( 150000 ) ) ).astype( np.int )
aDataSETasLIST = aDataSETasARRAY.tolist()
import numba
@numba.jit
def numba_bincount( anObject ):
np.bincount( anObject )
return
aZmqSTOPWATCH.start();np.bincount( aDataSETasARRAY );aZmqSTOPWATCH.stop()
14328L
aZmqSTOPWATCH.start();numba_bincount( aDataSETasARRAY );aZmqSTOPWATCH.stop()
592L
aZmqSTOPWATCH.start();count( aDataSETasLIST );aZmqSTOPWATCH.stop()
148609L
Реф. коментарі нижче щодо кешу та інших побічних ефектів в ОЗУ, які впливають на невеликий набір даних, які масово повторюються результати тестування.
collections.Counter(x)достатньо?