Старе питання, але я хотів би запропонувати власне рішення, яке виявиться найшвидшим, використовувати звичайне, 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)
достатньо?