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.

bluelantern
źródło
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)
David Dao
źródło
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.

Christian Witts
źródło
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'
jabaldonedo
źródło
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?

Chris
źródło
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)))
mathwizurd
źródło
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)
Kardi Teknomo
źródło
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
tashuhka
źródło
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
user2975335
źródło
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
Carl
źródło
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 
timpjohns
źródło
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 
równowaga życiowa
źródło
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.

lxop
źródło
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
user4406935
źródło
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
Tim Orton
źródło
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ł.

baby_yoda
źródło
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
akshaynagpal
źródło
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])
Venkata Prasanth T
źródło
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.")
SMS von der Tann
źródło
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}
María Frances Gaska
źródło
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)

źródło
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]))
pankaj
źródło
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]))
sim
źródło
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))
V3K3R
źródło
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")
shubh
źródło