Seaborn — библиотека для создания статистических графиков на Python. Она построена на основе matplotlib и тесно интегрируется со структурами данных pandas. Seaborn помогает вам изучить и понять данные. Его функции построения графиков работают с датасетами и выполняют все необходимы преобразования для создания информативных графиков.
Синтаксис, ориентированный на набор данных, позволяет сосредоточиться на графиках, а не деталях их построения.
Давайте более детально рассмотрим построение популярных типов графиков.
Весь дальнейший код будет выполняться в Jupyter Notebook
Построение Bar Plot в Seaborn
Гистограммы отображают числовые величины на одной оси и переменные категории на другой. Они позволяют вам увидеть, значения параметров для каждой категории.
Гистограммы можно использовать для визуализации временных рядов, а также только категориальных данных.
Построение гистограммы
Чтобы нарисовать гистограмму в Seaborn нужно вызвать функцию barplot(), и передать ей категориальные и числовые переменные, которые нужно визуализировать, как это сделано в примере:
import matplotlib.pyplot as plt
import seaborn as sns
x = ['А', 'Б', 'В']
y = [10, 50, 30]
sns.barplot(x=x, y=y);
В данном случае, у нас есть несколько категориальных переменных в списке — А, Б и В. А также непрерывные переменные (числа) в другом списке — 10, 50 и 30. Зависимость между этими двумя элементами визуализируется на гистограмме, для чего эти два списка передаются в функцию sns.barplot().
В результате получается четкая и простая гистограмма:
Чаще всего вы будете работать с датасетами, которые содержат гораздо больше данных, чем тот что приведен в примере. Иногда к этим наборам данным требуется сортировка, или подсчитать, сколько раз повторяются то или другое значение.
Когда вы работаете с данными можете столкнуться с ошибками и пропусками, которые в них имеются. К счастью, Seaborn защищает нас и автоматически применяет фильтр, который основан на вычислении среднего значения предоставленных данных.
Давайте импортируем классический датасет Titanic и визуализируем Bar Plot с этими данными:
x = ['А', 'Б', 'В']
y = [10, 50, 30]
sns.barplot(x=x, y=y, color='blue');
Тогда график будет выглядеть так:
Или, что еще лучше, установить аргумент pallete, который может принимать большое количество цветов. Довольно распространенное значение этого параметра hls:
Часто требуется сгруппировать столбцы на графиках по одному признаку. Допустим, вы хотите сравнить некоторые общие данные, выживаемость пассажиров, и сгруппировать их по заданным критериям.
Нам может потребоваться визуализировать количество выживших пассажиров, в зависимости от класса (первый, второй и третий), но также учесть, города из которого они прибыли.
Всю эту информацию можно легко отобразить на гистограмме.
Чтобы сгруппировать столбцы вместе, мы используем аргумент hue. Этот аргумент группирует соответствующие данные и сообщает библиотеке Seaborn, как раскрашивать столбцы.
Давайте посмотрим на только что обсужденный пример:
Настройка порядка отображения групп столбцов на гистограмме
Вы можете изменить порядок следования столбцов по умолчанию. Это делается с помощью аргумента order, который принимает список значений и порядок их размещения.
Например, до сих пор он упорядочивал классы с первого по третий. Что, если мы захотим сделать наоборот?
Вы также можете поэкспериментировать с доверительным интервалом, задав аргумент ci.
Например, вы можете отключить его, установив для него значение None, или использовать стандартное отклонение вместо среднего, установив sd, или даже установить верхний предел на шкале ошибок, установив capsize.
Давайте немного поэкспериментируем с атрибутом доверительного интервала:
Мы рассмотрели несколько способов построения гистограммы в Seaborn на примерах. Теперь перейдем к тепловым картам.
Построение Heatmap в Seaborn
Давайте посмотрим, как мы можем работать с библиотекой Seaborn на Python, чтобы создать базовую тепловую карту корреляции. Для наших целей мы будем использовать набор данных о жилье Ames, доступный на Kaggle.com. Он содержит более 30 показателей, которые потенциально могут повлиять на стоимость недвижимости.
Поскольку Seaborn была написана на основе библиотеки визуализации данных Matplotlib, их довольно просто использовать вместе. Поэтому помимо стандартных модулей мы также собираемся импортировать Matplotlib.pyplot.
Seaborn прост в использовании, но в нем довольно сложно ориентироваться. Библиотека поставляется с множеством встроенных функций и обширной документацией. Может быть трудно понять, какие именно аргументы использовать, если вам не нужны все возможные навороты.
Давайте сделаем базовую тепловую карту более полезной с минимальными усилиями.
vmin, vmax — устанавливают диапазон значений, которые служат основой для цветовой карты (colormap).
cmap — определяет конкретную colormap, которую мы хотим использовать (ознакомьтесь с полным диапазоном цветовых палитр здесь).
center — принимает вещественное число для центрирования цветовой карты; если cmap не указан, используется colormap по умолчанию; если установлено значение True — все цвета заменяются на синий.
annot — при значении True числовые значения корреляции отображаются внутри ячеек.
cbar — если установлено значение False, цветовая шкала (служит легендой) исчезает.
# Увеличьте размер
heatmap plt.figure(figsize=(16, 6))
# Сохраните объект тепловой карты в переменной, чтобы легко получить к нему доступ,
# когда вы захотите включить дополнительные функции (например, отображение заголовка).
# Задайте диапазон значений для отображения на цветовой карте от -1 до 1 и установите для аннотации (annot) значение True,
# чтобы отобразить числовые значения корреляции на тепловой карте.
heatmap = sns.heatmap(dataframe.corr(), vmin=-1, vmax=1, annot=True)
# Дайте тепловой карте название. Параметр pad (padding) определяет расстояние заголовка от верхней части тепловой карты.
heatmap.set_title('Correlation Heatmap', fontdict={'fontsize':12}, pad=12);
Для работы с heatmap лучше всего подходит расходящаяся цветовая палитра. Она имеет два очень разных темных (насыщенных) цвета на соответствующих концах диапазона интерполированных значений с бледной, почти бесцветной средней точкой. Проиллюстрируем это утверждение и разберемся с еще одной небольшой деталью: как сохранить созданную тепловую карту в файл png со всеми необходимыми x и y метками (xticklabels и yticklabels).
plt.figure(figsize=(16, 6))
heatmap = sns.heatmap(dataframe.corr(), vmin=-1, vmax=1, annot=True, cmap='BrBG')
heatmap.set_title('Correlation Heatmap', fontdict={'fontsize':18}, pad=12);
# Сохраните карту как png файл
# Параметр dpi устанавливает разрешение сохраняемого изображения в точках на дюйм
# bbox_inches, когда установлен в значение 'tight', не позволяет обрезать лейблы
plt.savefig('heatmap.png', dpi=300, bbox_inches='tight')
Треугольная тепловая карта корреляции
Взгляните на любую из приведенных выше тепловых карт. Если вы отбросите одну из ее половин по диагонали, обозначенной единицами, вы не потеряете никакой информации. Итак, давайте сократим тепловую карту, оставив только нижний треугольник.
Аргумент mask (маска) heatmap пригодится, чтобы скрыть часть тепловой карты. Маска — принимает в качестве аргумента массив логических значений или структуру табличных данных (dataframe). Если она предоставлена, ячейки тепловой карты, для которых значения маски является True, не отображаются.
Давайте воспользуемся функцией np.triu() библиотеки numpy, чтобы изолировать верхний треугольник матрицы, превращая все значения в нижнем треугольнике в 0. np.tril() будет делать то же самое, только для нижнего треугольника. В свою очередь функция np.ones_like() изменит все изолированные значения на 1.
plt.figure(figsize=(16, 6))
# Определите маску, чтобы установить значения в верхнем треугольнике на True
mask = np.triu(np.ones_like(dataframe.corr(), dtype=np.bool))
heatmap = sns.heatmap(dataframe.corr(), mask=mask, vmin=-1, vmax=1, annot=True, cmap='BrBG')
heatmap.set_title('Triangle Correlation Heatmap', fontdict={'fontsize':18}, pad=16);
Корреляция независимых переменных с зависимой
Довольно часто мы хотим создать цветную карту, которая показывает выраженность связи между каждой независимой переменной, включенной в нашу модель, и зависимой переменной.
Следующий код возвращает корреляцию каждого параметра с «ценой продажи», единственной зависимой переменной в порядке убывания.
Эти примеры демонстрируют основную функциональность heatmap в Seaborn. Теперь перейдем к точечным диаграммам.
Построение Scatter Plot в Seaborn
Давайте рассмотрим процесс создания точечной диаграммы в Seaborn. Построим простые и трехмерные диаграммы рассеивания, а также групповые графики на базе FacetGrid.
Импорт данных
Мы будем использовать набор данных, основанный на мировом счастье. Сравнение его индекса с другими показателям отразит факторы, влияющие на уровень счастья в мире.
Построение точечной диаграммы
На графике отразим соотношение индекса счастья к экономике страны (ВВП на душу населения):
dataframe = pd.read_csv('2016.csv')
sns.scatterplot(data=dataframe, x="Economy (GDP per Capita)", y="Happiness Score");
При помощи Seaborn очень легко составлять простые графики наподобие диаграмм рассеивания. Нам не обязательно использовать объект Figure и экземпляры Axes или что-нибудь настраивать. Здесь мы передали dataframe в качестве аргумента с данными, а признаки с информацией, которую нужно визуализировать, в x и y.
Оси диаграммы по умолчанию подписываются именами столбцов, которые соответствуют заголовкам из загружаемого файла. Ниже мы рассмотрим, как это изменить.
После выполнения кода мы получим следующее:
Результат показал прямую зависимость между ВВП на душу населения и предполагаемого уровня счастья жителей конкретной страны или региона.
Построение группы графиков scatterplot при помощи FacetGrid
Если требуется сравнить много переменных друг с другом, например, среднюю продолжительность жизни наряду с оценкой счастья и уровнем экономики, нет необходимости строить 3D-график.
Несмотря на существование двумерных диаграмм, позволяющих визуализировать соотношение между множествами переменных, не все из них просты в применении.
При помощи объекта FacetGrid, библиотека Seaborn позволяет обрабатывать данные и строить на их основе групповые взаимосвязанные графики.
В этом примере мы создали экземпляр объекта FacetGrid с параметром dataframe в качестве данных. При передаче значения "Region" аргументу col библиотека сгруппирует датасет по регионам и построит диаграмму рассеивания для каждого из них.
Параметр hue задает каждому региону собственный оттенок. Наконец, при помощи аргумента col_wrap ширина области Figure ограничивается до 5-ти диаграмм. По достижении этого предела следующие графики будут построены на новой строке.
Для подготовки сетки перед выводом на экран мы используем метод map(). Тип диаграммы передается в первом аргументе со значением sns.scatterplot, а в качестве осей служат переменные x и y.
В результате будет сформировано 10 графиков по каждому региону с соответствующими им осями. Непосредственно перед печатью мы вызываем метод, добавляющий легенду с обозначением цветовой маркировки.
Построение 3D-диаграммы рассеивания
К сожалению, в Seaborn отсутствует собственный 3D-движок. Являясь лишь дополнением к Matplotlib, он опирается на графические возможности основной библиотеки. Тем не менее, мы все еще можем применить стиль Seaborn к трехмерной диаграмме.
Посмотрим, как она будет выглядеть с выборкой по уровням счастья, экономики и здоровья:
%matplotlib notebook
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns
from mpl_toolkits.mplot3d import Axes3D
df = pd.read_csv('Downloads/2016.csv')
fig = plt.figure()
ax = fig.add_subplot(111, projection = '3d')
x = df['Happiness Score']
y = df['Economy (GDP per Capita)']
z = df['Health (Life Expectancy)']
ax.set_xlabel("Счастье")
ax.set_ylabel("Экономика")
ax.set_zlabel("Здоровье")
ax.scatter(x, y, z)
plt.show()
В результате выполнения кода появится интерактивная 3D-визуализация, которую можно вращать и масштабировать в трехмерном пространстве:
Настройка Scatter Plot
При помощи Seaborn можно легко настраивать различные элементы создаваемых диаграмм. Например, присутствует возможность изменения цвета и размера каждой точки на графике.
Попробуем задать некоторые параметры и посмотреть, как изменится его внешний вид:
Здесь мы применили оттенок к регионам — это означает, что данные по каждому из них будут раскрашены по-разному. Кроме того, при помощи аргумента size были заданы пропорции точек в зависимости от уровня свободы. Чем больше его значение, тем крупнее точка на диаграмме:
Или можно просто задать одинаковый цвет и размер для всех точек:
Отлично, вы узнали несколько способов построения scatter plot в Seaborn. Перейдем к еще одному популярному графику.
Построение Box Plot в Seaborn
Box Plot, называемые также:
графиками прямоугольников,
коробчатыми графиками,
графиками размаха
или ящиками с усами за свой вид.
Они используются для визуализации сводной статистики датасета. Box Plot отображают атрибуты распределения, такие как диапазон и распределение данных в диапазоне (прямоугольника, «усы», медиана).
Импорт данных
Для создания box plot нужны непрерывные числовые данные, поскольку такая диаграмма отображает сводную статистику — медиану, диапазон и выбросы. Для примера воспользуемся набором данных forestfires.csv (сведения об индексе влажности лесной подстилки, осадках, температуре, ветре и т.д.).
Импортируем pandas для загрузки и анализа датасета, seaborn и модуль pyplot из matplotlib для визуализации:
import pandas as pd
from matplotlib import pyplot as plt
import seaborn as sns
Воспользуемся pandas для чтения CSV-файла в dataframe и выведем первые 5 строк. Кроме того, проверим, содержит ли набор данных пропущенные значения (Null, NaN):
Для визуализации распределения только одного признака мы передаем его в переменную x. В этом случае, Seaborn автоматически вычислит значения по оси y, что видно на следующем изображении.
Если требуется определенное распределение, сегментированное по типу, то можно для функции boxplot в качестве аргументов передать категориальную переменную в x и непрерывную переменную в y.
Теперь получилась блочная диаграмма, созданная для каждого дня недели.
Если требуется визуализировать несколько столбцов одновременно, то аргументов x и y будет недостаточно. Для этих целей используется аргумент data, которому передается набор данных, содержащий требуемые переменные и их значения.
Создадим новый датасет, содержащий только те данные, которые мы хотим визуализировать. Затем к нему применим функцию melt(). Полученный в результате набор данных передается аргументу data. В аргументы x и y в этом случае передаются значения по умолчанию из melt (value и variable):
Seaborn автоматически назначает различные цвета различным переменным, чтобы можно было их легко визуально различить. Цвет диаграмм можно изменить, предоставив свой список цветов.
После определения списка цветов в виде HEX-значений или названий доcтупного цвета Matplotlib, можно передать их функции boxplot() в качестве аргумента palette:
С помощью Seaborn можно легко настроить подписи по осям X и Y. Например, изменить размер шрифта, подписи или повернуть их, чтобы сделать более удобными для чтения.
Для отображения блочных диаграмм в определенном порядке используется аргумент order, которому передается список имен столбцов в том порядке, в котором их нужно расположить:
Если необходимо разделить общий box plot на несколько для отдельных признаков, то это можно сделать. Определите область отрисовки (fig) и нужное количество координатных осей (axes) с помощью функции subplots из Matplotlib. Доступ к нужной области объекта axes можно получить через его индекс. Функция boxplot() принимает ax аргумент, который по индексу объекта axes получает область для построения диаграммы:
Для более наглядного восприятия распределения можно наложить точечную диаграмму рассеивания на блочную.
С этой целью последовательно создаем две диаграммы. Диаграмма, созданная функцией stripplot(), будет наложена поверх box plot, так как они выводятся в одной и той же области:
Мы рассмотрели несколько способов построения Box Plot с помощью Seaborn и Python. Также узнали, как настроить цвета, подписи осей, порядок следования диаграмм, наложение точечных диаграмм и разделение диаграмм для отдельных величин.
Последний тип графика, о котором стоит упомянуть — Violin Plot.
Построение Violin Plot в Seaborn
Violin Plot или скрипичные диаграммы используются для визуализации распределения данных, отображая диапазон данных, медиану и область распределения данных.
Такие диаграммы, как и ящики с усами, показывают сводную статистику. Дополнительно они включают в себя графики плотности распределения, которые и определяют форму/распределение данных при визуализации.
Импорт данных
Для примера воспользуемся набором данных Gapminder, содержащем информацию о численности населения, продолжительности жизни и другие данные по странам и годам, начиная с 1952 года.
Импортируем pandas, seaborn и модуль pyplot из matplotlib:
country = dataframe.country
continent = dataframe.continent
population = dataframe.population
life_exp = dataframe.life_exp
gdp_cap = dataframe.gdp_cap
Построение простой скрипичной диаграммы
Теперь, после того как мы загрузили данные и выбрали величины, которые хотим визуализировать, можно создать скрипичную диаграмму. Используем функцию violinplot(), которой в качестве аргумента x передадим переменную для визуализации.
Отмечу, что можно было не выбирать предварительно данные по имени столбца и не сохранять в переменной life_exp. Используя аргумент data, которому передан наш набор данных, и аргумент x, которому присвоено имя переменной «life_exp», получим точно такой же результат.
Обратите внимание на то, что на этом изображении Seaborn строит график распределения ожидаемой продолжительности жизни сразу по всем странам, так как использовалась только одна переменная life_exp. В большинстве случаев такого типа переменная рассматривается на основе других переменных, таких как country или continent в нашем случае.
Построение Violin Plot с осями X и Y
Для того чтобы получить визуализацию распределения данных, сегментированное по типу, необходимо в качестве аргументов функции использовать категориальную переменную для x и непрерывную для y.
В этом наборе данных много стран. Если построить диаграммы для всех стран, то их будет слишком много, чтобы их можно было рассмотреть. Можно, конечно, выделить подмножество из набора данных и просто построить диаграммы, скажем, для 10 стран.
Вместо этого, построим violinplot для континентов.
Предположим, что необходимо изменить некоторые заголовки и подписи нашего графика, чтобы было проще его анализировать.
Несмотря на то, что Seaborn автоматически подписывает оси X и Y, можно изменить подписи с помощью функций set_title() и set_label() после создания объекта axes. Надо просто передать название, которое хотим дать нашему графику, функции set_title().
Для того чтобы подписать оси, используется функция set() с аргументами xlabel и ylabel или функции-обертки set_xlabel()/set_ylabel():
Точечную диаграмму распределения можно наложить на скрипичную диаграмму, чтобы увидеть размещение точек, составляющих это распределение. Для этого просто создается одна область рисования, а затем последовательно в ней создаются две диаграммы.
plt.figure(figsize=(16,8))
sns.set_palette("RdBu")
sns.set_style("darkgrid")
sns.violinplot(x=continent, y=life_exp)
sns.swarmplot(x=continent, y=life_exp, color="k", alpha=0.8)
plt.title("Ожидаемая продолжительность жизни по континентам")
plt.ylabel("Ожидаемая продолжительность жизни")
plt.xlabel("Континент");
Построение Violin Plot для разных признаков
Если нужно разделить визуализацию столбцов из набора данных на их собственные диаграммы, то это можно сделать. Создайте область рисования и сетку, в ячейках которой будут графики.
Для отображения диаграммы в соответствующей ячейке применяется функция add_subplot(), которой передается адрес этой ячейки. Создание диаграммы делаем, как обычно, используя объект axes.
Можно использовать y=variable, либо data=variable.
Группировка скрипичных диаграмм по категориальному признаку
По настоящему полезная вещь для violinplot — это группировка по значениям категориальной переменной. Например, если есть категориальная величина, имеющая два значения (обычно, True/False), то в этом случае можно группировать графики по этим значениям.
Допустим, есть набор данных по трудоустройству населения со столбцом employment и его значениями employed и unemployed. Тогда можно сгруппировать диаграммы по видам занятости.
Поскольку в наборе данных Gapminder нет столбца, подходящего для такой группировки, его можно сделать, рассчитав среднюю продолжительность жизни для определенного подмножества стран, например, европейских стран.
Назначим Yes/No значение новому столбцу above_average_life_exp для каждой страны. Если средняя продолжительность жизни выше, чем в среднем по датасету, то это значение равно Yes, и наоборот:
# Отделяем европейские страны от исходного датасет
europe = dataframe.loc[dataframe["continent"] == "Europe"]
# Вычисляем среднее значение переменной "life_exp"
avg_life_exp = dataframe["life_exp"].mean()
# Добавим новую колонку
europe.loc[:, "above_average_life_exp"] = europe["life_exp"] > avg_life_exp
europe["above_average_life_exp"].replace(
{True: "Yes", False: "No"},
inplace=True
)
Теперь, если вывести наш набор данных, то получим следующее:
country
year
population
continent
life_exp
gdp_cap
above_average_life_exp
12
Albania
1952
1282697
Europe
55.23
1601.056136
No
13
Albania
1957
1476505
Europe
59.28
1942.284244
No
14
Albania
1962
1728137
Europe
64.82
2312.888958
Yes
15
Albania
1967
1984060
Europe
66.22
2760.196931
Yes
16
Albania
1972
2263554
Europe
67.69
3313.422188
Yes
Теперь можно построить скрипичные диаграммы, сгруппированные по новому столбцу, который мы вставили. Учитывая, что европейских стран много, для удобства визуализации выберем последние 50 строк, используя europe.tail():
europe = europe.tail(50)
ax = sns.violinplot(x=europe.country, y=europe.life_exp, hue=europe.above_average_life_exp)
ax.set_title("Ожидаемая продолжительность жизни по странам")
ax.set_ylabel("Ожидаемая продолжительность жизни")
ax.set_xlabel("Страны");
В результате получим:
Теперь страны с продолжительностью жизни меньше средней, ожидаемой отличаются по цвету.
Разделение скрипичных диаграмм по категориальному признаку
Если используется аргумент hue для категориальной переменной, имеющей два значения, то применив в функции violinplot() аргумент split и установив его в True, можно разделить скрипичные диаграммы пополам с учетом значения hue.
В нашем случае одна сторона скрипки (левая) будет представлять записи с ожидаемой продолжительностью жизни выше среднего, в то время как правая сторона будет использоваться для построения ожидаемой продолжительности жизни ниже среднего: