Znajdowanie trybu listy


126

Mając listę pozycji, pamiętaj, że tryb listy to pozycja, która występuje najczęściej.

Chciałbym wiedzieć, jak stworzyć funkcję, która może znaleźć tryb listy, ale która wyświetla komunikat, jeśli lista nie ma trybu (np. Wszystkie pozycje na liście pojawiają się tylko raz). Chcę utworzyć tę funkcję bez importowania żadnych funkcji. Próbuję stworzyć własną funkcję od zera.


Przepraszam, ale czy możesz wyjaśnić, co dokładnie rozumiesz przez „tryb listy”?
Vikas

5
@Vikas: tryb jest najczęściej występującym elementem (jeśli występuje). Niektóre definicje rozszerzają ją na średnią arytmetyczną wszystkich takich elementów, jeśli jest ich więcej.
Jeremy Roman

Tak wiele błędnych odpowiedzi! Na przykład assert(mode[1, 1, 1]) == Nonei assert(mode[1, 2, 3, 4]) == None. Przez szereg być mode, musi wystąpić kilka razy więcej niż co najmniej jednego innego numeru na liście, a to musi nie być tylko numer na liście.
saldo ratunkowe

Odpowiedzi:


156

Możesz użyć maxfunkcji i klawisza. Przyjrzyj się funkcji Pythona max przy użyciu „klucza” i wyrażenia lambda .

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

6
To jest poprawna odpowiedź na OP, biorąc pod uwagę, że nie wymaga dodatkowego importu. Dobra robota, David
Jason Parham

12
Wydaje mi się, że to się pojawi O(n**2). Czy to?
lirtosiast

7
To ma kwadratowy czas działania
Padraic Cunningham

20
Można też po prostu użyć max(lst, key=lst.count). (I naprawdę nie nazwałbym listy list.)
Stefan Pochmann

2
Czy ktoś może wyjaśnić, jak to działa w przypadku rozkładów dwumodalnych? np . a = [22, 33, 11, 22, 11]; print(max(set(a), key=a.count))zwroty 11. Czy zawsze zwróci tryb minimalny? A jeśli tak, to dlaczego?
battey

99

Możesz użyć Counterdostarczonego w collectionspakiecie, który ma funkcję 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

Uwaga: Licznik jest nowy w Pythonie 2.7 i nie jest dostępny we wcześniejszych wersjach.


19
Pytanie stwierdza, że ​​użytkownik chce wykonać funkcję od zera - tj. Bez importu.
dbliss

3
Twoja ostatnia linia zwraca listę zawierającą krotkę zawierającą modę i jej częstotliwość. Aby uzyskać tylko tryb, użyj Counter(your_list_in_here).most_common(1)[0][0]. Jeśli istnieje więcej niż jeden tryb, zwraca to dowolny.
Rory Daulton

1
Załóżmy, że są nnajbardziej powszechne modes. Jeśli Counter (your_list_in_here) .most_common (1) [0] [0] dostaniesz pierwszy tryb, w jaki sposób uzyskałbyś inny najpopularniejszy mode? Wystarczy zastąpić ostatni 0z 1? Można stworzyć funkcję, aby dostosować ją modedo swoich upodobań ..

1
jeśli jest więcej niż jeden tryb, jak mogę zwrócić największą z tych liczb?
Akin Hwan

59

Python 3.4 zawiera tę metodę statistics.mode, więc jest to proste:

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

Lista może zawierać elementy dowolnego typu, nie tylko liczbowe:

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

17
Zgłasza błąd podczas używania trybu ([1, 1,1,1, 2, 3, 3, 3, 3, 4]), w którym 1 i 3 powtarzają się równą liczbę razy. W idealnym przypadku powinno zwrócić najmniejszą z liczby, która jest największa, ale równa liczba razy. StatisticsError: brak unikalnego trybu; znaleziono 2 równie powszechne wartości
aman_novice

4
Nie korzystałem z tego pakietu statystyk 3.4, ale scipy.stats.mode zwróci najmniejszą, w tym przypadku 1. Wolałbym jednak w niektórych przypadkach rzucić błąd ...
wordsmith

2
@aman_novice, problem został rozwiązany w Pythonie 3.8. docs.python.org/3/library/statistics.html#statistics.mode
Michael D

2
Dodano również python 3.8 multimode, który zwraca wiele trybów, gdy jest więcej niż jeden.
stason

30

Biorąc listek z niektórych programów statystycznych, a mianowicie SciPy i MATLAB , zwracają one tylko najmniejszą najczęściej spotykaną wartość, więc jeśli dwie wartości występują równie często, zwracana jest najmniejsza z nich. Miejmy nadzieję, że przykład pomoże:

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

Czy jest jakiś powód, dla którego nie możesz przestrzegać tej konwencji?


4
Dlaczego zwracany jest tylko najmniejszy tryb, gdy jest ich wiele?
zyxue

@zyxue prosta konwencja statystyczna
chrisfs

2
@chrisfs i aby zwracał największy tryb, jeśli jest ich wiele?
Akin Hwan

25

Istnieje wiele prostych sposobów na znalezienie trybu listy w Pythonie, takich jak:

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

Lub możesz znaleźć maksimum na podstawie jego liczby

max(array, key = array.count)

Problem z tymi dwiema metodami polega na tym, że nie działają one z wieloma trybami. Pierwsza zwraca błąd, a druga zwraca pierwszy tryb.

Aby znaleźć tryby zestawu, możesz użyć tej funkcji:

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

3
Używając trybu, daje błąd, gdy dwa elementy występują w tym samym czasie.
Abhishek Mishra,

Przepraszam, zobaczyłem ten komentarz naprawdę późno. Statistics.mode (tablica) zwróciłby błąd z wieloma trybami, ale żadna z pozostałych metod nie zwróciłaby błędu.
mathwizurd

7

Rozszerzając odpowiedź społeczności, która nie zadziała, gdy lista jest pusta, oto działający kod dla trybu:

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

3

Jeśli jesteś zainteresowany najmniejszym, największym lub wszystkimi trybami:

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

Napisałem tę przydatną funkcję, aby znaleźć tryb.

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
Ta metoda nie powiedzie się, jeśli 2 elementy mają ten sam nr. wystąpień.
akshaynagpal

2

Krótkie, ale jakoś brzydkie:

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

Korzystanie ze słownika, nieco mniej brzydkie:

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

Nieco dłużej, ale może mieć wiele trybów i może otrzymać łańcuch z większością zliczeń lub mieszanki typów danych.

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

Przez szereg być mode, musi wystąpić kilka razy więcej niż co najmniej jeden inny numer na liście, a to musi nie być tylko numer na liście. Tak więc refaktoryzowałem odpowiedź @ mathwizurd (aby użyć differencemetody) w następujący sposób:

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

Te testy kończą się pomyślnie:

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

1

Dlaczego nie po prostu

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

To nie ma kilku sprawdzeń błędów, które powinien mieć, ale znajdzie tryb bez importowania żadnych funkcji i wydrukuje komunikat, jeśli wszystkie wartości pojawią się tylko raz. Wykryje również wiele przedmiotów o tej samej maksymalnej liczbie, chociaż nie było jasne, czy tego chcesz.


Więc to, co próbuję zrobić, to wykryć wiele elementów o tej samej liczbie, a następnie wyświetlić wszystkie elementy z tą samą liczbą
bluelantern

Czy faktycznie próbowałeś tego sam? Rozszerzenie z mojego kodu umożliwiające wydrukowanie wszystkich elementów o tej samej liczbie jest dość proste.
lxop

1

Ta funkcja zwraca tryb lub tryby funkcji bez względu na ich liczbę, a także częstotliwość trybu lub trybów w zbiorze danych. Jeśli nie ma trybu (tzn. Wszystkie elementy występują tylko raz), funkcja zwraca ciąg błędu. Jest to podobne do funkcji A_nagpal powyżej, ale moim skromnym zdaniem jest bardziej kompletne i myślę, że jest to łatwiejsze do zrozumienia dla wszystkich nowicjuszy w Pythonie (takich jak naprawdę), którzy czytają to pytanie, aby zrozumieć.

 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

Mówię to tylko dlatego, że powiedziałeś „funkcja zwraca ciąg błędu”. Wiersz, który czyta, return 'There is no mode for this data set. All values occur only once.'można przekształcić w komunikat o błędzie z traceback`` if condition: następny wiersz z podniesieniem wcięcia ValueError ('Brak trybu dla tego zestawu danych. Wszystkie wartości występują tylko raz.') Oto lista różnych typów błędy, które możesz zgłosić.

1

Spowoduje to zwrócenie wszystkich trybów:

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

Prosty kod, który znajduje tryb listy bez importu:

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)

W przypadku wielu trybów powinien zwrócić minimalny węzeł.


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

Oto prosta funkcja, która pobiera pierwszy tryb występujący na liście. Tworzy słownik z elementami listy jako kluczami i liczbą wystąpień, a następnie odczytuje wartości dyktowania, aby uzyskać tryb.

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

Jeśli chcesz mieć jasne podejście, przydatne w klasie i korzystasz tylko z list i słowników według zrozumienia, możesz:

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)

Powinieneś wyjaśnić swoją odpowiedź komentarzami lub więcej szczegółów
Michael

0

Oto, jak można znaleźć średnią, medianę i tryb listy:

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

Dla tych, którzy szukają trybu minimum, np .: przypadek dystrybucji bi-modalnej, używając numpy.

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

0

Tryb zbioru danych to element (elementy), który (e) najczęściej występuje (e) w zbiorze. Jeśli istnieją dwa elementy członkowskie, które pojawiają się najczęściej z taką samą liczbą razy, dane mają dwa tryby. To się nazywa bimodalnym .

Gdyby istniało więcej niż 2 tryby, dane byłyby nazywane multimodalnymi . Jeśli wszystkie elementy w zestawie danych pojawiają się tyle samo razy, oznacza to, że zestaw danych nie ma trybu .

Następująca funkcja modes()może działać, aby znaleźć tryb (y) na podanej liście danych:

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

Wynik:

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

Jeśli nie chcemy importować numpyani pandaswywoływać żadnej funkcji z tych pakietów, to aby uzyskać ten sam wynik, modes()funkcję można zapisać jako:

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")
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.