Bir listenin modunu bulmak


126

Bir öğe listesi verildiğinde, listenin modunun en sık meydana gelen öğe olduğunu hatırlayın .

Bir listenin modunu bulabilen ancak listenin bir modu yoksa bir mesaj görüntüleyen bir işlevin nasıl oluşturulacağını bilmek istiyorum (örn. Listedeki tüm öğeler yalnızca bir kez görünür). Bu işlevi herhangi bir işlevi içe aktarmadan yapmak istiyorum. Sıfırdan kendi işlevimi yapmaya çalışıyorum.


Pardon, ama "liste modu" ile tam olarak ne demek istediğini açıklayabilir misin?
Vikas

5
@Vikas: kip (eğer varsa) en sık meydana gelen unsurdur. Bazı tanımlar, birden fazla varsa, tüm bu tür öğelerin aritmetik ortalamasını alacak şekilde genişletir.
Jeremy Roman

Burada çok fazla yanlış cevap var! Örneğin assert(mode[1, 1, 1]) == Noneve assert(mode[1, 2, 3, 4]) == None. Bir sayının a modeolması için listedeki en az bir başka sayıdan daha fazla sayıda geçmesi ve listedeki tek sayı olmaması gerekir.
lifebalance

Yanıtlar:


156

Sen kullanabilirsiniz maxfonksiyonu ve bir anahtar. 'Key' ve lambda ifadesini kullanarak python max fonksiyonuna bir göz atın .

max(set(lst), key=lst.count)

6
Ekstra ithalat gerektirmediği düşünülürse, bu OP'nin doğru cevabıdır. Aferin David
Jason Parham

12
Bana öyle geliyor ki bu işe yarayacak O(n**2). Yapar?
lirtosiast

7
Bu ikinci dereceden çalışma
zamanına

20
Sadece kullanabilirdi max(lst, key=lst.count). (Ve gerçekten bir liste aramayacağım list.)
Stefan Pochmann

2
Bunun iki modlu dağıtımlar için nasıl çalıştığını kimse açıklayabilir mi? örneğin, a = [22, 33, 11, 22, 11]; print(max(set(a), key=a.count))döner 11. Her zaman minimum modu döndürür mü? Ve eğer öyleyse, neden?
battey

99

-Esque işlevine sahip Counterolan collectionspakette modeverilenleri kullanabilirsiniz.

from collections import Counter
data = Counter(your_list_in_here)
data.most_common()   # Returns all unique items and their counts
data.most_common(1)  # Returns the highest occurring item

Not: Counter, python 2.7'de yenidir ve önceki sürümlerde mevcut değildir.


19
Soru, kullanıcının sıfırdan bir işlev yapmak istediğini belirtir - yani ithalat yok.
dbliss

3
Son satırınız, bir modu ve frekansını içeren bir demet içeren bir liste döndürür. Sadece bir mod elde etmek için kullanın Counter(your_list_in_here).most_common(1)[0][0]. Birden fazla mod varsa, bu rastgele olanı döndürür.
Rory Daulton

1
nEn yaygın olduğunu varsayalım modes. Counter (your_list_in_here) .most_common (1) [0] [0] size ilk modu getirirse, en yaygın olan birini nasıl elde edersiniz mode? Sadece sonuncu 0ile değiştirilsin 1mi? Biri modekendi beğenisine göre özelleştirmek için bir işlev yapabilir ..

1
birden fazla mod varsa, bu sayıların en büyüğünü nasıl döndürebilirim?
Akın Hwan

59

Python 3.4 yöntemi içerir statistics.mode, bu nedenle basittir:

>>> from statistics import mode
>>> mode([1, 1, 2, 3, 3, 3, 3, 4])
 3

Listede yalnızca sayısal değil, her tür öğeye sahip olabilirsiniz:

>>> mode(["red", "blue", "blue", "red", "green", "red", "red"])
 'red'

17
1 ve 3'ün eşit sayıda zamanı tekrarladığı mod ([1, 1,1,1, 2, 3, 3, 3, 3, 4]) kullanılırken hata verir. İdeal olarak, en büyük ancak eşit sayıda olan sayının en küçüğünü döndürmelidir. StatisticsError: benzersiz mod yok; eşit derecede ortak 2 değer bulundu
aman_novice

4
Bu 3.4 istatistik paketini kullanmadım, ancak scipy.stats.mode en küçük olanı döndürecektir, bu durumda 1. Bununla birlikte, bazı durumlarda hatanın atılmasını tercih ederim ...
sözcü

2
@aman_novice, sorun Python 3.8'de çözüldü. docs.python.org/3/library/statistics.html#statistics.mode
Michael D

2
python 3.8 de eklendi multimode, bu da birden fazla mod olduğunda birden fazla mod döndürür.
stason

30

Bazı istatistik yazılımlarından, yani SciPy ve MATLAB'dan bir yaprak alarak, bunlar en küçük en yaygın değeri döndürür, bu nedenle iki değer eşit sıklıkta ortaya çıkarsa, bunların en küçüğü döndürülür. Umarım bir örnek yardımcı olur:

>>> from scipy.stats import mode

>>> mode([1, 2, 3, 4, 5])
(array([ 1.]), array([ 1.]))

>>> mode([1, 2, 2, 3, 3, 4, 5])
(array([ 2.]), array([ 2.]))

>>> mode([1, 2, 2, -3, -3, 4, 5])
(array([-3.]), array([ 2.]))

Bu kongreye uymamanız için herhangi bir sebep var mı?


4
Birden çok mod varken neden yalnızca en küçük mod döndürülür?
zyxue

@zyxue simple statistical convention
chrisfs

2
@chrisfs ve birden fazla varsa en büyük modu döndürmesini sağlamak için?
Akın Hwan

25

Python'da bir liste modunu bulmanın birçok basit yolu vardır, örneğin:

import statistics
statistics.mode([1,2,3,3])
>>> 3

Veya maksimumu sayısına göre bulabilirsiniz

max(array, key = array.count)

Bu iki yöntemle ilgili sorun, birden çok modla çalışmamalarıdır. Birincisi bir hata verirken, ikincisi birinci modu döndürür.

Bir setin modlarını bulmak için şu işlevi kullanabilirsiniz:

def mode(array):
    most = max(list(map(array.count, array)))
    return list(set(filter(lambda x: array.count(x) == most, array)))

3
Modu kullanmak, iki öğe aynı sürede meydana geldiğinde hata verir.
Abhishek Mishra

Üzgünüm, bu yorumu çok geç gördüm. Statistics.mode (dizi) birden çok modda bir hata döndürür, ancak diğer yöntemlerin hiçbiri döndürmez.
mathwizurd

7

Liste boşken işe yaramayacak olan Topluluk yanıtını genişletme, işte mod için çalışma kodu:

def mode(arr):
        if arr==[]:
            return None
        else:
            return max(set(arr), key=arr.count)

3

En küçük, en büyük veya tüm modlarla ilgileniyorsanız:

def get_small_mode(numbers, out_mode):
    counts = {k:numbers.count(k) for k in set(numbers)}
    modes = sorted(dict(filter(lambda x: x[1] == max(counts.values()), counts.items())).keys())
    if out_mode=='smallest':
        return modes[0]
    elif out_mode=='largest':
        return modes[-1]
    else:
        return modes

2

Modu bulmak için bu kullanışlı işlevi yazdım.

def mode(nums):
    corresponding={}
    occurances=[]
    for i in nums:
            count = nums.count(i)
            corresponding.update({i:count})

    for i in corresponding:
            freq=corresponding[i]
            occurances.append(freq)

    maxFreq=max(occurances)

    keys=corresponding.keys()
    values=corresponding.values()

    index_v = values.index(maxFreq)
    global mode
    mode = keys[index_v]
    return mode

2
2 öğe aynı numaraya sahipse bu yöntem başarısız olacaktır. oluşumların.
akshaynagpal

2

Kısa ama bir şekilde çirkin:

def mode(arr) :
    m = max([arr.count(a) for a in arr])
    return [x for x in arr if arr.count(x) == m][0] if m>1 else None

Sözlük kullanmak, biraz daha az çirkin:

def mode(arr) :
    f = {}
    for a in arr : f[a] = f.get(a,0)+1
    m = max(f.values())
    t = [(x,f[x]) for x in f if f[x]==m]
    return m > 1 t[0][0] else None

2

Biraz daha uzun, ancak birden fazla moda sahip olabilir ve çoğu sayım veya veri türü karışımı ile dize elde edebilir.

def getmode(inplist):
    '''with list of items as input, returns mode
    '''
    dictofcounts = {}
    listofcounts = []
    for i in inplist:
        countofi = inplist.count(i) # count items for each item in list
        listofcounts.append(countofi) # add counts to list
        dictofcounts[i]=countofi # add counts and item in dict to get later
    maxcount = max(listofcounts) # get max count of items
    if maxcount ==1:
        print "There is no mode for this dataset, values occur only once"
    else:
        modelist = [] # if more than one mode, add to list to print out
        for key, item in dictofcounts.iteritems():
            if item ==maxcount: # get item from original list with most counts
                modelist.append(str(key))
        print "The mode(s) are:",' and '.join(modelist)
        return modelist 

2

Bir sayının a modeolması için listedeki en az bir başka sayıdan daha fazla sayıda geçmesi ve listedeki tek sayı olmaması gerekir. Bu yüzden, @ mathwizurd'un yanıtını ( differenceyöntemi kullanmak için ) aşağıdaki gibi yeniden düzenledim :

def mode(array):
    '''
    returns a set containing valid modes
    returns a message if no valid mode exists
      - when all numbers occur the same number of times
      - when only one number occurs in the list 
      - when no number occurs in the list 
    '''
    most = max(map(array.count, array)) if array else None
    mset = set(filter(lambda x: array.count(x) == most, array))
    return mset if set(array) - mset else "list does not have a mode!" 

Bu testler başarıyla geçmiştir:

mode([]) == None 
mode([1]) == None
mode([1, 1]) == None 
mode([1, 1, 2, 2]) == None 

1

Neden sadece

def print_mode (thelist):
  counts = {}
  for item in thelist:
    counts [item] = counts.get (item, 0) + 1
  maxcount = 0
  maxitem = None
  for k, v in counts.items ():
    if v > maxcount:
      maxitem = k
      maxcount = v
  if maxcount == 1:
    print "All values only appear once"
  elif counts.values().count (maxcount) > 1:
    print "List has multiple modes"
  else:
    print "Mode of list:", maxitem

Bu, sahip olması gereken birkaç hata kontrolüne sahip değildir, ancak modu herhangi bir işlevi içe aktarmadan bulacaktır ve tüm değerler yalnızca bir kez görünürse bir mesaj yazdıracaktır. Aynı maksimum sayıyı paylaşan birden fazla öğeyi de algılayacaktır, ancak bunu isteyip istemediğiniz net değildir.


Yani yapmaya çalıştığım şey, aynı sayımı gösteren birden fazla öğeyi algılamak ve ardından aynı sayıma sahip tüm öğeleri görüntülemek
bluelantern

Bunu gerçekten kendin denedin mi? Kodumdaki uzantı, tüm öğeleri aynı sayıya sahip yazdırması için oldukça basittir.
lxop

1

Bu işlev, kaç tane olursa olsun bir işlevin modunu veya modlarını ve ayrıca veri kümesindeki mod veya modların frekansını döndürür. Mod yoksa (yani, tüm öğeler yalnızca bir kez oluşursa), işlev bir hata dizesi döndürür. Bu, A_nagpal'ın yukarıdaki işlevine benzer, ancak benim mütevazi görüşüme göre daha eksiksiz ve bence bu soruyu okuyan herhangi bir Python acemi için (sizinki gibi) anlamak daha kolay.

 def l_mode(list_in):
    count_dict = {}
    for e in (list_in):   
        count = list_in.count(e)
        if e not in count_dict.keys():
            count_dict[e] = count
    max_count = 0 
    for key in count_dict: 
        if count_dict[key] >= max_count:
            max_count = count_dict[key]
    corr_keys = [] 
    for corr_key, count_value in count_dict.items():
        if count_dict[corr_key] == max_count:
            corr_keys.append(corr_key)
    if max_count == 1 and len(count_dict) != 1: 
        return 'There is no mode for this data set. All values occur only once.'
    else: 
        corr_keys = sorted(corr_keys)
        return corr_keys, max_count

Bunu yalnızca "işlev bir hata dizesi döndürür" dediğin için söylüyorum. Okur hattı return 'There is no mode for this data set. All values occur only once.'ile bir hata mesajı dönüştürülebilir traceback`eğer koşulu olarak: girinti ile sonraki satıra zam ValueError ( '. Orada tüm değerler sadece bir kez ortaya bu veri seti için hiçbir mod') Burada bir liste farklı türlerdeki yükseltebileceğiniz hatalar.

1

Bu, tüm modları döndürecektir:

def mode(numbers)
    largestCount = 0
    modes = []
    for x in numbers:
        if x in modes:
            continue
        count = numbers.count(x)
        if count > largestCount:
            del modes[:]
            modes.append(x)
            largestCount = count
        elif count == largestCount:
            modes.append(x)
    return modes

1

Herhangi bir içe aktarma olmadan listenin modunu bulan basit kod:

nums = #your_list_goes_here
nums.sort()
counts = dict()
for i in nums:
    counts[i] = counts.get(i, 0) + 1
mode = max(counts, key=counts.get)

Birden fazla mod olması durumunda minimum düğümü döndürmelidir.


0
def mode(inp_list):
    sort_list = sorted(inp_list)
    dict1 = {}
    for i in sort_list:        
            count = sort_list.count(i)
            if i not in dict1.keys():
                dict1[i] = count

    maximum = 0 #no. of occurences
    max_key = -1 #element having the most occurences

    for key in dict1:
        if(dict1[key]>maximum):
            maximum = dict1[key]
            max_key = key 
        elif(dict1[key]==maximum):
            if(key<max_key):
                maximum = dict1[key]
                max_key = key

    return max_key

0
def mode(data):
    lst =[]
    hgh=0
    for i in range(len(data)):
        lst.append(data.count(data[i]))
    m= max(lst)
    ml = [x for x in data if data.count(x)==m ] #to find most frequent values
    mode = []
    for x in ml: #to remove duplicates of mode
        if x not in mode:
        mode.append(x)
    return mode
print mode([1,2,2,2,2,7,7,5,5,5,5])

0

İşte bir listede oluşan ilk modu alan basit bir işlev. Liste öğelerini anahtarlar ve oluşum sayısı olarak içeren bir sözlük oluşturur ve ardından modu elde etmek için dikte değerlerini okur.

def findMode(readList):
    numCount={}
    highestNum=0
    for i in readList:
        if i in numCount.keys(): numCount[i] += 1
        else: numCount[i] = 1
    for i in numCount.keys():
        if numCount[i] > highestNum:
            highestNum=numCount[i]
            mode=i
    if highestNum != 1: print(mode)
    elif highestNum == 1: print("All elements of list appear once.")

0

Açık bir yaklaşım istiyorsanız, sınıf için yararlı ve sadece kavrayarak listeler ve sözlükler kullanıyorsanız, şunları yapabilirsiniz:

def mode(my_list):
    # Form a new list with the unique elements
    unique_list = sorted(list(set(my_list)))
    # Create a comprehensive dictionary with the uniques and their count
    appearance = {a:my_list.count(a) for a in unique_list} 
    # Calculate max number of appearances
    max_app = max(appearance.values())
    # Return the elements of the dictionary that appear that # of times
    return {k: v for k, v in appearance.items() if v == max_app}

0
#function to find mode
def mode(data):  
    modecnt=0
#for count of number appearing
    for i in range(len(data)):
        icount=data.count(data[i])
#for storing count of each number in list will be stored
        if icount>modecnt:
#the loop activates if current count if greater than the previous count 
            mode=data[i]
#here the mode of number is stored 
            modecnt=icount
#count of the appearance of number is stored
    return mode
print mode(data1)

Cevabınızı yorumlarla veya daha fazla ayrıntıyla açıklamalısınız
Michael

0

Bir listenin ortalamasını, medyanını ve modunu şu şekilde bulabilirsiniz:

import numpy as np
from scipy import stats

#to take input
size = int(input())
numbers = list(map(int, input().split()))

print(np.mean(numbers))
print(np.median(numbers))
print(int(stats.mode(numbers)[0]))

0
import numpy as np
def get_mode(xs):
    values, counts = np.unique(xs, return_counts=True)
    max_count_index = np.argmax(counts) #return the index with max value counts
    return values[max_count_index]
print(get_mode([1,7,2,5,3,3,8,3,2]))

0

Minimum modu arayanlar için, örneğin: numpy kullanarak iki modlu dağıtım durumu.

import numpy as np
mode = np.argmax(np.bincount(your_list))

0

Mod bir veri kümesinin / olmasıdır elemanı (ler) (ler), en sık kümesinde meydana geldiği. En sık aynı sayıda görünen iki üye varsa, verilerin iki modu vardır. Buna çift modlu denir .

2'den fazla mod varsa, veri çok modlu olarak adlandırılır . Veri kümesindeki tüm üyeler aynı sayıda görünürse, veri kümesinin hiç modu yoktur .

Aşağıdaki işlev modes(), belirli bir veri listesinde modları bulmak için çalışabilir :

import numpy as np; import pandas as pd

def modes(arr):
    df = pd.DataFrame(arr, columns=['Values'])
    dat = pd.crosstab(df['Values'], columns=['Freq'])
    if len(np.unique((dat['Freq']))) > 1:
        mode = list(dat.index[np.array(dat['Freq'] == max(dat['Freq']))])
        return mode
    else:
        print("There is NO mode in the data set")

Çıktı:

# For a list of numbers in x as
In [1]: x = [2, 3, 4, 5, 7, 9, 8, 12, 2, 1, 1, 1, 3, 3, 2, 6, 12, 3, 7, 8, 9, 7, 12, 10, 10, 11, 12, 2]
In [2]: modes(x)
Out[2]: [2, 3, 12]
# For a list of repeated numbers in y as
In [3]: y = [2, 2, 3, 3, 4, 4, 10, 10]
In [4]: modes(y)
There is NO mode in the data set
# For a list of stings/characters in z as
In [5]: z = ['a', 'b', 'b', 'b', 'e', 'e', 'e', 'd', 'g', 'g', 'c', 'g', 'g', 'a', 'a', 'c', 'a']
In [6]: modes(z)
Out[6]: ['a', 'g']

Bu paketlerden herhangi bir işlevi içeri aktarmak numpyveya pandasçağırmak istemiyorsak , aynı çıktıyı elde etmek için modes()işlev şu şekilde yazılabilir:

def modes(arr):
    cnt = []
    for i in arr:
        cnt.append(arr.count(i))
    uniq_cnt = []
    for i in cnt:
        if i not in uniq_cnt:
            uniq_cnt.append(i)
    if len(uniq_cnt) > 1:
        m = []
        for i in list(range(len(cnt))):
            if cnt[i] == max(uniq_cnt):
                m.append(arr[i])
        mode = []
        for i in m:
            if i not in mode:
                mode.append(i)
        return mode
    else:
        print("There is NO mode in the data set")
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.