Как найти наиболее распространенные элементы списка?
Учитывая следующий список
['Jellicle', 'Cats', 'are', 'black', 'and', 'white,', 'Jellicle', 'Cats',
'are', 'rather', 'small;', 'Jellicle', 'Cats', 'are', 'merry', 'and',
'bright,', 'And', 'pleasant', 'to', 'hear', 'when', 'they', 'caterwaul.',
'Jellicle', 'Cats', 'have', 'cheerful', 'faces,', 'Jellicle', 'Cats',
'have', 'bright', 'black', 'eyes;', 'They', 'like', 'to', 'practise',
'their', 'airs', 'and', 'graces', 'And', 'wait', 'for', 'the', 'Jellicle',
'Moon', 'to', 'rise.', '']
Я пытаюсь подсчитать, сколько раз каждое слово появляется и отображать верхние 3.
Однако я только ищу, чтобы найти тройку лучших, которые имеют первую букву, заглавные и игнорируют все слова, которые не имеют заглавной буквой.
Я уверен, что есть лучший способ, но я решил сделать следующее:
- поместите первое слово в список в другой список, называемый uniquewords
- удалить первое слово и все его дубликаты из исходного списка
- добавить новое первое слово в уникальные слова
- удалить первое слово и все его дубликаты из исходного списка.
- и т.д...
- пока исходный список не станет пустым....
- подсчитывает, сколько раз каждое слово в uniquewords появляется в исходном списке
- найдите топ-3 и распечатайте
Ответы
Ответ 1
Если вы используете более раннюю версию Python или у вас есть веская причина, чтобы свернуть свой собственный счетчик слов (я бы хотел его услышать!), вы можете попробовать следующий подход, используя dict
.
Python 2.6.1 (r261:67515, Feb 11 2010, 00:51:29)
[GCC 4.2.1 (Apple Inc. build 5646)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> word_list = ['Jellicle', 'Cats', 'are', 'black', 'and', 'white,', 'Jellicle', 'Cats', 'are', 'rather', 'small;', 'Jellicle', 'Cats', 'are', 'merry', 'and', 'bright,', 'And', 'pleasant', 'to', 'hear', 'when', 'they', 'caterwaul.', 'Jellicle', 'Cats', 'have', 'cheerful', 'faces,', 'Jellicle', 'Cats', 'have', 'bright', 'black', 'eyes;', 'They', 'like', 'to', 'practise', 'their', 'airs', 'and', 'graces', 'And', 'wait', 'for', 'the', 'Jellicle', 'Moon', 'to', 'rise.', '']
>>> word_counter = {}
>>> for word in word_list:
... if word in word_counter:
... word_counter[word] += 1
... else:
... word_counter[word] = 1
...
>>> popular_words = sorted(word_counter, key = word_counter.get, reverse = True)
>>>
>>> top_3 = popular_words[:3]
>>>
>>> top_3
['Jellicle', 'Cats', 'and']
Верхний совет. Интерактивный интерпретатор Python - ваш друг, когда вы хотите играть с таким алгоритмом. Просто введите его и посмотрите, как он идет, проверяя элементы на этом пути.
Ответ 2
В Python 2.7 и выше есть класс под названием Counter, который может вам помочь:
from collections import Counter
words_to_count = (word for word in word_list if word[:1].isupper())
c = Counter(words_to_count)
print c.most_common(3)
Результат:
[('Jellicle', 6), ('Cats', 5), ('And', 2)]
Я новичок в программировании, поэтому, пожалуйста, попробуйте сделать это самым простым способом.
Вместо этого вы можете сделать это, используя словарь с ключом, являющимся словом, и значением, являющимся счетчиком для этого слова. Сначала перебирайте слова, добавляя их в словарь, если их нет, или увеличивайте количество слов, если оно присутствует. Затем, чтобы найти верхнюю тройку, вы можете использовать простой алгоритм сортировки O(n*log(n))
и перенести первые три элемента из результата, или вы можете использовать алгоритм O(n)
, который сканирует список, запоминая только три верхних элемента.
Важным замечанием для новичков является то, что, используя встроенные классы, предназначенные для этой цели, вы можете сэкономить много работы и/или получить лучшую производительность. Хорошо быть знакомым со стандартной библиотекой и функциями, которые она предлагает.
Ответ 3
Чтобы просто вернуть список, содержащий наиболее распространенные слова:
from collections import Counter
words=["i", "love", "you", "i", "you", "a", "are", "you", "you", "fine", "green"]
most_common_words= [word for word, word_count in Counter(words).most_common(3)]
print most_common_words
это печатает:
['you', 'i', 'a']
3 в "most_common(3)
" указывает количество элементов для печати.
Counter(words).most_common()
возвращает список кортежей с каждым кортежем, имеющим слово в качестве первого члена, и частотой в качестве второго члена. Кортежи упорядочены по частоте слова.
`most_common = [item for item in Counter(words).most_common()]
print(str(most_common))
[('you', 4), ('i', 2), ('a', 1), ('are', 1), ('green', 1), ('love',1), ('fine', 1)]`
"word for word, word_counter in
", извлекает только первый член кортежа.
Ответ 4
Разве это просто...
word_list=['Jellicle', 'Cats', 'are', 'black', 'and', 'white,', 'Jellicle', 'Cats',
'are', 'rather', 'small;', 'Jellicle', 'Cats', 'are', 'merry', 'and',
'bright,', 'And', 'pleasant', 'to', 'hear', 'when', 'they', 'caterwaul.',
'Jellicle', 'Cats', 'have', 'cheerful', 'faces,', 'Jellicle', 'Cats',
'have', 'bright', 'black', 'eyes;', 'They', 'like', 'to', 'practise',
'their', 'airs', 'and', 'graces', 'And', 'wait', 'for', 'the', 'Jellicle',
'Moon', 'to', 'rise.', '']
from collections import Counter
c = Counter(word_list)
c.most_common(3)
Для вывода
[('Jellicle', 6), ('Cats', 5), ('are', 3)]
Ответ 5
NLTK удобен для многих языков обработки. У него есть встроенные методы распределения частот. Что-то вроде:
import nltk
fdist = nltk.FreqDist(your_list) # creates a frequency distribution from a list
most_common = fdist.max() # returns a single element
top_three = fdist.keys()[:3] # returns a list
Ответ 6
Простым, двухстрочным решением для этого, которое не требует дополнительных модулей, является следующий код:
lst = ['Jellicle', 'Cats', 'are', 'black', 'and','white,',
'Jellicle', 'Cats','are', 'rather', 'small;', 'Jellicle',
'Cats', 'are', 'merry', 'and','bright,', 'And', 'pleasant',
'to','hear', 'when', 'they', 'caterwaul.','Jellicle',
'Cats', 'have','cheerful', 'faces,', 'Jellicle',
'Cats','have', 'bright', 'black','eyes;', 'They', 'like',
'to', 'practise','their', 'airs', 'and', 'graces', 'And',
'wait', 'for', 'the', 'Jellicle','Moon', 'to', 'rise.', '']
lst_sorted=sorted([ss for ss in set(lst) if len(ss)>0 and ss.istitle()],
key=lst.count,
reverse=True)
print lst_sorted[0:3]
Вывод:
['Jellicle', 'Cats', 'And']
Термин в квадратных скобках возвращает все уникальные строки в списке, которые не пусты и начинаются с заглавной буквы. Затем функция sorted()
сортирует их по тому, как часто они появляются в списке (с помощью клавиши lst.count
) в обратном порядке.
Ответ 7
Простой способ сделать это будет (если ваш список находится в 'l'):
>>> counter = {}
>>> for i in l: counter[i] = counter.get(i, 0) + 1
>>> sorted([ (freq,word) for word, freq in counter.items() ], reverse=True)[:3]
[(6, 'Jellicle'), (5, 'Cats'), (3, 'to')]
Полный образец:
>>> l = ['Jellicle', 'Cats', 'are', 'black', 'and', 'white,', 'Jellicle', 'Cats', 'are', 'rather', 'small;', 'Jellicle', 'Cats', 'are', 'merry', 'and', 'bright,', 'And', 'pleasant', 'to', 'hear', 'when', 'they', 'caterwaul.', 'Jellicle', 'Cats', 'have', 'cheerful', 'faces,', 'Jellicle', 'Cats', 'have', 'bright', 'black', 'eyes;', 'They', 'like', 'to', 'practise', 'their', 'airs', 'and', 'graces', 'And', 'wait', 'for', 'the', 'Jellicle', 'Moon', 'to', 'rise.', '']
>>> counter = {}
>>> for i in l: counter[i] = counter.get(i, 0) + 1
...
>>> counter
{'and': 3, '': 1, 'merry': 1, 'rise.': 1, 'small;': 1, 'Moon': 1, 'cheerful': 1, 'bright': 1, 'Cats': 5, 'are': 3, 'have': 2, 'bright,': 1, 'for': 1, 'their': 1, 'rather': 1, 'when': 1, 'to': 3, 'airs': 1, 'black': 2, 'They': 1, 'practise': 1, 'caterwaul.': 1, 'pleasant': 1, 'hear': 1, 'they': 1, 'white,': 1, 'wait': 1, 'And': 2, 'like': 1, 'Jellicle': 6, 'eyes;': 1, 'the': 1, 'faces,': 1, 'graces': 1}
>>> sorted([ (freq,word) for word, freq in counter.items() ], reverse=True)[:3]
[(6, 'Jellicle'), (5, 'Cats'), (3, 'to')]
С простыми я имею в виду работу почти в каждой версии python.
Если вы не понимаете некоторые функции, используемые в этом примере, вы всегда можете сделать это в интерпретаторе (после вставки кода выше):
>>> help(counter.get)
>>> help(sorted)
Ответ 8
Ответ от @Mark Byers лучше всего, но если вы используете версию Python < 2.7 (но не менее 2,5, что в наши дни довольно устарело), вы можете просто реплицировать функциональность класса Counter через defaultdict (в противном случае для python < 2,5 необходимы три дополнительные строки кода до d [i] + = 1, как в ответе @Johnnysweb).
from collections import defaultdict
class Counter():
ITEMS = []
def __init__(self, items):
d = defaultdict(int)
for i in items:
d[i] += 1
self.ITEMS = sorted(d.iteritems(), reverse=True, key=lambda i: i[1])
def most_common(self, n):
return self.ITEMS[:n]
Затем вы используете класс точно так же, как в ответе Марка Байера, т.е.:
words_to_count = (word for word in word_list if word[:1].isupper())
c = Counter(words_to_count)
print c.most_common(3)
Ответ 9
Если вы используете Count или создали свой собственный стиль Count-style и хотите показать имя элемента и его количество, вы можете перебирать вокруг словаря так:
top_10_words = Counter(my_long_list_of_words)
# Iterate around the dictionary
for word in top_10_words:
# print the word
print word[0]
# print the count
print word[1]
или выполнить итерацию в шаблоне:
{% for word in top_10_words %}
<p>Word: {{ word.0 }}</p>
<p>Count: {{ word.1 }}</p>
{% endfor %}
Надеюсь, это поможет кому-то
Ответ 10
Существует два стандартных способа поиска наиболее часто встречающихся значений в списке:
statistics.mode
:
from statistics import mode
most_common = mode([3, 2, 2, 2, 1, 1]) # 2
most_common = mode([3, 2]) # StatisticsError: no unique mode
- Вызывает исключение, если нет единственного наиболее частого значения
- Возвращает только одно наиболее частое значение
collections.Counter.most_common
:
from collections import Counter
most_common, count = Counter([3, 2, 2, 2, 1, 1]).most_common(2) # 2, 3
(most_common_1, count_1), (most_common_2, count_2) = Counter([3, 2, 2]).most_common(2) # (2, 2), (3, 1)
- Может возвращать несколько наиболее частых значений
- Также возвращает количество элементов
Таким образом, в случае вопроса, второй будет правильным выбором. Как примечание стороны, оба идентичны с точки зрения работы.