Site icon 8HOST.COM

Визуализация частоты употребления слов с помощью matplotlib и Python 3

Текстовые данные существуют во многих различных формах (от социальных сетей до электронной почты). Анализируя и визуализируя текстовые данные, вы можете отследить общие тенденции написания и восприятия текста.

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

Требования

Чтобы настроить среду разработки, обратитесь к статьям:

1: Файл программы

Установив библиотеку matplotlib, вы можете приступать к созданию проекта.

При помощи любого удобного редактора создайте файл word_freq.py. Это будет главный файл программы.

Импортируйте в программу библиотеку matplotlib и класс pyplot (используйте псевдоним plt). В целом plt объявляется как глобальная переменная, которая будет использоваться в сценарии.

import matplotlib.pyplot as plt

Читайте также: Импорт модулей в Python 3

Далее нужно импортировать стандартные пакеты Python, с помощью которых можно настроить и принимать входные данные командной строки. Важно отметить пакет argparse: он позволяет собирать информацию командной строки и включает текст справки для пользователя.

Чтобы импортировать эти пакеты, добавьте в файл word_freq.py такие строки:

import matplotlib.pyplot as plt
import sys
import operator
import argparse

Затем создайте основной метод и вызов. В основном методе будет находиться большая часть кода программы.

import matplotlib.pyplot as plt
import sys
import operator
import argparse
def main():
if __name__ == "__main__":
main()

Базовый файл программы готов.

2: Настройка аргументов

Теперь нужно создать аргументы командной строки и сократить их в переменной для быстрого доступа.

Читайте также: Использование переменных в Python 3

В основном методе создайте переменную parser и присвойте ей конструктор argparse по умолчанию. Затем нужно присвоить ей аргументы – слова, которые нужно найти в файле, и файл, в котором нужно выполнить поиск (это будет файл .txt).

...
def main():
parser = argparse.ArgumentParser()
parser.add_argument(
"word",
help="the word to be searched for in the text file."
)
parser.add_argument(
"filename",
help="the path to the text file to be searched through"
)
if __name__ == "__main__":
main()

Первым аргументом в методе является слово, которое будет помещено в командную строку. Второй аргумент, help= “…”, предоставляет пользователю некоторую информацию о том, как должен выглядеть аргумент командной строки.

Сохраните эти аргументы в другую переменную, args:

...
def main():
parser = argparse.ArgumentParser()
parser.add_argument(
"word",
help="the word to be searched for in the text file."
)
parser.add_argument(
"filename",
help="the path to the text file to be searched through"
)
args = parser.parse_args()
if __name__ == "__main__":
main()

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

...
def main():
...
args = parser.parser_args()
try:
open(args.filename)
except FileNotFoundError:
sys.stderr.write("Error: " + args.filename + " does not exist!")
sys.exit(1)
if __name__ == "__main__":
main()

Строка sys.exit(1) сообщит пользователю о проблемах в коде, из-за которых он не был выполнен.

Теперь программа может принимать аргументы командной строки.

3: Парсинг файла

Теперь нужно прочитать файл, подсчитать и зарегистрировать, сколько раз в нём встречается то или иное слово, и сохранить данные в словарь.

Добавьте в файл функцию word_freq(), которая принимает два аргумента командной строки (слово и имя файла), а затем вызовите эту функцию в main().

...
def main():
...
word_freq(args.word, args.filename)
def word_freq(word, filename):
if __name__ == "__main__":
main()

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

...
def word_freq( word, filename ):
doc = {}
if __name__ == "__main__":
main()

Далее нужно настроить итерацию файла. Для этого используйте вложенный цикл for.

Читайте также: Циклы for в Python 3

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

Второй цикл for рассматривает полученный массив и проверяет, есть он в словаре или нет. Если массив уже встречается в словаре, он добавляет к счётчику единицу. Если массива в словаре нет, цикл создаёт новую запись и ставит в счётчике 1.

...
def word_freq(word, filename):
doc = {}
for line in open(filename):
split = line.split(' ')
for entry in split:
if (doc.__contains__(entry)):
doc[entry] = int(doc.get(entry)) + 1
else:
doc[entry] = 1
if __name__ == "__main__":
main()

Напомним, что метод main() настраивает входные данные командной строки и передаёт их функции word_freq(). Функция word_freq() должна получать из командной строки слово и имя файла и сохранять каждое уникальное слово, найденное в файле.

4: Хранение и сортировка данных

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

...
def word_freq(word, filename):
...
else:
doc[entry] = 1
if (not word in doc):
sys.stderr.write("Error: " + word + " does not appear in " + filename)
sys.exit(1)
if __name__ == "__main__":
main()

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

Для начала нужно отсортировать данные в словаре по частоте употребления слова в порядке убывания и инициализировать переменные для дальнейшей работы. Сортировка данных необходима для построения графика.

...
def word_freq(word, filename):
...
if (not word in doc):
sys.stderr.write("Error: " + word + " does not appear in " + filename)
sys.exit(1)
sorted_doc = (sorted(doc.items(), key = operator.itemgetter(1)))[::-1] just_the_occur = [] just_the_rank = [] word_rank = 0
word_frequency = 0
if __name__ == "__main__":
main()

Обратите внимание на переменные just_the_occur и just_the_rank. Первая содержит данные о том, сколько раз встречается то или иное слово, а вторая отображает место слова в рейтинге.

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

...
def word_freq( word, filename ):
...
sortedDoc = (sorted(doc.items(), key = operator.itemgetter(1)))[::-1] just_the_occur = [] just_the_rank = [] word_rank = 0
word_frequency = 0
entry_num = 1
for entry in sorted_doc:
if (entry[0] == word):
word_rank = entryNum
word_frequency = entry[1] just_the_rank.append(entry_num)
entry_num += 1
just_the_occur.append(entry[1])
if __name__ == "__main__":
main()

Переменные just_the_occur и just_the_rank должны быть одной длины, иначе matplotlib не сможет построить график.

Также нужно добавить в цикл выражение if, чтобы найти слово и извлечь данные о нём.

5: Построение графика

Теперь можно использовать переменную plt, созданную ещё в начале руководства. Чтобы собрать график, нужно указать заголовок, метки осей x и y, масштаб и тип графика.

Метки осей должны быть описательными (хотя это, конечно, не обязательно, вы можете выбрать любые метки).

...
def word_freq( word, filename ):
...
just_the_rank.append(entry_num)
entry_num += 1
just_the_occur.append(entry[1])
plt.title("Word Frequencies in " + filename)
plt.ylabel("Total Number of Occurrences")
plt.xlabel("Rank of word(\"" + word + "\" is rank " + str(word_rank) + ")")
plt.loglog(
just_the_rank,
just_the_occur,
basex=10
)
plt.scatter(
[word_rank],
[word_frequency],
color="orange",
marker="*",
s=100,
label=word
)
plt.show()
if __name__ == "__main__":
main()

Функция plt.title определяет заголовок, функции plt.ylabel() и plt.xlabel() – метки осей.

Функция plt.loglog() принимает значения just_the_rank и just_the_occur и присваивает их осям х и у соответственно.

Нужная точка на графике будет отмечена оранжевой звёздочкой и подписана искомым словом.

Функция plt.show() отображает график.

Теперь код программы полностью готов.

6: Запуск программы

Чтобы проверить работу программы, нам понадобится тестовый файл. Для примера загрузите что-нибудь с сайта бесплатных электронных книг Project Gutenberg.

К примеру, загрузим роман A Tale of Two Cities; файл cities.txt можно загрузить с помощью curl в текущий каталог, в котором хранится сценарий Python.

curl http://www.gutenberg.org/files/98/98-0.txt --output cities.txt

Чтобы запустить программу, передайте в качестве параметров любое слово (например, fish) и имя файла.

python word_freq.py fish cities.txt

Если код не содержит ошибок, на экране вы увидите график, отображающий частоту использования каждого слова в файле; место слова fish в этом графике будет отмечено оранжевой звёздочкой.

Читайте также: Работа с текстовыми файлами в Python 3

Полный код программы и рекомендуемые улучшения

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

Полный код программы выглядит так:

import matplotlib.pyplot as plt
import sys
import operator
import argparse
def main():
parser = argparse.ArgumentParser()
parser.add_argument(
"word",
help="the word to be searched for in the text file."
)
parser.add_argument(
"filename",
help="the path to the text file to be searched through"
)
args = parser.parse_args()
try:
open(args.filename)
except FileNotFoundError:
# Custom error print
sys.stderr.write("Error: " + args.filename + " does not exist!")
sys.exit(1)
word_freq(args.word, args.filename)
def word_freq(word, filename):
doc = {}
for line in open(filename):
# Assume each word is separated by a space
split = line.split(' ')
for entry in split:
if (doc.__contains__(entry)):
doc[entry] = int(doc.get(entry)) + 1
else:
doc[entry] = 1
if (word not in doc):
sys.stderr.write("Error: " + word + " does not appear in " + filename)
sys.exit(1)
sorted_doc = (sorted(doc.items(), key=operator.itemgetter(1)))[::-1] just_the_occur = [] just_the_rank = [] word_rank = 0
word_frequency = 0
entry_num = 1
for entry in sorted_doc:
if (entry[0] == word):
word_rank = entry_num
word_frequency = entry[1] just_the_rank.append(entry_num)
entry_num += 1
just_the_occur.append(entry[1])
plt.title("Word Frequencies in " + filename)
plt.ylabel("Total Number of Occurrences")
plt.xlabel("Rank of word(\"" + word + "\" is rank " + str(word_rank) + ")")
plt.loglog(just_the_rank, just_the_occur, basex=10)
plt.scatter(
[word_rank],
[word_frequency],
color="orange",
marker="*",
s=100,
label=word
)
plt.show()
if __name__ == "__main__":
main()

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

Или же программа могла бы сравнивать длину двух слов и сохранять полученный результат в словарь.