
- •Об авторе
- •О научном редакторе
- •От издательства
- •Введение
- •Использование Python для data science
- •Для кого эта книга?
- •О чем эта книга?
- •Глава 1. Базовые знания о данных
- •Категории данных
- •Неструктурированные данные
- •Структурированные данные
- •Слабоструктурированные данные
- •Данные временных рядов
- •Источники данных
- •Веб-страницы
- •Базы данных
- •Файлы
- •Получение
- •Очистка
- •Преобразование
- •Анализ
- •Хранение
- •Питонический стиль
- •Выводы
- •Глава 2. Структуры данных Python
- •Списки
- •Создание списка
- •Использование общих методов списков
- •Использование срезов
- •Использование списка в качестве очереди
- •Использование списка в качестве стека
- •Использование списков и стеков для обработки естественного языка
- •Расширение функциональности с помощью списковых включений
- •Кортежи
- •Список кортежей
- •Неизменяемость
- •Словари
- •Список словарей
- •Добавление элементов в словарь с помощью setdefault()
- •Преобразование JSON в словарь
- •Множества
- •Удаление дубликатов из последовательности
- •Общие операции с множеством
- •Упражнение № 1: продвинутый анализ тегов фотографий
- •Выводы
- •NumPy
- •Установка NumPy
- •Создание массива NumPy
- •Выполнение поэлементных операций
- •Использование статистических функций NumPy
- •Упражнение № 2: использование статистических функций numpy
- •pandas
- •Установка pandas
- •pandas Series
- •Упражнение № 3: объединение трех серий
- •pandas DataFrame
- •Упражнение № 4: использование разных типов join
- •scikit-learn
- •Установка scikit-learn
- •Получение набора образцов
- •Преобразование загруженного датасета в pandas DataFrame
- •Разделение набора данных на обучающий и тестовый
- •Преобразование текста в числовые векторы признаков
- •Обучение и оценка модели
- •Создание прогнозов на новых данных
- •Выводы
- •Глава 4. Доступ к данным из файлов и API
- •Импортирование данных с помощью функции open()
- •Текстовые файлы
- •Файлы с табличными данными
- •Упражнение № 5: открытие json-файлов
- •Двоичные файлы
- •Экспортирование данных в файл
- •Доступ к удаленным файлам и API
- •Как работают HTTP-запросы
- •Библиотека urllib3
- •Библиотека Requests
- •Упражнение № 6: доступ к api с помощью requests
- •Перемещение данных в DataFrame и из него
- •Импортирование вложенных структур JSON
- •Конвертирование DataFrame в JSON
- •Выводы
- •Глава 5. Работа с базами данных
- •Реляционные базы данных
- •Понимание инструкций SQL
- •Начало работы с MySQL
- •Определение структуры базы данных
- •Вставка данных в БД
- •Запрос к базе данных
- •Упражнение № 8: объединение «один-ко-многим»
- •Использование инструментов аналитики баз данных
- •Базы данных NoSQL
- •Документоориентированные базы данных
- •Упражнение № 9: вставка и запрос нескольких документов
- •Выводы
- •Глава 6. Агрегирование данных
- •Данные для агрегирования
- •Объединение датафреймов
- •Группировка и агрегирование данных
- •Просмотр конкретных агрегированных показателей по MultiIndex
- •Срез диапазона агрегированных значений
- •Срезы на разных уровнях агрегирования
- •Добавление общего итога
- •Добавление промежуточных итогов
- •Выбор всех строк в группе
- •Выводы
- •Глава 7. Объединение датасетов
- •Объединение встроенных структур данных
- •Объединение списков и кортежей с помощью оператора +
- •Объединение словарей с помощью оператора **
- •Объединение строк из двух структур
- •Реализация join-объединений списков
- •Конкатенация массивов NumPy
- •Объединение структур данных pandas
- •Конкатенация датафреймов
- •Удаление столбцов/строк из датафрейма
- •Join-объединение двух датафреймов
- •Выводы
- •Глава 8. Визуализация
- •Распространенные способы визуализации
- •Линейные диаграммы
- •Столбчатые диаграммы
- •Круговые диаграммы
- •Гистограммы
- •Построение графиков с помощью Matplotlib
- •Установка Matplotlib
- •Использование matplotlib.pyplot
- •Работа с объектами Figure и Axes
- •Создание гистограммы с помощью subplots()
- •Совместимость Matplotlib с другими библиотеками
- •Построение графиков для данных pandas
- •Отображение данных геолокации с помощью Cartopy
- •Выводы
- •Глава 9. Анализ данных о местоположении
- •Получение данных о местоположении
- •Преобразование стандартного вида адреса в геокоординаты
- •Получение геокоординат движущегося объекта
- •Анализ пространственных данных с помощью geopy и Shapely
- •Поиск ближайшего объекта
- •Поиск объектов в определенной области
- •Объединение двух подходов
- •Упражнение № 15: совершенствование алгоритма подбора машины
- •Получение непространственных характеристик
- •Объединение датасетов с пространственными и непространственными данными
- •Выводы
- •Глава 10. Анализ данных временных рядов
- •Регулярные и нерегулярные временные ряды
- •Общие методы анализа временных рядов
- •Вычисление процентных изменений
- •Вычисление скользящего окна
- •Вычисление процентного изменения скользящего среднего
- •Многомерные временные ряды
- •Обработка многомерных временных рядов
- •Анализ зависимости между переменными
- •Выводы
- •Глава 11. Получение инсайтов из данных
- •Ассоциативные правила
- •Поддержка
- •Доверие
- •Лифт
- •Алгоритм Apriori
- •Создание датасета с транзакциями
- •Определение часто встречающихся наборов
- •Генерирование ассоциативных правил
- •Визуализация ассоциативных правил
- •Получение полезных инсайтов из ассоциативных правил
- •Генерирование рекомендаций
- •Планирование скидок на основе ассоциативных правил
- •Выводы
- •Глава 12. Машинное обучение для анализа данных
- •Почему машинное обучение?
- •Типы машинного обучения
- •Обучение с учителем
- •Обучение без учителя
- •Как работает машинное обучение
- •Данные для обучения
- •Статистическая модель
- •Неизвестные данные
- •Пример анализа тональности: классификация отзывов о товарах
- •Получение отзывов о товарах
- •Очистка данных
- •Разделение и преобразование данных
- •Обучение модели
- •Оценка модели
- •Упражнение № 19: расширение набора примеров
- •Прогнозирование тенденций фондового рынка
- •Получение данных
- •Извлечение признаков из непрерывных данных
- •Генерирование выходной переменной
- •Обучение и оценка модели
- •Выводы

228 Глава 11. Получение инсайтов из данных
Как и поддержка, доверие находится в диапазоне от 0 до 1, но, в отличие от поддержки, оно не симметрично. Это означает, что метрика доверия для правила творог -> сметанаможет отличаться от доверия для правила сметана -> творог:
доверие(сметана -> творог) = (творог & сметана) / сметана = 20 / 30 = 0.66
В данном сценарии значение доверия будет меньше, если антецедент и консеквент ассоциативного правила поменяются местами. Это говорит о том, что вероятность того, что человек, покупающий сметану, купит и творог, меньше, чем вероятность того, что человек, покупающий творог, купит и сметану.
Лифт
Лифт (lift) оценивает значимость ассоциативного правила для случая, когда элементы правила оказываются в одной транзакции случайно. Лифт ассоциативного правила творог -> сметана — это отношение наблюдаемой поддержки для творог -> сметанак ожидаемой, если бы покупка творога и покупка сметаны были независимы друг от друга. Рассчитать лифт можно следующим образом:
лифт(сметана -> творог) = поддержка(творог & сметана) / (поддержка (творог) *
поддержка(сметана)) = 0.2 / (0.25 * 0.3) = 2.66
Метрика лифта симметрична — если поменять местами антецедент и консеквент, значение метрики не изменится. Коэффициент лифта варьируется от 0 до бесконечности, и чем больше этот коэффициент, тем сильнее связь. В частности, коэффициент лифта, больший 1, указывает на то, что связь между антецедентом и консеквентом сильнее, чем можно было бы ожидать, если бы они были независимыми, то есть эти два товара часто покупают вместе. Коэффициент лифта, равный 1, указывает на отсутствие корреляции между антецедентом и консеквентом. Коэффициент лифта, меньший 1, говорит о наличии отрицательной корреляции между антецедентом и консеквентом. Это означает, что их вряд ли купят вместе. В данном случае коэффициент лифта 2.66 можно интерпретировать так: когда клиент покупает творог, ожидаемая вероятность того, что он также купит сметану, увеличивается на 166%.
Алгоритм Apriori
Теперь вы знаете, что собой представляют ассоциативные правила и некоторые метрики оценки их значимости, но как создавать ассоциативные правила для

Алгоритм Apriori 229
анализа потребительской корзины? Один из способов — использовать алгоритм Apriori (Apriori algorithm), автоматизированный процесс анализа данных о транз акциях. В общих чертах этот алгоритм состоит из двух шагов:
1.Определение всех часто встречающихся наборов или группы из одного либо нескольких товаров, которые в рамках датасета присутствуют сразу во многих транзакциях. Алгоритм находит все товары или группы товаров, значение поддержки которых превышает определенный порог.
2.Генерирование ассоциативных правил для часто встречающихся наборов товаров путем рассмотрения всех возможных бинарных разбиений каждого набора товаров (то есть всех разбиений набора на группу антецедентов и группу консеквентов) и вычисления метрик ассоциативных правил для каждого разбиения.
После создания ассоциативных правил их значимость можно оценить с помощью метрик из предыдущего раздела.
Несколько сторонних библиотек Python поставляются с реализацией алгоритма Apriori. Одна из них — библиотека mlxtend (сокращение от machine learning extensions). Библиотека mlxtend включает инструменты для решения ряда общих задач в области data science. В этом разделе мы рассмотрим пример анализа потребительской корзины с помощью реализации алгоритма Apriori. Но сначала установим mlxtend с помощью pip:
$ pip install mlxtend
ПРИМЕЧАНИЕ
Чтобы узнать больше о mlxtend, обратитесь к документации библиотеки1.
Создание датасета с транзакциями
Для проведения анализа потребительской корзины понадобятся данные о нескольких транзакциях. Для простоты можно использовать всего несколько транзакций, реализованных в виде списка списков, как показано ниже:
transactions = [
['curd', 'sour cream'], ['curd', 'orange', 'sour cream'],
['bread', 'cheese', 'butter'], ['bread', 'butter'], ['bread', 'milk'], ['apple', 'orange', 'pear'], ['bread', 'milk', 'eggs'], ['tea', 'lemon'],
1 http://rasbt.github.io/mlxtend

230 Глава 11. Получение инсайтов из данных
['curd', 'sour cream', 'apple'], ['eggs', 'wheat flour', 'milk'], ['pasta', 'cheese'], ['bread', 'cheese'], ['pasta', 'olive oil', 'cheese'], ['curd', 'jam'], ['bread', 'cheese', 'butter'],
['bread', 'sour cream', 'butter'], ['strawberry', 'sour cream'], ['curd', 'sour cream'], ['bread', 'coffee'], ['onion', 'garlic']
] 1
Каждый внутренний список содержит набор товаров одной транзакции. Внешний список transactions содержит в общей сложности 20 транзакций. Для сохранения количественных пропорций, определенных в исходном примере творог/ сметана, датасет содержит пять операций с творогом (curd), шесть операций со сметаной (sour cream) и четыре операции, содержащие и творог, и сметану.
Чтобы пропустить данные транзакций через алгоритм Apriori библиотеки mlxtend, необходимо преобразовать их в булев массив, созданный с помощью быстрого кодирования (OHE, one-hot encoding), то есть структуру, где каждый столбец представляет доступный товар, а строка — транзакцию. Значения массива могут быть равны либо True, либо False (True, если транзакция включала данный конкретный товар, и False — если нет). Во фрагменте кода ниже мы выполняем необходимое преобразование, используя объект mlxtend TransactionEncoder:
import pandas as pd
from mlxtend.preprocessing import TransactionEncoder
encoder = TransactionEncoder()
encoded_array = encoder.fit(transactions).transform(transactions)df_itemsets = pd.DataFrame(encoded_array, columns=encoder.columns_)
Мы создаем объект TransactionEncoder и используем его для преобразования списка списков transactions в булев OHE-массив с названием encoded_array . Затем преобразуем массив в pandas DataFrame df_itemsets , фрагмент которого приведен ниже:
|
apple |
bread |
butter |
cheese |
coffee |
curd |
eggs |
... |
0 |
False |
False |
False |
False |
False |
True |
False |
... |
1 |
False |
False |
False |
False |
False |
True |
False |
... |
2 |
False |
True |
True |
True |
False |
False |
False |
... |
3 |
False |
True |
True |
False |
False |
False |
False |
... |
4 |
False |
True |
False |
False |
False |
False |
False |
... |
1curd — творог, sour cream — сметана, orange — апельсин, bread — хлеб, cheese — сыр, butter — масло, milk — молоко, apple — яблоко, pear — груша, eggs — яйца, tea — чай, lemon — лимон, wheat flour — пшеничная мука, pasta — макароны, olive oil — оливковое масло, jam — джем, strawberry — клубника, coffee — кофе, onion — лук, garlic — чеснок. — Примеч. пер.

Алгоритм Apriori 231
5 |
True |
False |
False |
False |
False |
False |
False |
... |
6 |
False |
True |
False |
False |
False |
False |
True |
... |
--фрагмент— |
|
|
|
|
|
|
|
|
[20 |
rows x 20 columns] |
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
Датафрейм состоит из 20 строк и 20 столбцов. Строки представляют собой транзакции, а столбцы — товары. Чтобы проверить, что в исходном списке списков действительно было 20 транзакций, основанных на 20 доступных товарах, используйте следующий код:
print('Number of transactions: ', len(transactions)) print('Number of unique items: ', len(set(sum(transactions, []))))
В обоих случаях должно получиться 20.
Определение часто встречающихся наборов
Теперь, когда данные транзакции представлены в удобном формате, можно использовать функцию mlxtend apriori() для определения всех часто встречающихся наборов товаров в данных о транзакциях, то есть всех товаров или групп товаров с достаточно высокой метрикой поддержки. Вот как это реализовать:
from mlxtend.frequent_patterns import apriori
frequent_itemsets = apriori(df_itemsets, min_support=0.1, use_colnames=True)
Из модуля mlxtend.frequent_patternsимпортируем функцию apriori(). Затем вызываем ее, передавая датафрейм с данными о транзакциях в качестве первого параметра. Также устанавливаем для параметра min_support значение 0.1, чтобы возвращать наборы с поддержкой не менее 10% (помните, что метрика поддержки показывает, в каком проценте транзакций встречается товар или группа товаров). Для use_colnames мы устанавливаем значение True, чтобы определить столбцы, включаемые в каждый набор товаров, по их названию (например, curd или sour cream), а не по индексу. В результате apriori() возвращает следующий датафрейм:
|
support |
itemsets |
0 |
0.10 |
(apple) |
1 |
0.40 |
(bread) |
2 |
0.20 |
(butter) |
3 |
0.25 |
(cheese) |
4 |
0.25 |
(curd) |
5 |
0.10 |
(eggs) |

232 |
|
Глава 11. Получение инсайтов из данных |
6 |
0.15 |
(milk) |
7 |
0.10 |
(orange) |
8 |
0.10 |
(pasta) |
9 |
0.30 |
(sour cream) |
10 |
0.20 |
(bread, butter) |
11 |
0.15 |
(bread, cheese) |
12 |
0.10 |
(bread, milk) |
13 |
0.10 |
(cheese, butter) |
14 |
0.10 |
(pasta, cheese) |
15 |
0.20 |
(sour cream, curd) |
16 |
0.10 |
(milk, eggs) |
17 |
0.10 |
(bread, cheese, butter) |
|
|
|
Как уже отмечалось, набор товаров может состоять из одного или нескольких позиций, и действительно, apriori()вернул несколько наборов с одним товаром. В конечном итоге mlxtend не будет учитывать наборы с одним товаром при составлении ассоциативных правил; тем не менее ему понадобятся данные обо всех часто встречающихся наборах (включая те, которые содержат один товар). Ради интереса можете выбрать только те наборы товаров, которые содержат несколько позиций. Для этого добавьте колонку length к датафрейму frequent_itemsets:
frequent_itemsets['length'] = frequent_itemsets['itemsets'].apply(lambda itemset: len(itemset))
Затем, используя синтаксис pandas, отфильтруйте датафрейм так, чтобы остались только те строки, значение поля length которых равно или больше 2:
print(frequent_itemsets[frequent_itemsets['length'] >= 2])
Вы получите датафрейм, который не содержит наборов с одним товаром:
10 |
0.20 |
(bread, |
butter) |
2 |
11 |
0.15 |
(bread, |
cheese) |
2 |
12 |
0.10 |
(bread, milk) |
2 |
|
13 |
0.10 |
(cheese, butter) |
2 |
|
14 |
0.10 |
(pasta, cheese) |
2 |
|
15 |
0.20 |
(sour cream, curd) |
2 |
|
16 |
0.10 |
(milk, eggs) |
2 |
|
17 |
0.10 |
(bread, cheese, butter) |
3 |
|
|
|
|
|
|
Повторимся, однако, что для генерации ассоциативных правил mlxtend требует информацию обо всех часто встречающихся наборах товаров. Поэтому убедитесь, что вы не удаляете ни одной строки из исходного датафрейма frequent_itemsets.