2012-05-29 18 views
61

Dada una lista de elementos, recuerde que el modo de la lista es el elemento que ocurre con mayor frecuencia.Encontrar el modo de una lista

Me gustaría saber cómo crear una función que pueda encontrar el modo de una lista pero que muestre un mensaje si la lista no tiene un modo (por ejemplo, todos los elementos de la lista solo aparecen una vez). Quiero hacer esta función sin importar ninguna función. Estoy tratando de hacer mi propia función desde cero.

+0

Lo sentimos, pero puedo explicar qué es exactamente lo que quiere decir con 'modo de la lista'? – Vikas

+3

@Vikas: el modo es el elemento más frecuente (si corresponde). Algunas definiciones lo amplían para tomar la media aritmética de todos esos elementos si hay más de uno. –

+0

¡Tantas respuestas incorrectas aquí! Por ejemplo 'assert (modo [1, 1, 1]) == None' y ' assert (modo [1, 2, 3, 4]) == Ninguno'. Para que un número sea un 'modo ', debe ocurrir más veces que al menos otro número en la lista, y no debe ser el único número en la lista. – lifebalance

Respuesta

73

se puede utilizar el Counter incluye en el paquete collections que tiene una función mode 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 

Nota: Contador es nuevo en Python 2.7 y no está disponible en las versiones anteriores.

+12

La pregunta indica que el usuario desea realizar una función desde cero, es decir, no importa. – dbliss

+1

Su última línea devuelve una lista que contiene una tupla que contiene un modo y su frecuencia. Para obtener solo un modo use 'Counter (su_lista_en_aquí) .most_common (1) [0] [0]'. Si hay más de un modo, esto devuelve uno arbitrario. –

+0

Supongamos que hay 'n' los' modos' más comunes. Si Counter (your_list_in_here) .most_common (1) [0] [0] te ofrece el primer modo, ¿cómo obtendrías otro 'modo' más común?¿Simplemente reemplaza el último '0' con' 1'? Se puede hacer una función para personalizar el 'modo' a su gusto. – mikey

19

Tomando una hoja de algún software de estadísticas, concretamente SciPy y MATLAB, estos simplemente devuelven el valor más pequeño más común, de modo que si dos valores ocurren con la misma frecuencia, se devuelve el más pequeño de estos. Esperemos que un ejemplo ayude:

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

¿Hay alguna razón por la que no se puede seguir esta convención?

+2

¿Por qué solo se devuelve el modo más pequeño cuando hay múltiples? – zyxue

0

¿Por qué no

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 

Esto no tiene algunas verificaciones de error que debería tener, pero va a encontrar el modo sin importar cualquier funciones e imprimirá un mensaje si todos los valores aparecen sólo una vez. También detectará varios elementos que comparten el mismo recuento máximo, aunque no estaba claro si usted quería eso.

+0

Entonces, lo que intento hacer es detectar varios elementos que muestran el mismo recuento y luego mostrar todos los elementos con ese mismo recuento – bluelantern

+0

¿Lo ha probado usted realmente? La extensión de mi código aquí para que imprima todos los elementos con el mismo recuento es bastante sencilla. – lxop

1

Escribí esta útil función para encontrar el modo.

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 
+1

Este método fallará si 2 elementos tienen el mismo no. de ocurrencias. – akshaynagpal

27

Python 3.4 incluye el método statistics.mode, por lo que es sencillo:

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

Usted puede tener cualquier tipo de elementos en la lista, no sólo numérica:

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

Lanza un error al usar el modo ([1, 1,1,1, 2, 3, 3, 3, 3, 4]) donde 1 y 3 repiten la misma cantidad de tiempo. Idealmente, debería devolver el número más pequeño del número más grande pero igual número de veces. StatisticsError: no hay modo único; encontrado 2 valores igualmente comunes –

+1

No he usado este paquete de estadísticas 3.4, pero scipy.stats.mode devolverá el más pequeño, en este caso 1. Sin embargo, preferiría el lanzamiento del error en ciertos casos ... – wordsmith

1

corto, pero de alguna manera fea:

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 

El uso de un diccionario, un poco menos feo:

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

Esta función devuelve el modo o modos de función, no importa cuántas, así como la frecuencia del modo o modos en el conjunto de datos. Si no hay un modo (es decir, todos los elementos aparecen solo una vez), la función devuelve una cadena de error. Esto es similar a la función de A_nagpal anterior, pero es, en mi humilde opinión, más completo, y creo que es más fácil de entender para cualquier principiante de Python (como el tuyo) leer esta pregunta para entenderla.

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 
+0

I di esto solo porque dijiste "la función devuelve una cadena de error". La línea que dice 'devolver 'No hay modo para este conjunto de datos. Todos los valores ocurren solo una vez. '' Se puede convertir en un mensaje de error con 'traceback' como' if condition: * next line with indent * raise ValueError ('No hay modo para este conjunto de datos. Todos los valores ocurren solo una vez.') [Aquí hay una lista] (https://docs.python.org/3/tutorial/errors.html) de los diferentes tipos de errores que puede generar. – mikey

77

Puede usar la función max y una clave. Eche un vistazo al python max function using 'key' and lambda expression.

max(set(list), key=list.count) 
+5

Esta es la respuesta correcta a OP, considerando que no requiere ninguna importación adicional. Buen trabajo, David –

+5

Me parece que esto se ejecutará en 'O (n ** 2)'. ¿Lo hace? – lirtosiast

+4

Esto tiene un tiempo de ejecución cuadrático –

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

Hay muchas formas sencillas de encontrar el modo de una lista en Python como:

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

O, usted podría encontrar el máximo por su recuento

max(array, key = array.count) 

El problema con estos dos métodos es que no funcionan con múltiples modos. El primero devuelve un error, mientras que el segundo devuelve el primer modo.

el fin de encontrar los modos de un conjunto, se puede usar esta función:

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

Usando el modo, da error cuando hay dos elementos que ocurren la misma cantidad de tiempo. – user31688

2

Un poco más de tiempo, pero puede tener múltiples modos y puede llegar cadena con la mayoría de los recuentos o mezcla de tipos de datos.

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 
0

Aquí hay una función simple que obtiene el primer modo que ocurre en una lista. Hace un diccionario con los elementos de la lista como claves y número de apariciones y luego lee los valores dict para obtener el modo.

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

En caso de estar interesado en cualquiera de los más pequeños modos, más grandes o todas:

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 
0

Esto devolverá todos modos:

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 
0

Si desea un enfoque claro, útil para el aula y solo usando listas y diccionarios por comprensión, puede hacer:

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

Para un número para ser un mode, debe ocurrir con mayor número de veces que al menos otro número en la lista, y debe no ser el único número en la lista. Por lo tanto, refactorizado respuesta de @ mathwizurd (para usar el método difference) de la siguiente manera:

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

Estas pruebas pasan con éxito:

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