Подтвердить что ты не робот

Найдите наиболее частое число в векторе numpy

Предположим, что у меня есть следующий список в python:

a = [1,2,3,1,2,1,1,1,3,2,2,1]

Как найти наиболее частое число в этом списке аккуратным способом?

4b9b3361

Ответ 1

Если ваш список содержит все неотрицательные ints, вы должны взглянуть на 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)

Ответ 2

Вы можете использовать

(values,counts) = np.unique(a,return_counts=True)
ind=np.argmax(counts)
print values[ind]  # prints the most frequent element

Если какой-то элемент является таким же частым, как и другой, этот код вернет только первый элемент.

Ответ 3

Если вы хотите использовать SciPy:

>>> from scipy.stats import mode
>>> mode([1,2,3,1,2,1,1,1,3,2,2,1])
(array([ 1.]), array([ 6.]))
>>> most_frequent = mode([1,2,3,1,2,1,1,1,3,2,2,1])[0][0]
>>> most_frequent
1.0

Ответ 4

Выступления (используя iPython) для некоторых решений, найденных здесь:

>>> # 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'

Ответ 5

Также, если вы хотите получить наиболее частое значение (положительное или отрицательное) без загрузки каких-либо модулей, вы можете использовать следующий код:

lVals = [1,2,3,1,2,1,1,1,3,2,2,1]
print max(map(lambda val: (lVals.count(val), val), set(lVals)))

Ответ 6

Хотя большинство приведенных выше ответов полезны, в случае, если вы: 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]

Ответ 7

Мне нравится решение JoshAdel.

Но есть только один улов.

Решение np.bincount() работает только с числами.

Если у вас есть строки, решение collections.Counter будет работать для вас.

Ответ 8

Расширение на этот метод, применяемый для поиска режима данных, где вам может понадобиться индекс фактического массива, чтобы увидеть, как далеко это значение от центр распространения.

(_, idx, counts) = np.unique(a, return_index=True, return_counts=True)
index = idx[np.argmax(counts)]
mode = a[index]

Не забывайте отменить режим, когда len (np.argmax(counts)) > 1

Ответ 9

Вот общее решение, которое может применяться вдоль оси, независимо от значений, используя чисто numpy. Я также обнаружил, что это намного быстрее, чем 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]

Ответ 10

В Python 3 должно работать следующее:

max(set(li), key=lambda x: li.count(x))

Ответ 11

Недавно я делал проект и использовал коллекции. Каунтер. (Который мучил меня).

Счетчик в коллекциях имеет очень плохую производительность, на мой взгляд. Это просто класс wrapping dict().

Чем хуже, если вы используете cProfile для профайла его метода, вы должны увидеть много вещей __missing__ и '__instancecheck__', которые все время тратятся впустую.

Будьте осторожны, используя его most_common(), потому что каждый раз он вызывает тип, который делает его чрезвычайно медленным. и если вы используете most_common (x), он будет вызывать сортировку кучи, которая также замедляется.

Btw, numpy bincount также имеет проблему: если вы используете np.bincount([1,2,4000000]), вы получите массив с 4000000 элементами.