Пошук режиму списку


126

Давши список елементів, нагадайте, що режим списку - це той предмет, який найчастіше зустрічається.

Я хотів би знати, як створити функцію, яка може знайти режим списку, але яка відображає повідомлення, якщо у списку немає режиму (наприклад, усі елементи у списку відображаються лише один раз). Я хочу зробити цю функцію без імпорту жодної функції. Я намагаюся зробити власну функцію з нуля.


Вибачте, але чи можете ви пояснити, що саме ви маєте на увазі під "режимом списку"?
Вікас

5
@Vikas: режим є найпоширенішим елементом (якщо він є). Деякі визначення поширюють його на середнє арифметичне всіх таких елементів, якщо їх більше.
Джеремі Роман

Стільки неправильних відповідей тут! Наприклад, assert(mode[1, 1, 1]) == Noneі assert(mode[1, 2, 3, 4]) == None. Щоб число було а mode, воно повинно виникати більше разів, ніж принаймні одне інше число у списку, і воно не повинно бути єдиним номером у списку.
життєвий баланс

Відповіді:


156

Ви можете використовувати maxфункцію та клавішу. Погляньте на функцію python max, використовуючи вираз 'key' та лямбда .

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

6
Це правильна відповідь на ОП, оскільки він не потребує додаткового імпорту. Гарна робота, Девід
Джейсон Пархам

12
Мені здається, що це бігло б O(n**2). Робить це?
lirtosiast

7
Це квадратичний час виконання
Padraic Cunningham

20
Може також просто використовувати max(lst, key=lst.count). (І я справді не закликав би список list.)
Штефан Похман

2
Чи може хтось пояснити, як це працює для бімодальних розподілів? наприклад, a = [22, 33, 11, 22, 11]; print(max(set(a), key=a.count))повертає 11. Чи завжди він поверне мінімальний режим? А якщо так, то чому?
battey

99

Ви можете використовувати Counterнаданий в collectionsупаковці 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

Примітка: Лічильник новий у python 2.7 та недоступний у попередніх версіях.


19
У запитанні зазначено, що користувач хоче зробити функцію з нуля - тобто не імпортувати.
dbliss

3
Ваш останній рядок повертає список, що містить кортеж, що містить режим та його частоту. Щоб просто скористатися режимом Counter(your_list_in_here).most_common(1)[0][0]. Якщо існує більше одного режиму, це повертає довільний режим.
Рорі Даултон

1
Припустимо, є nнайпоширеніші modes. Якщо Counter (your_list_in_here) .most_common (1) [0] [0] отримує вам перший режим, як би ви отримали інший найпоширеніший mode? Просто замініть останній 0на 1? Можна створити функцію, щоб налаштувати їх modeдо вподоби ..

1
якщо існує декілька режимів, як я можу повернути найбільшу з цих цифр?
Акін Хван

59

Python 3.4 включає метод statistics.mode, так що це просто:

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

Ви можете мати будь-який тип елементів у списку, а не лише числовий:

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

17
Припускає помилку при використанні режиму ([1, 1,1,1, 2, 3, 3, 3, 3, 4]), де 1 і 3 повторюють рівну кількість часу. В ідеалі, слід повернути найменше з числа, яке найбільше, але рівне число разів. StatisticsError: немає унікального режиму; знайдено 2 однаково поширені значення
aman_novice

4
Я не використовував цей пакет статистичних даних 3.4, але scipy.stats.mode поверне найменший, у цьому випадку 1. Я, однак, вважаю за краще помилку в певних випадках ...
Слова

2
@aman_novice, проблему було вирішено в Python 3.8. docs.python.org/3/library/statistics.html#statistics.mode
Michael D

2
також додано python 3.8 multimode, який повертає кілька режимів, коли їх існує більше.
стасон

30

Беручи лист із деяких програм статистики, а саме SciPy та MATLAB , вони просто повертають найменше найпоширеніше значення, тому якщо два значення зустрічаються однаково часто, найменше повертається. Сподіваємось, приклад допоможе:

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

Чи є якась причина, чому ви не можете дотримуватися цієї конвенції?


4
Чому повертається лише найменший режим, коли їх кілька?
zyxue

@zyxue проста статистична конвенція
chrisfs

2
@chrisfs і змусити його повернути найбільший режим, якщо їх кілька?
Акін Хван

25

Існує багато простих способів знайти режим списку в Python, наприклад:

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

Або ви могли знайти максимум за його кількістю

max(array, key = array.count)

Проблема цих двох методів полягає в тому, що вони не працюють у кількох режимах. Перший повертає помилку, а другий повертає перший режим.

Для того, щоб знайти режими набору, ви можете використовувати цю функцію:

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

3
Використовуючи режим, дає помилку, коли два елементи трапляються однакову кількість часу.
Абхішек Мішра

Вибачте, побачив цей коментар дуже пізно. Statistics.mode (масив) повертає помилку в декількох режимах, але жоден з інших методів не робить.
mathwizurd

7

Розширення відповіді спільноти, яка не буде працювати, коли список порожній, ось робочий код для режиму:

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

3

Якщо вас цікавить або найменший, найбільший або всі режими:

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

Я написав цю зручну функцію для пошуку режиму.

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-х предметів немає жодного. випадків.
акшайгнапал

2

Короткий, але якось потворний:

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

Використовуючи словник, трохи менш потворний:

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

Трохи довше, але може мати декілька режимів і може отримати рядок з більшістю підрахунків або поєднання типів даних.

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

Щоб число було а mode, воно повинно виникати більше разів, ніж принаймні одне інше число у списку, і воно не повинно бути єдиним номером у списку. Отже, я відновив відповідь @ mathwizurd (застосувати differenceметод) наступним чином:

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

Ці тести успішно проходять:

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

1

Чому б не просто

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

У цьому немає декількох перевірок помилок, але він знайде режим, не імпортуючи жодної функції, і надрукує повідомлення, якщо всі значення з’являться лише один раз. Він також виявить декілька елементів, що мають однаковий максимальний кількість, хоча не було зрозуміло, чи хочете ви цього.


Тож, що я намагаюся зробити, це виявити декілька предметів, що відображають однакову кількість, а потім відобразити всі елементи з тим самим рахунком
bluelantern

Ви насправді самі пробували це? Розширення з мого коду тут, щоб він друкував усі елементи з однаковим рахунком, досить простий.
lxop

1

Ця функція повертає режим або режими функції незалежно від кількості, а також частоту режимів або режимів у наборі даних. Якщо немає режиму (тобто всі елементи трапляються лише один раз), функція повертає рядок помилки. Це схоже на функцію A_nagpal, описану вище, але, на мою скромну думку, є більш повною, і я вважаю, що легше зрозуміти будь-яких новачків Python (таких як ваш справді), читаючи це питання, щоб зрозуміти.

 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

Я кажу це лише тому, що ви сказали, що "функція повертає рядок помилки". Рядок, який зчитується, return 'There is no mode for this data set. All values occur only once.'може бути перетворений у повідомлення про помилку із tracebackтаким чином: "як умова: наступний рядок з відступом підвищити ValueError (" Для цього набору даних немає режиму. Усі значення трапляються лише один раз. ") Ось список різних типів помилки, які ви можете викликати.

1

Це поверне всі режими:

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

Простий код, який знаходить режим списку без жодного імпорту:

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)

У випадку декількох режимів він повинен повернути мінімальний вузол.


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

Ось проста функція, яка отримує перший режим, який виникає у списку. Створює словник з елементами списку як ключами та кількістю подій, а потім зчитує значення dict для отримання режиму.

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

Якщо ви хочете чіткий підхід, корисний для аудиторії та використовуючи лише списки та словники з розумінням, ви можете зробити:

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)

Свою відповідь слід пояснити коментарями або більш детальною інформацією
Майкл

0

Ось як можна знайти середню, медіану та режим списку:

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

Для тих, хто шукає мінімальний режим, наприклад: випадок бімодального розподілу з використанням numpy.

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

0

Режим набору даних є / є членами, які найчастіше зустрічаються в наборі. Якщо є два учасники, які з’являються найчастіше з однаковою кількістю разів, то дані мають два режими. Це називається бімодальним .

Якщо існує більше 2 режимів, то дані називали б мультимодальними . Якщо всі члени в наборі даних з’являються однаковою кількістю разів, то набір даних взагалі не має режиму .

Наступна функція modes()може працювати для пошуку режимів (-ів) у заданому списку даних:

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

Вихід:

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

Якщо ми не хочемо імпортувати numpyабо pandasвикликати якусь функцію з цих пакетів, то для отримання цього ж виводу modes()функцію можна записати як:

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")
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.