सबसे अधिक संख्या में लगातार संख्या खोजें


123

मान लीजिए कि मेरे पास अजगर में निम्नलिखित सूची है:

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

इस सूची में सबसे स्वच्छ तरीके से सबसे अधिक संख्या कैसे प्राप्त करें?

जवाबों:


193

यदि आपकी सूची में सभी गैर-नकारात्मक स्याही हैं, तो आपको 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एक समान तरीके से उपयोग कर सकते हैं । वैकल्पिक रूप से, यदि आप केवल सुन्नता का उपयोग किए बिना अजगर में काम करना चाहते हैं, तो 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))

58
+1। बस हो सकता हैnp.bincount([1, 2, 3, 1, 2, 1, 1, 1, 3, 2, 2, 1]).argmax()
निकोलाई Fetissov

1
+1। यह कम से कम परिमाण का क्रम है scipy.stats.mode, हालांकि कम सामान्य है।
फ्रेड फू

अच्छा उत्तर! हालाँकि, अगर कोई अजगर 2.6 पर है, तो संग्रह। मुठभेड़ उपलब्ध नहीं है। उस स्थिति में, मेरा जवाब नीचे देखें।
JJC

19
हममें से 2016 के बाद आने वाले लोगों के लिए: मैं इस जवाब को नापसंद करता हूं, क्योंकि बींकाउंट (गिरफ्तारी) एक सरणी देता है जो गिरफ्तारी के सबसे बड़े तत्व के रूप में बड़ा होता है, इसलिए एक बड़ी श्रेणी के साथ एक छोटा सरणी एक अत्यधिक बड़े सरणी का निर्माण करेगा। नीचे Apoengtus का उत्तर बहुत बेहतर है, हालांकि मुझे नहीं लगता कि 2011 में numpy.unique () मौजूद था, जब यह उत्तर बनाया गया था।
वेहर्डो

2
अजगर 3 :Counter(array).most_common(1)[0][0]
दिरलिक

80

तुम उपयोग कर सकते हो

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

यदि कुछ तत्व एक दूसरे के रूप में लगातार होता है, तो यह कोड केवल पहला तत्व वापस करेगा।


4
मुझे यह सबसे उपयोगी लगता है क्योंकि यह सामान्य, संक्षिप्त है और कुछ व्युत्पन्न सूचकांक द्वारा मूल्यों या गणना से तत्वों को खींचने की अनुमति देता है।
ryanjdillon

2
यदि हमारे पास कई सबसे अधिक मूल्य हैं, values[counts.argmax()]तो पहला मान वापस आएगा। उन सभी को प्राप्त करने के लिए, हम उपयोग कर सकते हैं values[counts == counts.max()]
डब्ल्यू। झू

44

यदि आप 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

30

यहाँ पाए गए कुछ समाधानों के लिए प्रदर्शन (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
>>> 

समस्या जैसी छोटी सरणियों के लिए 'सेट' के साथ 'अधिकतम' है।

@ डेविड सैंडर्स के अनुसार, यदि आप सरणी का आकार 100,000 तत्वों की तरह बढ़ाते हैं, तो "अधिकतम w / सेट" एल्गोरिथ्म दूर तक सबसे खराब होता है जबकि "सुन्न bincount" विधि सबसे अच्छा है।


1
आदेश का सबसे अच्छा तरीका है कि हम कई मामलों के खिलाफ यह परीक्षण की आवश्यकता बात करने के लिए में @IuliusCurt: छोटे सरणियों, बड़े सरणियों, यादृच्छिक सरणियों, असली दुनिया सरणियों (जैसे timsort छँटाई के लिए करता है), ... लेकिन मैं आपसे सहमत हूँ
iuridiniz

3
अपने दृष्टिकोण के अनुसार, केवल एक छोटे से सरणी का उपयोग करना, अलग-अलग एल्गोरिदम के बीच बहुत अच्छी तरह से भेद करने वाला नहीं है।
डेविड सैंडर्स

10
यदि आप परीक्षण सूची आकार को 100000 ( a = (np.random.rand(100000) * 1000).round().astype('int'); a_list = list(a)) तक बढ़ाते हैं , तो आपका "अधिकतम w / सेट" एल्गोरिथ्म दूर तक सबसे खराब होता है जबकि "सुन्न bincount" विधि सबसे अच्छा है। मैंने a_listमूल अजगर कोड के लिए और aखस्ता कोड से बचने के लिए इस परीक्षण का उपयोग किया , ताकि परिणामों को खराब करने वाले मार्शलों से बचा जा सके।
डेविड सैंडर्स

4

यदि आप किसी भी मॉड्यूल को लोड किए बिना सबसे अधिक मूल्य (सकारात्मक या नकारात्मक) प्राप्त करना चाहते हैं, तो आप निम्नलिखित कोड का उपयोग कर सकते हैं:

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

1
यह कुछ समय पहले से है, लेकिन पश्चात के लिए: यह आसानी से पढ़े जाने के बराबर है max(set(lVals), key=lVals.count), जो lValsलगभग O (n ^ 2) (संभालने वाले O (n) अद्वितीय के प्रत्येक अद्वितीय तत्व के लिए एक O (n) गणना करता है तत्व)। जोश एडेल द्वारा सुझाए गएcollections.Counter(lVals).most_common(1)[0][0] मानक पुस्तकालय से उपयोग करना केवल ओ (एन) है।
डोगल

3

जबकि ऊपर दिए गए अधिकांश उत्तर आपके लिए उपयोगी हैं, यदि आप: 1) को गैर-सकारात्मक-पूर्णांक मानों (जैसे फ़्लोट्स या नकारात्मक पूर्णांक ;-)) का समर्थन करने की आवश्यकता है, और पायथन 2.7 (जो संग्रह में उपलब्ध नहीं हैं) आवश्यकता होती है), और 3) अपने कोड में scipy (या यहां तक ​​कि सुन्न) की निर्भरता को जोड़ने के लिए नहीं पसंद करते हैं, तो एक शुद्ध रूप से अजगर 2.6 समाधान है कि हे (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]

2

मुझे जोश एडेल द्वारा समाधान पसंद है।

लेकिन सिर्फ एक कैच है।

np.bincount()समाधान केवल नंबरों पर काम करता है।

यदि आपके पास तार हैं, तो collections.Counterसमाधान आपके लिए काम करेगा।


1

इस पद्धति पर विस्तार करते हुए , डेटा के मोड को खोजने के लिए आवेदन किया जाता है, जहां आपको वितरण के केंद्र से मूल्य कितनी दूर है यह देखने के लिए वास्तविक सरणी के सूचकांक की आवश्यकता हो सकती है।

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

जब len (np.argmax (मायने रखता है))> 1 मोड को त्यागना याद रखें



1

में शुरू 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]

0

यहां एक सामान्य समाधान है जिसे अक्ष के साथ लागू किया जा सकता है, मूल्यों की परवाह किए बिना, विशुद्ध रूप से सुन्न का उपयोग करके। मैंने यह भी पाया है कि यह 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]

-1

मैं हाल ही में एक परियोजना कर रहा हूं और संग्रह का उपयोग कर रहा हूं। मुठभेड़ (जो मुझे अत्याचार करता है)।

काउंटर इन कलेक्शन का मेरी राय में बहुत खराब प्रदर्शन है। यह सिर्फ तानाशाही को लपेटने वाला वर्ग है ()।

क्या बुरा है, यदि आप इसकी विधि को प्रोफाइल करने के लिए cProfile का उपयोग करते हैं, तो आपको पूरे समय को बर्बाद करते हुए बहुत सारे '__missing__' और '__instancecheck__' सामान देखने चाहिए।

इसका सबसे अधिक उपयोग करें सावधान रहें (), क्योंकि हर बार यह एक प्रकार का आह्वान करेगा जो इसे बेहद धीमा बनाता है। और यदि आप most_common (x) का उपयोग करते हैं, तो यह एक ढेर प्रकार का आह्वान करेगा, जो धीमा भी है।

Btw, numpy के बिंकाउंट में भी एक समस्या है: यदि आप np.bincount ([1,2,4000000]) का उपयोग करते हैं, तो आपको 4000000 तत्वों के साथ एक सरणी मिलेगी।


3
पाइथन में एक तानाशाह सबसे बारीक-ट्यून डेटा संरचना है और मनमानी वस्तुओं की गिनती के लिए आदर्श है। इसके विपरीत, बिनिंग केवल संख्यात्मक मानों पर काम करता है और आपको बारीकी से अंतरित असतत मूल्यों के बीच के संबंध को रोकने नहीं देता है। काउंटर के मामले में, __missing__ विधि केवल तब कहा जाता है जब कोई तत्व पहली बार देखा जाता है; अन्यथा, इसकी उपस्थिति लागत रहित है। ध्यान दें, अधिकांश मामलों में most_common () विधि बहुत तेज़ी से चल रही है क्योंकि कुल डेटासेट की तुलना में ढेर बहुत छोटा है। ज्यादातर मामलों में, सबसे अधिक () विधि मिनट () की तुलना में केवल थोड़ी अधिक तुलना करती है ।
रेमंड हेटिंगर 21
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.