Практика EDA. Часть 3 | Анализ и обработка данных

Практика EDA. Часть 3

Все курсы > Анализ и обработка данных > Занятие 4 (часть 3)

В третьей части занятия рассмотрим построение графиков в Matplotlib.

Продолжим работать в том же ноутбуке

График в Matplotlib

Теперь более детально рассмотрим некоторые из составляющих графика в Matplotlib. В частности, приведем его «анатомию».

анатомия графика в библиотеке Matplotlib
Код для построения этого графика можно посмотреть здесь

И пройдемся по некоторым наиболее важным компонентам с помощью функции np.linspace().

Стиль графика

Цвет графика

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

цвет графика

В документации можно найти более полный перечень названий цветов⧉.

Тип линии графика

Посмотрим на различные типы линии.

тип линии графика

Строка форматирования

Цветом и типом линии можно также управлять с помощью строки форматирования (format string).

строка форматирования

Стиль точечной диаграммы

стиль точечной диаграммы

Стиль графика в целом

Помимо отдельных элементов графика мы можем управлять стилем графика в целом. Вначале посмотрим на доступные варианты.

Теперь используем стиль bmh.

стиль графика в целом

Акроним bmh расшифровывается как Bayesian Methods for Hackers или «Байесовские методы для хакеров». Так называется онлайн-книга по байесовской статистике⧉, в которой этот стиль используется для форматирования графиков.

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

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

базовый стиль Matplotlib

Пределы шкалы и деления осей графика

Пределы шкалы

Пределы шкалы по оси x и по оси y можно задавать двумя способами.

Способ 1. Использовать функции plt.xlim() и plt.ylim().

пределы шкалы: функции plt.xlim() и plt.ylim()

Способ 2. Кроме этого, мы можем воспользоваться функцией plt.axis().

пределы шкалы: функция plt.axis()

Деления

Иногда бывает необходимо принудительно изменить деления (tick) графика. Например, слишком большие числа могут не помещаться на шкале или для наглядности мы хотим изменить их формат. Сделать это можно с помощью функций plt.xticks() и plt.yticks().

деления графика

Подписи, легенда и размеры графика

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

подписи, легенда и размеры графика

В целом комментарии к коду, я думаю, понятны и дальнейших пояснений не требуют. Замечу лишь, что для выведения легенды важны как функция plt.legend(), так и параметр label внутри функции, строящей график (в данном случае plt.plot()). Без обоих этих элементов легенда не отобразится.

plt.figure() и plt.axes()

На прошлом занятии мы узнали, что Matplotlib поддерживает объектно-ориентированный подход к созданию графиков, и plt.figure() — это класс, который создает некий контейнер для хранения графиков, а plt.axes() строит графики внутри него. Рассмотрим простой пример создания объектов этих классов.

plt.figure() и plt.axes()

В данном случае объект fig мы не видим, изображение выше — объект ax (чтобы в этом убедиться, создайте объект класса plt.figure() без класса plt.axes()). Добавим к этому объекту кривую функции синуса.

функция синуса

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

  • plt.xlabel() $ \rightarrow $ ax.set_xlabel()
  • plt.ylabel() $ \rightarrow $ ax.set_ylabel()
  • plt.xlim() $ \rightarrow $ ax.set_xlim()
  • plt.ylim() $ \rightarrow $ ax.set_ylim()
  • plt.title() $ \rightarrow $ ax.set_title()

Продемонстрируем их применение.

методы класса plt.axes()

Кроме этого, можно применить общий метод .set(), в параметрах которого прописать необходимые настройки.

ax.set()

Построение подграфиков

Остается рассмотреть важный вопрос создания подграфиков (subplots), то есть нескольких объектов класса plt.axes() внутри plt.figure(). Сделать это можно несколькими способами.

Способ 1. Создание вручную

Вначале создадим два объекта plt.axes(), один стандартный, второй — по координатам и размерам окна по следующей схеме plt.axes([left, bottom, width, height]). Другими словами, мы передаем координату левого нижнего угла и размеры по ширине и высоте.

Например, создадим вложенный график, левый нижний угол которого будет находиться в центре основного графика [0.5, 0.5] и иметь размеры [0.3, 0.3] по шкале основного графика.

построение подграфиков вручную

Посмотрим, как расположить графики один над другим.

fig.add_axes()

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

Способ 2. Метод .add_subplot()

Еще один способ создания подграфиков — применять к объекту класса plt.figure() метод .add_subplot(). По большому счету .add_subplot() принимает три основных параметра: количество столбцов, количество строк и индекс подграфика. Например, если мы хотим создать сетку из двух подграфиков в один ряд, количество строк будет равно одному, столбцов — двум (т.е. 1 х 2).

Потребуется, соответственно, два раза использовать метод .add_subplot().

метод .add_subplot()

Создать подграфики можно и с помощью цикла for.

метод .add_subplot() + цикл for

Способ 3. Функция plt.subplots()

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

Функция plt.subplots() сразу создает фигуру и набор подграфиков. Приведем пример.

функция plt.subplots()

Функция plt.tight_layout() корректирует внешние отступы (padding) фигуры и отступы между графиками таким образом, чтобы подграфики не перекрывали друг друга.

Подграфики можно сразу передать в соответствующие переменные. Мы уже делали так выше, когда строили совмещенный график гистограммы и boxplot.

подграфики с соответствующими переменными

Еще один вариант использования функции plt.subplots(): «на ходу», т.е. в цикле for, заполнять объекты класса plt.axes() нужными графиками. Начнем с данных.

данные для построения графика

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

plt.subplots() + цикл for

Мы так делали опять же на занятии по компьютерному зрению или, например, обсуждая центральную предельную теорему на занятии по модулю random.

Обратите внимание, как используется объект ax с функциями библиотеки Seaborn.

Объект ax передается в одноименный параметр ax с указанием соответствующего индекса ax = ax[i, j].

Способ 4. Метод .plot() библиотеки Pandas

Метод .plot() библиотеки Pandas также позволяет строить подграфики. Причем в базовом варианте (без дополнительных настроек) мы можем обойтись относительно небольшим количеством кода.

подграфики: метод .plot() библиотеки Pandas

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

Здесь важно понимать, что метод .plot() также основан на библиотеке Matplotlib и также создает объекты класса plt.axes(). Для того чтобы ими воспользоваться, передадим результат метода .plot() в переменную ax и через индексы модифицируем каждый из подграфиков.

подграфики: метод .plot() библиотеки Pandas + подписи

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

Дополнительные возможности

Метод .twinx()

Если мы хотим построить две визуализации на одном графике с, например, разными шкалами по оси y, то мы можем воспользоваться методом .twinx(). По сути, этот метод накладывает один объект ax на другой.

Мы уже использовали этот прием, когда при изучении нормального распределения, рассматривали связь функции плотности (pdf) и функции распределения (cdf).

3D визуализации

Кроме этого, в следующем разделе мы будем использовать 3D визуализации при изучении оптимизации многомерной функции методом градиентного спуска.

Такой график можно построить с помощью метода .add_subplot() с параметром projection = ‘3d’.

Подведем итог

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

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

Вопросы для закрепления

Вопрос. Что такое stacked и grouped графики?

Ответ: проще всего еще раз привести графики из датасета «Титаник».

Посмотрим на grouped barplot выживших в разрезе класса пассажира (столбцы выживших и погибших расположены рядом друг с другом, сгруппированы).

Теперь посмотрим на относительное количество выживших и погибших в каждом классе каюты с помощью stacked barplot.

Stacked (т.е. «поставленный один на другой», «нагроможденный») график как раз удобно использовать, когда нужно увидеть доли, занимаемые той или иной категорией.

Вопрос. Чем barplot отличается от countplot?

Ответ: говоря упрощенно, barplot можно построить если уже посчитана некоторая метрика в каждой категории (объем продаж в каждой категории или в каждом году, количество пациентов принимавших каждое из лекарств и т.п.), countplot же самостоятельно считает количество наблюдений в каждой категории и выводит столбчатую диаграмму.

Вопрос. Что такое plt.figure() и plt.axes() в Matplotlib?

Ответ: класс plt.figure() создает объект (обычно помещается в переменную fig), который позволяет управлять общем «полотном», на котором может располагаться один или несколько объектов класса plt.axes() (обычно помещаются в переменную ax).

У каждого из этих объектов есть свои методы, которые позволяют управлять соответственно «полотном» и конкретным графиком или графиками.

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


Ответы на вопросы

Вопрос. Зачем использовать Питон, в котором нужно прописывать элементы графиков руками, когда можно использовать инструменты BI, например Tableau?

Ответ. В моем понимании у них разное назначение. Tableau — инструмент для создания интерактивных графиков, которые удобно показывать бизнес-пользователям. Графические инструменты Питона чаще используются внутри ноутбука, например, как часть пайплайна по созданию модели ML.


Вопрос. Что такое грамматика графики?

Ответ. Грамматика графики (the grammar of graphics) — подход к построению визуализаций, который разбивает график на части подобно тому как это делает обычная грамматика с естественным языком. По большому счету, это попытка систематизировать графический способ передачи информации и сделать его более осмысленным.

На практике этот подход наилучшим образом реализован в библиотеке ggplot (эта библиотека есть в R и Питоне). Более подробно можно почитать вот в этой статье⧉.


Вопрос. Как посмотреть, какая версия библиотеки используется в Google Colab?

Ответ. Версию библиотеки можно посмотреть с помощью атрибута __version__.

Более полную информацию о библиотеке можно посмотреть с помощью команды show.

О программе pip мы уже говорили на прошлом курсе. В Google Colab к ней можно получить доступ через !pip.

Кроме этого, мы можем совместить три команды, list (выводит список библиотек), | (pipe operator, оператор объединения команд) и grep <название библиотеки> (ищет совпадения с передаваемой строкой), для поиска упоминания конкретной библиотеки и ее версии в общем списке.