Подтвердить что ты не робот

Python - найти элемент с максимальными вхождениями в список

В Python у меня есть список:

L = [1, 2, 45, 55, 5, 4, 4, 4, 4, 4, 4, 5456, 56, 6, 7, 67]  

Я хочу идентифицировать элемент, который имел наибольшее количество раз. Я могу решить это, но мне нужен самый быстрый способ сделать это. Я знаю, что есть хороший ответ на Питону.

4b9b3361

Ответ 1

Вот решение defaultdict, которое будет работать с версиями Python версии 2.5 и выше:

from collections import defaultdict

L = [1,2,45,55,5,4,4,4,4,4,4,5456,56,6,7,67]
d = defaultdict(int)
for i in L:
    d[i] += 1
result = max(d.iteritems(), key=lambda x: x[1])
print result
# (4, 6)
# The number 4 occurs 6 times

Обратите внимание, если L = [1, 2, 45, 55, 5, 4, 4, 4, 4, 4, 4, 5456, 7, 7, 7, 7, 7, 56, 6, 7, 67] то есть шесть 4 и шесть 7. Однако результатом будет (4, 6) то есть шесть 4s.

Ответ 2

from collections import Counter
most_common,num_most_common = Counter(L).most_common(1)[0] # 4, 6 times

Для более старых версий Python (< 2.7) вы можете использовать этот рецепт, чтобы получить Counter.

Ответ 3

Я удивлен, что никто не упомянул простейшее решение max() с ключом list.count:

max(lst,key=lst.count)

Пример:

>>> lst = [1, 2, 45, 55, 5, 4, 4, 4, 4, 4, 4, 5456, 56, 6, 7, 67]
>>> max(lst,key=lst.count)
4

Это работает в Python 3 или 2, но обратите внимание, что он возвращает только самый частый элемент, а не частоту. Кроме того, в случае розыгрыша (т.е. Наиболее часто встречающегося элемента) возвращается только один элемент.

Хотя временная сложность использования max() хуже, чем использование Counter.most_common(1) качестве комментариев PM 2Ring, этот подход выигрывает от быстрой реализации C и я считаю, что этот подход наиболее быстр для коротких списков, но медленнее для более крупных (Python 3.6 время показанное в IPython 5.3):

In [1]: from collections import Counter
   ...: 
   ...: def f1(lst):
   ...:     return max(lst, key = lst.count)
   ...: 
   ...: def f2(lst):
   ...:     return Counter(lst).most_common(1)
   ...: 
   ...: lst0 = [1,2,3,4,3]
   ...: lst1 = lst0[:] * 100
   ...: 

In [2]: %timeit -n 10 f1(lst0)
10 loops, best of 3: 3.32 us per loop

In [3]: %timeit -n 10 f2(lst0)
10 loops, best of 3: 26 us per loop

In [4]: %timeit -n 10 f1(lst1)
10 loops, best of 3: 4.04 ms per loop

In [5]: %timeit -n 10 f2(lst1)
10 loops, best of 3: 75.6 us per loop

Ответ 4

В вашем вопросе вы попросили максимально быстрый способ сделать это. Как неоднократно демонстрировалось, особенно с Python, интуиция не является надежным руководством: вам нужно измерить.

Вот простой тест нескольких различных реализаций:

import sys
from collections import Counter, defaultdict
from itertools import groupby
from operator import itemgetter
from timeit import timeit

L = [1,2,45,55,5,4,4,4,4,4,4,5456,56,6,7,67]

def max_occurrences_1a(seq=L):
    "dict iteritems"
    c = dict()
    for item in seq:
        c[item] = c.get(item, 0) + 1
    return max(c.iteritems(), key=itemgetter(1))

def max_occurrences_1b(seq=L):
    "dict items"
    c = dict()
    for item in seq:
        c[item] = c.get(item, 0) + 1
    return max(c.items(), key=itemgetter(1))

def max_occurrences_2(seq=L):
    "defaultdict iteritems"
    c = defaultdict(int)
    for item in seq:
        c[item] += 1
    return max(c.iteritems(), key=itemgetter(1))

def max_occurrences_3a(seq=L):
    "sort groupby generator expression"
    return max(((k, sum(1 for i in g)) for k, g in groupby(sorted(seq))), key=itemgetter(1))

def max_occurrences_3b(seq=L):
    "sort groupby list comprehension"
    return max([(k, sum(1 for i in g)) for k, g in groupby(sorted(seq))], key=itemgetter(1))

def max_occurrences_4(seq=L):
    "counter"
    return Counter(L).most_common(1)[0]

versions = [max_occurrences_1a, max_occurrences_1b, max_occurrences_2, max_occurrences_3a, max_occurrences_3b, max_occurrences_4]

print sys.version, "\n"

for vers in versions:
    print vers.__doc__, vers(), timeit(vers, number=20000)

Результаты на моей машине:

2.7.2 (v2.7.2:8527427914a2, Jun 11 2011, 15:22:34) 
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] 

dict iteritems (4, 6) 0.202214956284
dict items (4, 6) 0.208412885666
defaultdict iteritems (4, 6) 0.221301078796
sort groupby generator expression (4, 6) 0.383440971375
sort groupby list comprehension (4, 6) 0.402786016464
counter (4, 6) 0.564319133759

Итак, кажется, что решение Counter не является самым быстрым. И, в этом случае, по крайней мере, groupby работает быстрее. defaultdict хорошо, но вы платите немного за его удобство; он немного быстрее использует обычный dict с get.

Что произойдет, если список намного больше? Добавьте L *= 10000 к тесту выше и уменьшите количество повторений до 200:

dict iteritems (4, 60000) 10.3451900482
dict items (4, 60000) 10.2988479137
defaultdict iteritems (4, 60000) 5.52838587761
sort groupby generator expression (4, 60000) 11.9538850784
sort groupby list comprehension (4, 60000) 12.1327362061
counter (4, 60000) 14.7495789528

Теперь defaultdict является явным победителем. Так что, возможно, стоимость метода get и потери дополнения inplace складывается (рассмотрение сгенерированного кода остается в виде упражнения).

Но с измененными тестовыми данными количество уникальных значений элементов не изменилось, поэтому предположительно dict и defaultdict имеют преимущество над другими реализациями. Итак, что произойдет, если мы будем использовать более крупный список, но существенно увеличим количество уникальных предметов? Заменив инициализацию L следующим образом:

LL = [1,2,45,55,5,4,4,4,4,4,4,5456,56,6,7,67]
L = []
for i in xrange(1,10001):
    L.extend(l * i for l in LL)

dict iteritems (2520, 13) 17.9935798645
dict items (2520, 13) 21.8974409103
defaultdict iteritems (2520, 13) 16.8289561272
sort groupby generator expression (2520, 13) 33.853593111
sort groupby list comprehension (2520, 13) 36.1303369999
counter (2520, 13) 22.626899004

Итак, теперь Counter явно быстрее решений groupby, но все же медленнее версий iteritems dict и defaultdict.

Целью этих примеров является не создание оптимального решения. Дело в том, что часто не существует одного оптимального общего решения. Кроме того, существуют другие критерии эффективности. Требования к памяти будут существенно различаться между решениями, и по мере увеличения размера ввода требования к памяти могут стать основным фактором при выборе алгоритма.

Нижняя строка: все зависит и вам нужно измерить.

Ответ 6

Я получил наилучшие результаты с помощью модуля groupby от itertools с помощью этой функции, используя Python 3.5.2:

from itertools import groupby

a = [1, 2, 45, 55, 5, 4, 4, 4, 4, 4, 4, 5456, 56, 6, 7, 67]

def occurrence():
    occurrence, num_times = 0, 0
    for key, values in groupby(a, lambda x : x):
        val = len(list(values))
        if val >= occurrence:
            occurrence, num_times =  key, val
    return occurrence, num_times

occurrence, num_times = occurrence()
print("%d occurred %d times which is the highest number of times" % (occurrence, num_times))

Вывод:

4 occurred 6 times which is the highest number of times

Протестируйте с помощью модуля timeit от timeit.

Я использовал этот script для моего теста с number= 20000:

from itertools import groupby

def occurrence():
    a = [1, 2, 45, 55, 5, 4, 4, 4, 4, 4, 4, 5456, 56, 6, 7, 67]
    occurrence, num_times = 0, 0
    for key, values in groupby(a, lambda x : x):
        val = len(list(values))
        if val >= occurrence:
            occurrence, num_times =  key, val
    return occurrence, num_times

if __name__ == '__main__':
    from timeit import timeit
    print(timeit("occurrence()", setup = "from __main__ import occurrence",  number = 20000))

Выход (лучший):

0.1893607140000313

Ответ 7

Простой способ без каких-либо библиотек или наборов

def mcount(l):
  n = []                  #To store count of each elements
  for x in l:
      count = 0
      for i in range(len(l)):
          if x == l[i]:
              count+=1
      n.append(count)
  a = max(n)              #largest in counts list
  for i in range(len(n)):
      if n[i] == a:
          return(l[i],a)  #element,frequency
  return                  #if something goes wrong

Ответ 8

Я хочу добавить другое решение, которое выглядит красиво и быстро для коротких списков.

def mc(seq=L):
    "max/count"
    max_element = max(seq, key=seq.count)
    return (max_element, seq.count(max_element))

Вы можете сравнить это с кодом, предоставленным Ned Deily, который даст вам эти результаты для самого маленького тестового примера:

3.5.2 (default, Nov  7 2016, 11:31:36) 
[GCC 6.2.1 20160830] 

dict iteritems (4, 6) 0.2069783889998289
dict items (4, 6) 0.20462976200065896
defaultdict iteritems (4, 6) 0.2095775119996688
sort groupby generator expression (4, 6) 0.4473949929997616
sort groupby list comprehension (4, 6) 0.4367636879997008
counter (4, 6) 0.3618192010007988
max/count (4, 6) 0.20328268999946886

Но будьте осторожны, он неэффективен и, таким образом, становится очень медленным для больших списков!

Ответ 9

Ниже приведено решение, с которым я столкнулся, если в строке есть несколько символов, имеющих самую высокую частоту.

mystr = input("enter string: ")
#define dictionary to store characters and their frequencies
mydict = {}
#get the unique characters
unique_chars = sorted(set(mystr),key = mystr.index)
#store the characters and their respective frequencies in the dictionary
for c in unique_chars:
    ctr = 0
    for d in mystr:
        if d != " " and d == c:
            ctr = ctr + 1
    mydict[c] = ctr
print(mydict)
#store the maximum frequency
max_freq = max(mydict.values())
print("the highest frequency of occurence: ",max_freq)
#print all characters with highest frequency
print("the characters are:")
for k,v in mydict.items():
    if v == max_freq:
        print(k)

Вход: "привет люди"

Вывод:

{'o': 2, 'p': 2, 'h': 1, ' ': 0, 'e': 3, 'l': 3}

самая высокая частота появления: 3

символы:

e

l

Ответ 10

Простой и лучший код:

def max_occ(lst,x):
    count=0
    for i in lst:
        if (i==x):
            count=count+1
    return count

lst=[1, 2, 45, 55, 5, 4, 4, 4, 4, 4, 4, 5456, 56, 6, 7, 67]
x=max(lst,key=lst.count)
print(x,"occurs ",max_occ(lst,x),"times")

Выход: 4 происходит 6 раз

Ответ 11

Мой (простой) код (три месяца изучения Python):

def more_frequent_item(lst):
    new_lst = []
    times = 0
    for item in lst:
        count_num = lst.count(item)
        new_lst.append(count_num)
        times = max(new_lst)
    key = max(lst, key=lst.count)
    print("In the list: ")
    print(lst)
    print("The most frequent item is " + str(key) + ". Appears " + str(times) + " times in this list.")


more_frequent_item([1, 2, 45, 55, 5, 4, 4, 4, 4, 4, 4, 5456, 56, 6, 7, 67])

Выход будет:

In the list: 
[1, 2, 45, 55, 5, 4, 4, 4, 4, 4, 4, 5456, 56, 6, 7, 67]
The most frequent item is 4. Appears 6 times in this list.

Ответ 12

Если вы используете Python 3.4 или выше, вы можете использовать statistics.mode()

>>> import statistics
>>> L = [1, 2, 45, 55, 5, 4, 4, 4, 4, 4, 4, 5456, 56, 6, 7, 67] 
>>> statistics.mode(L)
4

Обратите внимание, что при этом будет выдано statistics.StatisticsError, если список пуст или если не существует только одного наиболее распространенного значения.

Ответ 13

может что-то вроде этого:

testList = [1, 2, 3, 4, 2, 2, 1, 4, 4] print(max(set(testList), key = testList.count))