Відповіді:
Якщо ваш список містить усі негативні вставки, слід переглянути numpy.bincounts:
http://docs.scipy.org/doc/numpy/reference/generated/numpy.bincount.html
а потім, ймовірно, використовувати np.argmax:
a = np.array([1,2,3,1,2,1,1,1,3,2,2,1])
counts = np.bincount(a)
print(np.argmax(counts))
Для більш складного списку (який, можливо, містить від’ємні числа чи не цілі значення), ви можете використовувати np.histogram
аналогічним чином. Крім того, якщо ви просто хочете працювати в python, не використовуючи numpy, collections.Counter
це хороший спосіб обробки такого роду даних.
from collections import Counter
a = [1,2,3,1,2,1,1,1,3,2,2,1]
b = Counter(a)
print(b.most_common(1))
scipy.stats.mode
, хоча і менш загальне.
Counter(array).most_common(1)[0][0]
Ви можете використовувати
(values,counts) = np.unique(a,return_counts=True)
ind=np.argmax(counts)
print values[ind] # prints the most frequent element
Якщо якийсь елемент настільки ж частий, як інший, цей код поверне лише перший елемент.
values[counts.argmax()]
повернемо перше значення. Щоб отримати їх усі, ми можемо використати values[counts == counts.max()]
.
>>> # small array
>>> a = [12,3,65,33,12,3,123,888000]
>>>
>>> import collections
>>> collections.Counter(a).most_common()[0][0]
3
>>> %timeit collections.Counter(a).most_common()[0][0]
100000 loops, best of 3: 11.3 µs per loop
>>>
>>> import numpy
>>> numpy.bincount(a).argmax()
3
>>> %timeit numpy.bincount(a).argmax()
100 loops, best of 3: 2.84 ms per loop
>>>
>>> import scipy.stats
>>> scipy.stats.mode(a)[0][0]
3.0
>>> %timeit scipy.stats.mode(a)[0][0]
10000 loops, best of 3: 172 µs per loop
>>>
>>> from collections import defaultdict
>>> def jjc(l):
... d = defaultdict(int)
... for i in a:
... d[i] += 1
... return sorted(d.iteritems(), key=lambda x: x[1], reverse=True)[0]
...
>>> jjc(a)[0]
3
>>> %timeit jjc(a)[0]
100000 loops, best of 3: 5.58 µs per loop
>>>
>>> max(map(lambda val: (a.count(val), val), set(a)))[1]
12
>>> %timeit max(map(lambda val: (a.count(val), val), set(a)))[1]
100000 loops, best of 3: 4.11 µs per loop
>>>
Найкраще - "max" з "set" для невеликих масивів, як проблема.
За даними @David Sanders, якщо збільшити розмір масиву до приблизно 100 000 елементів, алгоритм "max w / set" в кінцевому підсумку стає найгіршим, тоді як метод "numpy bincount" є найкращим.
a = (np.random.rand(100000) * 1000).round().astype('int'); a_list = list(a)
), ваш алгоритм "макс. Ш / набір" в кінцевому підсумку стає найгіршим, тоді як метод "нумерований рахунок" є найкращим. Я провів цей тест, використовуючи a_list
нативний код python та a
numpy код, щоб уникнути витрат на марширування та накручування результатів.
Крім того, якщо ви хочете отримати найчастіше значення (позитивне або негативне), не завантажуючи жодних модулів, ви можете використовувати наступний код:
lVals = [1,2,3,1,2,1,1,1,3,2,2,1]
print max(map(lambda val: (lVals.count(val), val), set(lVals)))
max(set(lVals), key=lVals.count)
, який рахує O (n) для кожного унікального елемента lVals
приблизно для O (n ^ 2) (якщо вважати O (n) унікальним елементи). Використання collections.Counter(lVals).most_common(1)[0][0]
зі стандартної бібліотеки, як це запропонував JoshAdel , є лише O (n).
Хоча більшість наведених вище відповідей корисні, якщо вам: 1) це потрібно для підтримки непозитивних цілих значень (наприклад, поплавці чи від'ємні цілі числа ;-)), і 2) не знаходяться на Python 2.7 (який колекції.Counter 3) воліють не додавати залежність scipy (або навіть numpy) до вашого коду, тоді суто рішення python 2.6, яке є O (nlogn) (тобто ефективним), це саме це:
from collections import defaultdict
a = [1,2,3,1,2,1,1,1,3,2,2,1]
d = defaultdict(int)
for i in a:
d[i] += 1
most_frequent = sorted(d.iteritems(), key=lambda x: x[1], reverse=True)[0]
Розширюючи цей метод , застосовується для пошуку режиму даних, де, можливо, знадобиться індекс фактичного масиву, щоб побачити, наскільки далеко знаходиться значення від центру розподілу.
(_, idx, counts) = np.unique(a, return_index=True, return_counts=True)
index = idx[np.argmax(counts)]
mode = a[index]
Не забудьте відмовитись від режиму, коли len (np.argmax (counts))> 1
У Python 3 слід працювати:
max(set(a), key=lambda x: a.count(x))
Починаючи з Python 3.4
, стандартна бібліотека включає statistics.mode
функцію повернення єдиної найпоширенішої точки даних.
from statistics import mode
mode([1, 2, 3, 1, 2, 1, 1, 1, 3, 2, 2, 1])
# 1
Якщо є кілька режимів з однаковою частотою, statistics.mode
повертається перший, що виник.
Починаючи з цього Python 3.8
, statistics.multimode
функція повертає список найбільш часто зустрічаються значень у тому порядку, в якому вони вперше зустрічалися:
from statistics import multimode
multimode([1, 2, 3, 1, 2])
# [1, 2]
Ось загальне рішення, яке можна застосувати уздовж осі, незалежно від значень, використовуючи чисто нумеровані. Я також виявив, що це набагато швидше, ніж scipy.stats.mode, якщо існує багато унікальних значень.
import numpy
def mode(ndarray, axis=0):
# Check inputs
ndarray = numpy.asarray(ndarray)
ndim = ndarray.ndim
if ndarray.size == 1:
return (ndarray[0], 1)
elif ndarray.size == 0:
raise Exception('Cannot compute mode on empty array')
try:
axis = range(ndarray.ndim)[axis]
except:
raise Exception('Axis "{}" incompatible with the {}-dimension array'.format(axis, ndim))
# If array is 1-D and numpy version is > 1.9 numpy.unique will suffice
if all([ndim == 1,
int(numpy.__version__.split('.')[0]) >= 1,
int(numpy.__version__.split('.')[1]) >= 9]):
modals, counts = numpy.unique(ndarray, return_counts=True)
index = numpy.argmax(counts)
return modals[index], counts[index]
# Sort array
sort = numpy.sort(ndarray, axis=axis)
# Create array to transpose along the axis and get padding shape
transpose = numpy.roll(numpy.arange(ndim)[::-1], axis)
shape = list(sort.shape)
shape[axis] = 1
# Create a boolean array along strides of unique values
strides = numpy.concatenate([numpy.zeros(shape=shape, dtype='bool'),
numpy.diff(sort, axis=axis) == 0,
numpy.zeros(shape=shape, dtype='bool')],
axis=axis).transpose(transpose).ravel()
# Count the stride lengths
counts = numpy.cumsum(strides)
counts[~strides] = numpy.concatenate([[0], numpy.diff(counts[~strides])])
counts[strides] = 0
# Get shape of padded counts and slice to return to the original shape
shape = numpy.array(sort.shape)
shape[axis] += 1
shape = shape[transpose]
slices = [slice(None)] * ndim
slices[axis] = slice(1, None)
# Reshape and compute final counts
counts = counts.reshape(shape).transpose(transpose)[slices] + 1
# Find maximum counts and return modals/counts
slices = [slice(None, i) for i in sort.shape]
del slices[axis]
index = numpy.ogrid[slices]
index.insert(axis, numpy.argmax(counts, axis=axis))
return sort[index], counts[index]
Нещодавно я займаюся проектом і використовую колекції.Counter. (Що мене мучило).
Лічильник колекцій на мою думку має дуже погані показники. Це просто клас обгортки ().
Що ще гірше, якщо ви використовуєте cProfile для профілю свого методу, ви повинні побачити багато "__missing__" і "__instancheck__" матеріалів, що витрачають весь час.
Будьте обережні, використовуючи його most_common (), оскільки кожного разу він викликає такий вид, який робить його надзвичайно повільним. і якщо ви використовуєте most_common (x), він викликатиме сортування купи, що також повільно.
Btw, рахунок рахунку numpy також має проблему: якщо ви використовуєте np.bincount ([1,2400000000]), ви отримаєте масив з 4000000 елементів.
np.bincount([1, 2, 3, 1, 2, 1, 1, 1, 3, 2, 2, 1]).argmax()