Программа подсчета частоты слов на Python варианты реализации

Раздел: Прочее -> Практические примеры

Различные подходы к реализации программы подсчета частоты слов

Эта статья посвящена одной программе на Python - подсчету частоты слов в тексте. Показаны различные варианты решения, от простого до более сложного, с пояснениями и разбором типичных ошибок.

Основной рекомендуемый подход

Данный вариант использует модуль collections.Counter, фильтрацию пунктуации и нормализацию регистра. Он наиболее сбалансирован по простоте и производительности.

import re
from collections import Counter

def word_frequency(text):
    # удаляем пунктуацию, приводим к нижнему регистру
    words = re.findall(r'\b\w+\b', text.lower())
    return Counter(words)

text = "Python - это язык программирования. Python популярен!"
result = word_frequency(text)
print(result)

1 программа на python (одна программа на python)

Counter({'python': 2, 'это': 1, 'язык': 1, 'программирования': 1, 'популярен': 1})

Пояснение: re.findall(r'\b\w+\b', text.lower()) находит все последовательности букв и цифр (слова) в нижнем регистре, игнорируя знаки препинания. Затем Counter подсчитывает количество вхождений.

Типичные ошибки:

  • Забыть про регистр - слова "Python" и "python" считаются разными. Решается вызовом .lower().
  • Использовать str.split() без очистки пунктуации - слова с точкой или запятой будут отличны от чистых слов. Регулярное выражение решает эту проблему.
  • Для очень больших файлов чтение всего текста в память неэффективно - следует читать построчно (см. вариант с файлами).

Цель: получение быстрого и чистого результата для текстов среднего размера. Используется в анализе логов, обработке отзывов, подготовке данных для NLP.

Как реализовать ручной подсчет без Counter?

def word_frequency_manual(text):
    frequency = {}
    words = text.lower().split()
    for word in words:
        word = word.strip('.,!?;:"()[]{}')
        if word:
            frequency[word] = frequency.get(word, 0) + 1
    return frequency

print(word_frequency_manual("Hello, hello! World."))
{'hello': 2, 'world': 1}

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

Проблемы:

  • Метод strip() удаляет только символы с начала и конца строки, но не внутри (например, "don't" останется как "don't"). Если нужно разделить по всем небуквенным символам, лучше использовать регулярные выражения.
  • Высокая сложность при большом количестве символов пунктуации - нужно перечислять их все.

Цель: обучение основам работы со словарями и строками. Подходит для начинающих.

Как обработать текст из файла построчно для больших данных?

from collections import Counter
import re

def word_frequency_from_file(filename):
    counter = Counter()
    with open(filename, 'r', encoding='utf-8') as f:
        for line in f:
            words = re.findall(r'\b\w+\b', line.lower())
            counter.update(words)
    return counter

# Пример с файлом 'sample.txt'
result = word_frequency_from_file('sample.txt')
print(result.most_common(5))

Пояснение: файл читается построчно, что позволяет обрабатывать даже гигабайтные файлы без загрузки в память целиком. counter.update() добавляет новые вхождения.

Ошибки:

  • Забыть указать кодировку encoding='utf-8' - получится ошибка UnicodeDecodeError при наличии нелатинских символов.
  • Не обработать пустые строки - re.findall вернет пустой список, это безопасно.

Цель: работа с большими файлами (логи сервера, корпусы текстов).

Как добавить поддержку аргументов командной строки?

import argparse
import re
from collections import Counter

def main():
    parser = argparse.ArgumentParser(description='Подсчет частоты слов')
    parser.add_argument('file', help='путь к текстовому файлу')
    parser.add_argument('-n', '--top', type=int, default=10, help='количество выводимых слов')
    args = parser.parse_args()

    with open(args.file, 'r', encoding='utf-8') as f:
        counter = Counter()
        for line in f:
            words = re.findall(r'\b\w+\b', line.lower())
            counter.update(words)

    for word, count in counter.most_common(args.top):
        print(f"{word}: {count}")

if __name__ == '__main__':
    main()

Пояснение: модуль argparse позволяет задавать имя файла и опцию --top из командной строки. Это делает программу пригодной для реального использования в конвейерах.

Проблемы:

  • Если файл не существует, программа упадет с FileNotFoundError - требуется обработка исключений.
  • При указании неверного ключа argparse выведет справку.

Цель: создание утилиты командной строки для автоматизации.

Как исключить стоп-слова (предлоги, союзы)?

import re
from collections import Counter

STOP_WORDS = {'и', 'в', 'на', 'с', 'по', 'для', 'а', 'но', 'да', 'или', 'не', 'так', 'что', 'как', 'это', 'то', 'все', 'она', 'его', 'их', 'мы', 'вы', 'у', 'о', 'об', 'от', 'из', 'за', 'до', 'без', 'над', 'под', 'при', 'через', 'около', 'после', 'во', 'ко', 'со', 'же', 'бы', 'ли', 'ни', 'чем', 'чтобы', 'потому', 'поэтому'}

def word_frequency_no_stop(text):
    words = re.findall(r'\b\w+\b', text.lower())
    return Counter(word for word in words if word not in STOP_WORDS)

print(word_frequency_no_stop("Python и Java - это языки программирования. Python популярен."))
Counter({'python': 2, 'java': 1, 'языки': 1, 'программирования': 1, 'популярен': 1})

Пояснение: стоп-слова отфильтровываются на лету с помощью генераторного выражения. Список стоп-слов можно загрузить из файла.

Замечание:

Стоп-слова зависят от языка и задачи. Иногда удаление предлогов ухудшает анализ (например, в поиске фраз).

Цель: очистка текста для последующего анализа (облако тегов, кластеризация).

Расширенные примеры и нестандартные решения

Помимо базовых вариантов, для одной программы на Python можно применять различные расширения. Ниже приведены несколько подробных примеров с кодом и результатами.

Использование регулярных выражений с захватом всех слов (включая апострофы)

Пример
import re
from collections import Counter

text = "don't can't "isn't" it's a cat's"
words = re.findall(r"\b[\w']+\b", text.lower())
print(Counter(words))
Counter({"don't": 1, "can't": 1, "isn't": 1, "it's": 1, "a": 1, "cat's": 1})

Пояснение: шаблон \b[\w']+\b позволяет включать апостроф в состав слова. Это полезно для обработки английского языка.

Подсчет биграмм (пар слов)

Пример
import re
from collections import Counter

def bigrams(text):
    words = re.findall(r'\b\w+\b', text.lower())
    return Counter(zip(words, words[1:]))

text = "Python это язык Python это инструмент"
result = bigrams(text)
for bigram, count in result.most_common():
    print(f"{' '.join(bigram)}: {count}")
python это: 2
это язык: 1
язык python: 1
это инструмент: 1

Пояснение: zip(words, words[1:]) создает пары последовательных слов. Counter подсчитывает количество каждой пары. Аналогично можно считать триграммы.

Вывод результата в порядке убывания с ранжированием

Пример
from collections import Counter
import re

text = "яблоко апельсин яблоко банан яблоко банан"
words = re.findall(r'\b\w+\b', text.lower())
counter = Counter(words)
sorted_words = counter.most_common()
for rank, (word, cnt) in enumerate(sorted_words, 1):
    print(f"{rank}. {word}: {cnt}")
1. яблоко: 3
2. банан: 2
3. апельсин: 1

Пояснение: метод most_common() возвращает список кортежей, отсортированных по убыванию частоты. Функция enumerate добавляет ранжирование.

Экспорт результата в CSV

Пример
import csv
import re
from collections import Counter

text = "кот собака кот мышь кот"
words = re.findall(r'\b\w+\b', text.lower())
counter = Counter(words)

with open('frequency.csv', 'w', newline='', encoding='utf-8') as f:
    writer = csv.writer(f)
    writer.writerow(['Word', 'Frequency'])
    writer.writerows(counter.most_common())

print("CSV файл создан")
CSV файл создан

Содержимое frequency.csv:

Word,Frequency
кот,2
собака,1
мышь,1

Пояснение: модуль csv упрощает запись таблицы. Данные можно открыть в Excel или Google Sheets.

Визуализация топ-10 слов с помощью matplotlib

Пример
import matplotlib.pyplot as plt
import re
from collections import Counter

text = "яблоко яблоко груша груша груша слива персик персик абрикос манго киви лимон лайм"
words = re.findall(r'\b\w+\b', text.lower())
top = Counter(words).most_common(10)

words_list = [pair[0] for pair in top]
counts = [pair[1] for pair in top]

plt.bar(words_list, counts)
plt.xlabel('Слова')
plt.ylabel('Частота')
plt.title('Топ-10 слов')
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()

Пояснение: график строится с помощью matplotlib. Перед запуском убедитесь, что библиотека установлена. Результат (описание) - появляется окно с гистограммой.

одна программа на Python - comments

En
1 программа на python (python)