it-swarm.com.de

Finde die häufigste Zahl in einem numpy-Vektor

Angenommen, ich habe die folgende Liste in Python: 

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

Wie kann ich die häufigste Nummer in dieser Liste ordentlich finden?

84
JustInTime

Wenn Ihre Liste alle nicht negativen Ints enthält, sollten Sie sich numpy.bincounts ansehen:

http://docs.scipy.org/doc/numpy/reference/generated/numpy.bincount.html

und dann wahrscheinlich np.argmax verwenden:

a = np.array([1,2,3,1,2,1,1,1,3,2,2,1])
counts = np.bincount(a)
print np.argmax(counts)

Für eine kompliziertere Liste (die möglicherweise negative Zahlen oder nicht ganzzahlige Werte enthält) können Sie np.histogram auf ähnliche Weise verwenden. Wenn Sie nur mit Python arbeiten möchten, ohne Numpy zu verwenden, ist collections.Counter eine gute Möglichkeit, diese Art von Daten zu behandeln.

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)
150
JoshAdel

Sie können verwenden

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

Wenn ein Element so häufig ist wie ein anderes, gibt dieser Code nur das erste Element zurück.

56
Apogentus

Wenn Sie bereit sind, SciPy zu verwenden:

>>> 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
31
Fred Foo

Leistungen (mit iPython) für einige Lösungen, die hier zu finden sind:

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

Am besten ist 'Max' mit 'Set' 

20
iuridiniz

Während die meisten der obigen Antworten nützlich sind, sollten Sie: 1) nicht-positive Ganzzahlwerte (z. B. Gleitkommazahlen oder negative Ganzzahlen ;-)) und 2) nicht auf Python verwenden 2.7 (welche Collections.Counter erfordert) und 3) ziehen Sie es vor, die Abhängigkeit von scipy (oder gar numpy) nicht zu Ihrem Code hinzuzufügen, dann eine reine Python 2.6-Lösung, die O(nlogn) ist (dh effizient) ist genau das:

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]
2
JJC

Wenn Sie den häufigsten Wert (positiv oder negativ) erhalten möchten, ohne Module zu laden, können Sie den folgenden Code verwenden:

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

Ich mag die Lösung von JoshAdel.

Aber es gibt nur einen Haken. 

Die np.bincount()-Lösung funktioniert nur für Zahlen.

Wenn Sie über Strings verfügen, funktioniert collections.Counter solution für Sie.

1
Vikas

Erweiterung auf diese Methode , angewendet auf das Finden des Modus der Daten, in dem Sie möglicherweise den Index des tatsächlichen Arrays benötigen, um zu sehen, wie weit der Wert vom Verteilungszentrum entfernt ist. 

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

Denken Sie daran, den Modus zu verwerfen, wenn len (np.argmax (counts))> 1 ist

1
Lean Bravo

In Python 3 sollte Folgendes funktionieren:

max(set(a), key=lambda x: a.count(x))
1
Yury Kliachko

Hier ist eine allgemeine Lösung, die unabhängig von den Werten entlang einer Achse angewendet werden kann, indem rein numpy verwendet wird. Ich habe auch festgestellt, dass dies viel schneller ist als scipy.stats.mode, wenn es viele eindeutige Werte gibt.

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]
0
Devin Cairns