Trouver le mode d'une liste


126

Étant donné une liste d'éléments, rappelez-vous que le mode de la liste est l'élément qui apparaît le plus souvent.

Je voudrais savoir comment créer une fonction qui peut trouver le mode d'une liste mais qui affiche un message si la liste n'a pas de mode (par exemple, tous les éléments de la liste n'apparaissent qu'une seule fois). Je veux faire cette fonction sans importer aucune fonction. J'essaie de créer ma propre fonction à partir de zéro.


Pardon, mais pouvez-vous expliquer ce que vous entendez exactement par «mode de la liste»?
Vikas

5
@Vikas: le mode est l'élément le plus fréquent (le cas échéant). Certaines définitions l'étendent pour prendre la moyenne arithmétique de tous ces éléments s'il y en a plus d'un.
Jeremy Roman

Tant de mauvaises réponses ici! Pour par exemple assert(mode[1, 1, 1]) == Noneet assert(mode[1, 2, 3, 4]) == None. Pour qu'un nombre soit a mode, il doit apparaître plus de fois qu'au moins un autre nombre de la liste, et ce ne doit pas être le seul nombre de la liste.
lifebalance

Réponses:


156

Vous pouvez utiliser la maxfonction et une touche. Jetez un œil à la fonction python max en utilisant l'expression 'key' et lambda .

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

6
C'est la bonne réponse à OP, étant donné qu'elle ne nécessite aucune importation supplémentaire. Bon travail, David
Jason Parham

12
Il me semble que cela fonctionnerait O(n**2). Le fait-il?
lirtosiast

7
Cela a un temps d'exécution quadratique
Padraic Cunningham

20
Pourrait aussi simplement utiliser max(lst, key=lst.count). (Et je n'appellerais vraiment pas une liste list.)
Stefan Pochmann

2
Quelqu'un peut-il expliquer comment cela fonctionne pour les distributions bimodales? par exemple, a = [22, 33, 11, 22, 11]; print(max(set(a), key=a.count))retourne 11. Retournera-t-il toujours le mode minimum? Et si oui, pourquoi?
battey

99

Vous pouvez utiliser le Counterfourni dans le collectionspackage qui a une modefonction -esque

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

Remarque: Counter est nouveau dans python 2.7 et n'est pas disponible dans les versions antérieures.


19
La question indique que l'utilisateur veut créer une fonction à partir de zéro - c'est-à-dire pas d'importations.
dbliss

3
Votre dernière ligne renvoie une liste contenant un tuple contenant un mode et sa fréquence. Pour obtenir juste un mode d'utilisation Counter(your_list_in_here).most_common(1)[0][0]. S'il y a plus d'un mode, cela renvoie un mode arbitraire.
Rory Daulton le

1
Supposons qu'il existe les nplus courants modes. Si Counter (your_list_in_here) .most_common (1) [0] [0] vous donne le premier mode, comment en obtiendriez-vous un autre plus courant mode? Remplacez simplement le dernier 0par 1? On peut créer une fonction pour personnaliser le modeà leur goût.

1
s'il y a plus d'un mode, comment puis-je renvoyer le plus grand de ces nombres?
Akin Hwan

59

Python 3.4 inclut la méthode statistics.mode, donc c'est simple:

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

Vous pouvez avoir n'importe quel type d'éléments dans la liste, pas seulement numériques:

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

17
Lance une erreur lors de l'utilisation du mode ([1, 1,1,1, 2, 3, 3, 3, 3, 4]) où 1 et 3 se répètent un nombre égal de fois. Idéalement, devrait renvoyer le plus petit du nombre de fois le plus grand mais égal. StatisticsError: pas de mode unique; trouvé 2 valeurs également communes
aman_novice

4
Je n'ai pas utilisé ce package de statistiques 3.4, mais scipy.stats.mode renverra le plus petit, dans ce cas 1. Je préférerais cependant le rejet de l'erreur dans certains cas ...
wordsmith

2
@aman_novice, le problème a été résolu dans Python 3.8. docs.python.org/3/library/statistics.html#statistics.mode
Michael D

2
python 3.8 a également été ajouté multimode, qui retourne plusieurs modes lorsqu'il y en a plus d'un.
stason

30

Prenant une feuille de certains logiciels de statistiques, à savoir SciPy et MATLAB , ceux-ci ne renvoient que la plus petite valeur la plus courante, donc si deux valeurs se produisent également souvent, la plus petite d'entre elles est renvoyée. Espérons qu'un exemple aidera:

>>> 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.]))

Y a-t-il une raison pour laquelle vous ne pouvez pas suivre cette convention?


4
Pourquoi seul le plus petit mode est renvoyé lorsqu'il y en a plusieurs?
zyxue

@zyxue convention statistique simple
chrisfs

2
@chrisfs et le faire retourner le plus grand mode s'il y en a plusieurs?
Akin Hwan

25

Il existe de nombreuses façons simples de trouver le mode d'une liste en Python, telles que:

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

Ou, vous pouvez trouver le maximum par son nombre

max(array, key = array.count)

Le problème avec ces deux méthodes est qu'elles ne fonctionnent pas avec plusieurs modes. Le premier renvoie une erreur, tandis que le second renvoie le premier mode.

Afin de trouver les modes d'un ensemble, vous pouvez utiliser cette fonction:

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

3
L'utilisation du mode donne une erreur lorsqu'il y a deux éléments qui se produisent le même laps de temps.
Abhishek Mishra

Désolé, j'ai vu ce commentaire très tard. Statistics.mode (tableau) renverrait une erreur avec plusieurs modes, mais aucune des autres méthodes ne le fait.
mathwizurd

7

Étendre la réponse communautaire qui ne fonctionnera pas lorsque la liste est vide, voici le code de travail pour le mode:

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

3

Si vous êtes intéressé par le plus petit, le plus grand ou tous les modes:

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

J'ai écrit cette fonction pratique pour trouver le mode.

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
Cette méthode échouera si 2 éléments ont le même no. des événements.
akshaynagpal

2

Bref, mais quelque peu laid:

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

Utilisation d'un dictionnaire, un peu moins moche:

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

Un peu plus long, mais peut avoir plusieurs modes et peut obtenir une chaîne avec la plupart des nombres ou un mélange de types de données.

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

Pour qu'un nombre soit a mode, il doit se produire plus de fois qu'au moins un autre nombre de la liste et il ne doit pas être le seul nombre de la liste. Donc, j'ai refactoré la réponse de @ mathwizurd (pour utiliser la differenceméthode) comme suit:

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!" 

Ces tests réussissent:

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

1

Pourquoi pas juste

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

Cela n'a pas quelques contrôles d'erreur qu'il devrait avoir, mais il trouvera le mode sans importer de fonctions et imprimera un message si toutes les valeurs n'apparaissent qu'une seule fois. Il détectera également plusieurs éléments partageant le même nombre maximum, bien que vous ne sachiez pas si vous le vouliez.


Donc, ce que j'essaie de faire est de détecter plusieurs éléments affichant le même nombre, puis d'afficher tous les éléments avec le même nombre
bluelantern

Avez-vous réellement essayé cela vous-même? L'extension de mon code ici pour qu'il imprime tous les éléments avec le même nombre est assez simple.
lxop

1

Cette fonction renvoie le ou les modes d'une fonction, quel qu'en soit le nombre, ainsi que la fréquence du ou des modes dans l'ensemble de données. S'il n'y a pas de mode (c'est-à-dire que tous les éléments n'apparaissent qu'une seule fois), la fonction renvoie une chaîne d'erreur. Ceci est similaire à la fonction A_nagpal ci-dessus mais est, à mon humble avis, plus complet, et je pense qu'il est plus facile à comprendre pour tous les novices de Python (comme le vôtre) qui lisent cette question pour comprendre.

 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

Je dis cela uniquement parce que vous avez dit "la fonction renvoie une chaîne d'erreur". La ligne qui lit return 'There is no mode for this data set. All values occur only once.'peut être transformée en un message d'erreur avec tracebackcomme `si condition: ligne suivante avec retrait augmenter ValueError ('Il n'y a pas de mode pour cet ensemble de données. Toutes les valeurs n'apparaissent qu'une seule fois.') Voici une liste de différents types de erreurs que vous pouvez soulever.

1

Cela retournera tous les modes:

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

Code simple qui trouve le mode de la liste sans aucune importation:

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)

En cas de modes multiples, il doit renvoyer le nœud minimum.


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

Voici une fonction simple qui obtient le premier mode qui se produit dans une liste. Il crée un dictionnaire avec les éléments de la liste sous forme de clés et le nombre d'occurrences, puis lit les valeurs dict pour obtenir le mode.

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

Si vous voulez une approche claire, utile pour la classe et n'utilisant que des listes et des dictionnaires par compréhension, vous pouvez faire:

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)

Vous devriez expliquer votre réponse avec des commentaires ou plus de détails
Michael

0

Voici comment trouver la moyenne, la médiane et le mode d'une liste:

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

Pour ceux qui recherchent le mode minimum, par exemple: cas de la distribution bi-modale, utilisant numpy.

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

0

Le mode d'un ensemble de données est / sont le (s) membre (s) qui apparaissent le (s) le (s) le (s) le (s) le (s) le (s) le (s) le plus. S'il y a deux membres qui apparaissent le plus souvent avec le même nombre de fois, alors les données ont deux modes. Ceci est appelé bimodal .

S'il y a plus de 2 modes, alors les données seront appelées multimodales . Si tous les membres de l'ensemble de données apparaissent le même nombre de fois, alors l'ensemble de données n'a aucun mode .

La fonction suivante modes()peut fonctionner pour trouver le (s) mode (s) dans une liste donnée de données:

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")

Production:

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

Si nous ne voulons pas importer numpyou pandasappeler une fonction à partir de ces packages, alors pour obtenir cette même sortie, la modes()fonction peut être écrite comme suit:

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")
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.