Вы можете быть удивлены термином Zipf . Чтобы понять, что мы подразумеваем под этим термином, нам нужно сначала определить закон Ципфа . Не волнуйся, я сделаю все просто.
Закон Ципфа
Закон Ципфа просто гласит, что, учитывая некоторый корпус (большой и структурированный набор текстов) высказываний на естественном языке, встречаемость наиболее часто встречающегося слова будет примерно в два раза чаще, чем второе наиболее часто встречаемое слово, в три раза больше, чем третье наиболее часто употребляемое слово, четыре раза как четвертое по частоте слово и так далее.
Давайте посмотрим на пример этого. Если вы загляните в « Коричневый корпус» американского английского, вы заметите, что наиболее частое слово — это (69 971 вхождение). Если мы посмотрим на второе самое частое слово, то есть, мы заметим, что оно встречается 36 411 раз.
На это слово приходится около 7% слов Brown Corpus (69 971 из немногим более 1 миллиона слов). Если мы подойдем к слову о , мы заметим, что на его долю приходится около 3,6% корпуса (около половины). Таким образом, мы можем заметить, что закон Ципфа относится к этой ситуации.
Таким образом, закон Ципфа пытается сказать нам, что небольшое количество предметов обычно составляет основную часть действий, которые мы наблюдаем. Например, небольшое количество заболеваний (рак, сердечно-сосудистые заболевания) составляют основную часть смертей. Это также относится к словам, которые составляют основную часть всех вхождений слов в литературе, и многих других примеров в нашей жизни.
Подготовка данных
Прежде чем двигаться дальше, позвольте мне направить вас к данным, которые мы будем использовать для экспериментов в нашем руководстве. Наши данные на этот раз будут из Национальной медицинской библиотеки . Мы будем загружать отсюда файл ASCII MeSH (заголовок медицинской темы). В частности, d2016.bin (28 МБ).
Я не буду вдаваться в детали при описании этого файла, поскольку он выходит за рамки данного руководства, и нам просто нужно поэкспериментировать с нашим кодом.
Построение Программы
После того, как вы загрузили данные в приведенном выше разделе, давайте теперь приступим к созданию нашего скрипта Python, который найдет распределение данных d2016.bin
в d2016.bin
.
Первый нормальный шаг — open
файл:
1
|
open_file = open(‘d2016.bin’, ‘r’)
|
Чтобы выполнить необходимые операции над файлом bin
, нам нужно загрузить файл в строковую переменную. Это может быть просто достигнуто с помощью функции read()
следующим образом:
1
|
file_to_string = open_file.read()
|
Поскольку мы будем искать какой-то шаблон (то есть слова), в игру вступают регулярные выражения . Таким образом, мы будем использовать модуль re
Python.
На данный момент мы уже прочитали файл bin
и загрузили его содержимое в строковую переменную. Найти распределение Zipf означает найти частоту встречаемости слов в bin
файле. Таким образом, регулярное выражение будет использоваться для поиска слов в файле.
Метод, который мы будем использовать для сопоставления, — это findall()
. Как упомянуто в документации модуля re
о findall()
, метод будет:
Возвратите все неперекрывающиеся совпадения шаблона в строке в виде списка строк. Строка сканируется слева направо, и совпадения возвращаются в указанном порядке. Если в шаблоне присутствует одна или несколько групп, вернуть список групп; это будет список кортежей, если шаблон имеет более одной группы. Пустые совпадения включаются в результат, если они не касаются начала другого совпадения.
Мы хотим написать регулярное выражение, которое найдет все отдельные слова в текстовой строковой переменной. Регулярное выражение, которое может выполнить эту задачу:
1
|
\b[A-Za-z][az]{2,10}\b
|
где \b
является якорем для границ слова . В Python это можно представить следующим образом:
1
|
words = re.findall(r'(\b[A-Za-z][az]{2,9}\b)’, file_to_string)
|
Это регулярное выражение в основном говорит нам найти все слова, которые начинаются с буквы (верхнего или нижнего регистра) и сопровождаются последовательностью букв, состоящей как минимум из 2
символов и не более 9
символов. Другими словами, размер слов, которые будут включены в вывод, будет варьироваться от 3
до 10
символов.
Теперь мы можем запустить цикл, который предназначен для вычисления частоты появления каждого слова:
1
2
3
|
for word in words:
count = frequency.get(word,0)
frequency[word] = count + 1
|
Здесь, если слово еще не найдено в списке слов, вместо KeyError
, возвращается значение по умолчанию 0
. В противном случае, счетчик увеличивается на 1
, представляя количество случаев, когда слово встречалось в списке до сих пор.
Наконец, мы напечатаем пару ключ-значение в словаре , показывая слово (ключ) и количество раз, которое оно появилось в списке (значение):
1
2
|
for key, value in reversed(sorted(frequency.items(), key = itemgetter(1))):
print key, value
|
Эта sorted(frequency.items(), key = itemgetter(1))
часть sorted(frequency.items(), key = itemgetter(1))
сортирует выходные данные по значению в порядке возрастания, то есть показывает слова от наименее частого вхождения до наиболее частого вхождения. Чтобы перечислить наиболее часто встречающиеся слова в начале, мы используем метод reversed()
.
Собираем все вместе
Пройдя через различные строительные блоки программы, давайте посмотрим, как все это выглядит вместе:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
import re
from operator import itemgetter
frequency = {}
open_file = open(‘d2016.bin’, ‘r’)
file_to_string = open_file.read()
words = re.findall(r'(\b[A-Za-z][az]{2,9}\b)’, file_to_string)
for word in words:
count = frequency.get(word,0)
frequency[word] = count + 1
for key, value in reversed(sorted(frequency.items(), key = itemgetter(1))):
print key, value
|
Я покажу здесь первые десять слов и их частоты, возвращаемые программой:
01
02
03
04
05
06
07
08
09
10
|
the 42602
abcdef 31913
and 30699
abbcdef 27016
was 17430
see 16189
with 14380
under 13127
for 9767
abcdefv 8694
|
Из этого распределения Zipf мы можем проверить закон Zipf в том смысле, что некоторые слова (высокочастотные слова) представляют собой большую часть слов, как мы можем видеть выше and
for
. Это также относится к последовательностям abcdef
, abbcdef
и abcdefv
которые являются очень частыми буквенными последовательностями, имеющими некоторое значение, характерное для этого файла.
Вывод
В этом уроке мы увидели, как Python облегчает работу со статистическими понятиями, такими как закон Ципфа. Python особенно удобен при работе с большими текстовыми файлами, что потребует много времени и усилий, если мы найдем дистрибутив Zipf вручную. Как мы увидели, мы смогли быстро загрузить, проанализировать и найти распределение Zipf файла размером 28 МБ. Не говоря уже о простоте сортировки результатов благодаря словарям Python.