Статистика почтовых систем




Итак, наш шаблон проверки работает. Давайте решим следующую задачу: необходимо посчитать количество адресов в файле email_base.csv в разбивке по почтовым доменам. Т. е. посчитать сколько адресов принадлежат yandex.ru, сколько - gmail.com итд. А если адрес не похож на email, то необходимо посчитать количество таких строк как 'wrong email'

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

pattern = '([\w\.-]+)@([\w]+(\.ru|\.com))'

В поиске нам поможет метод search. Перебор результатов можно делать с помощью метода group, в качестве аргумента пишем номер группы в скобках:

# то что стоит в первых скобках

re.search(pattern, 'username@yandex.ru').group(1)

Результат: 'username'

# то что стоит во вторых скобках

re.search(pattern, 'username@yandex.ru').group(2)

Результат: 'yandex.ru'

# то что стоит во внутренних скобках

re.search(pattern, 'username@yandex.ru').group(3)

Результат: '.ru'

Теперь оформим проверку соответствия регулярному выражению в функцию. Если адрес не подходит под шаблон, то ставим 'wrong email':

def get_email_domain(row):

if re.match(pattern, row['email']):

return re.search(pattern, row['email']).group(2)

 

else:

return 'wrong email'

Применяем функцию к датафрейму email и пишем результат в столбец 'domain':

emails['domain'] = emails.apply(get_email_domain, axis = 1)

emails.head()

Теперь можем получить распределение почтовых систем для нашей базы:

%matplotlib inline

emails['domain'].hist()

Упражнение

Какое количество строк содержит некорректные email-адреса в таблице emails?

нет ответа

Выделение email-адресов из текста

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

text = 'Андрей Марков страхование markov_chains@yandex.ru. Мария Кюри технологии mary_decay@gmail.com Петр Капица онлайн-образование study-hard@rambler.ru'

Шаблон с прошлого шага:

pattern = '([\w\.-]+)@([\w]+(\.ru|\.com))'

Для решения этой задачи используем метод findall:

re.findall(pattern, text)

Результат:

[('markov_chains', 'yandex.ru', '.ru'),

('mary_decay', 'gmail.com', '.com'),

('study-hard', 'rambler.ru', '.ru')]

Мы получили набор групп group шаблона pattern. Давайте изменим порядок скобок, чтобы не разделять имя пользователя и домен:

pattern = '([\w\.-]+@[\w]+(\.ru|\.com))'

Посмотрим как изменился результат:

re.findall(pattern, text)

Результат:

[('markov_chains@yandex.ru', '.ru'),

('mary_decay@gmail.com', '.com'),

('study-hard@rambler.ru', '.ru')]

Теперь в первом элементе каждой строки выводится искомый email-адрес. Запишем итоговый алгоритм:

for address in re.findall(pattern, text):

print(address[0])

Результат:

markov_chains@yandex.ru

mary_decay@gmail.com

study-hard@rambler.ru

Упражнение

Необходимо получить из текста названия почтовых доменов. Т. е. yandex, gmail, rambler. Как нужно изменить шаблон регулярного выражения, чтобы выделить эти названия из текста?

([\w\.-]+@([\w]+)(\.ru|\.com)) (([\w\.-]+)@[\w]+(\.ru|\.com)) это невозможно

- Этот вопрос оставлен без ответа.

Постановка задачи

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

Файл с отзывами texts_opinions.txt

Файл с отзывами имеет кодировку UTF-8 и может некорректно отображаться при открытии в браузере.

Для классификации для каждого отзыва будем использовать следующий алгоритм:

  1. Предварительно составляем список основ слов, которые характеризуют положительные и отрицательные отзывы. Используем SnowballStemmer библиотеки NLTK (можно было использовать Pymystem, сейчас для простоты используем NLTK).
  2. Разбиваем текст отзыва на отдельные слова (здесь нам заранее придется удалить все знаки препинания).
  3. Заменяем каждое слово на его основу с помощью SnowballStemmer библиотеки NLTK.
  4. Ищем основу каждого слова отзыва среди основ слов из пункта 1. Считаем каких слов получилось больше - из списка "положительных" или "отрицательных" слов. Если таких слов в отзыве не нашлось или их число совпало, то возвращаем 'undef'.

После классификации отзывов мы можем сверить наш результат с "правильной" классификацией texts_ratings.txt, которую выставляли сами пользователи, когда писали эти отзывы.

Файл texts_ratings.txt

Несколько замечаний:

  1. Сейчас мы не рассматриваем качество и правдивость составленных отзывов. Наша задача - научиться пользоваться инструментами для подобных задач.
  2. Существует множество алгоритмов решения этой задачи, в том числе с помощью машинного обучения. Абсолютное большинство из них начинаются также как и наш - со стемминга или лемматизации исходных текстов.
  3. Аналогичный подход может сильно помочь вам в задачах фильтрации данных по словам.

Разбивка на слова

Итак, сначала составим список основ слов, которые характерны для положительных и отрицательных отзывов. Чтобы не учитывать их многочисленные формы используем стеммер NLTK. Например, найдем основу слова "благодарны":

from nltk.stem import SnowballStemmer

snowball_stemmer = SnowballStemmer("russian")

snowball_stemmer.stem('благодарны')

Результат:

'благодарн'

Аналогичную основу будут иметь многие вариации этого слова:

for word in ['благодарность', 'благодарностью', 'благодарны']:

print(snowball_stemmer.stem(word))

Результат:

благодарн

благодарн

благодарн

Мы взяли несколько простых вариантов "положительных" и "отрицательных" наборов слов, чтобы получить самый простой классификатор. Запишем их в файл params.yaml.

Основы слов params.yaml

Теперь напишем алгоритм классификатора. Сначала импортируем список слов в переменную params:

from yaml import load

params = load(open('params.yaml', mode = 'r', encoding = 'utf-8'))

Сначала необходимо удалить из текста знаки препинания, чтобы его можно легко было разбить на слова через пробел. Воспользуемся методом translate. Метод берет список знаков препинания symbols и применяет к ним метод translate. При этом заменяя их на пробелы. Для этого мы заводим строку spaces из такого же количества пробелов, что и symbols:

def clear_punctuation(text):

"""Удаление знаком пунктуации из текста text"""

symbols = '.,!()"<>'

spaces = ' ' * len(symbols)

return text.translate(text.maketrans(symbols, spaces))

Проверяем как работает:

clear_punctuation('Просто шикарный клуб! Ходили с другом на "Animal Джаz"! Остались очень довольны, атмосфера очень уютная, дружелюбная, есть второй этаж, бар')

Результат:

'Просто шикарный клуб Ходили с другом на Animal Джаz Остались очень довольны атмосфера очень уютная дружелюбная есть второй этаж бар'

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



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2020-01-14 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: