Перейти к содержанию

252 уроков, 17 библиотек и челлендж «Что выведет код?» — бесплатно, код прямо в браузере

Начать обучение
Урок 15 из 20 Средний 25 мин 120 XP

catplot: категориальные сетки графиков в Seaborn

Одна функция catplot заменяет полдесятка категориальных графиков: переключатель kind, раскладка по сетке col и row — и сравнение групп превращается в три панели рядом.

Редакция Питоники

К категории данных Seaborn предлагает десяток функций: barplot для средних, boxplot для разброса, pointplot для трендов — и это только начало списка. У каждой свои параметры, и на маленький вопрос «а как это выглядит по городам?» ответ почему-то требует переписывать вызов заново. sns.catplot закрывает этот разнобой: catplot — одна функция с переключателем kind: bar, box или point вместо трёх отдельных вызовов. Плюс то, чего у axes-level функций нет вовсе — автоматическая раскладка в сетку.

В этом уроке разберём три рабочих значения kind, соберём сетку панелей через col и row и сформулируем правило, когда figure-level функция выигрывает у axes-level. Данные те же, что и во всём курсе: интернет-магазин, выручка по городам за четыре месяца.

catplot: одна функция вместо десяти

Сначала посмотрим на таблицу, с которой работаем весь урок: три города, четыре месяца, выручка в тысячах рублей — 12 строк.

выручка по городам и месяцам
import pandas as pd

df = pd.DataFrame({
    "город": ["Москва", "Москва", "Москва", "Москва",
              "Казань", "Казань", "Казань", "Казань",
              "Сочи", "Сочи", "Сочи", "Сочи"],
    "месяц": ["янв", "фев", "мар", "апр",
              "янв", "фев", "мар", "апр",
              "янв", "фев", "мар", "апр"],
    "выручка": [412, 385, 467, 501,
                254, 241, 289, 296,
                187, 224, 310, 342],
})
print(df)
Вывод
     город месяц  выручка
0   Москва   янв      412
1   Москва   фев      385
2   Москва   мар      467
3   Москва   апр      501
4   Казань   янв      254
5   Казань   фев      241
6   Казань   мар      289
7   Казань   апр      296
8     Сочи   янв      187
9     Сочи   фев      224
10    Сочи   мар      310
11    Сочи   апр      342

В данных видна история: Москва стабильна и велика, Казань стоит на месте, а Сочи разгоняется к сезону. Именно такие сюжеты удобно показывать catplot: он сам сгруппирует строки по городу, посчитает средние и нарисует. Первый вызов — со значением kind="bar":

kind=bar — средние по городам
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd

df = pd.DataFrame({
    "город": ["Москва", "Москва", "Москва", "Москва",
              "Казань", "Казань", "Казань", "Казань",
              "Сочи", "Сочи", "Сочи", "Сочи"],
    "месяц": ["янв", "фев", "мар", "апр",
              "янв", "фев", "мар", "апр",
              "янв", "фев", "мар", "апр"],
    "выручка": [412, 385, 467, 501,
                254, 241, 289, 296,
                187, 224, 310, 342],
})

sns.catplot(data=df, x="город", y="выручка", kind="bar")
plt.show()
Вывод
График отображается под редактором

Получились столбцы средних с чёрными усами — доверительными интервалами, знакомыми по уроку про barplot. Заметно и главное отличие: мы не вызывали plt.subplots() и не передавали ax. catplot относится к figure-level функциям: он сам создаёт фигуру целиком и возвращает объект-контейнер, а не рисует в готовую панель. Подробно про контейнер — ниже, а пока поменяем kind.

kind: bar, box, point

kind — переключатель типа категориального графика. kind="box" вместо столбцов рисует ящики с усами: медиану, квартили и выбросы — всю форму распределения по каждой группе. Это то же самое, что делает sns.boxplot, только с готовой инфраструктурой сетки:

kind=box — распределения по городам
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd

df = pd.DataFrame({
    "город": ["Москва", "Москва", "Москва", "Москва",
              "Казань", "Казань", "Казань", "Казань",
              "Сочи", "Сочи", "Сочи", "Сочи"],
    "месяц": ["янв", "фев", "мар", "апр",
              "янв", "фев", "мар", "апр",
              "янв", "фев", "мар", "апр"],
    "выручка": [412, 385, 467, 501,
                254, 241, 289, 296,
                187, 224, 310, 342],
})

sns.catplot(data=df, x="город", y="выручка", kind="box")
plt.show()
Вывод
График отображается под редактором

Третье частое значение — kind="point": точки средних, соединённые линией. Столбцы хороши для сравнения размеров, а точки с линией — для тренда: рост или падение по оси читаются наклоном. Положим на ось X месяцы, а города раскрасим через hue:

kind=point — тренд по месяцам с разбивкой
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd

df = pd.DataFrame({
    "город": ["Москва", "Москва", "Москва", "Москва",
              "Казань", "Казань", "Казань", "Казань",
              "Сочи", "Сочи", "Сочи", "Сочи"],
    "месяц": ["янв", "фев", "мар", "апр",
              "янв", "фев", "мар", "апр",
              "янв", "фев", "мар", "апр"],
    "выручка": [412, 385, 467, 501,
                254, 241, 289, 296,
                187, 224, 310, 342],
})

sns.catplot(data=df, x="месяц", y="выручка", kind="point", hue="город")
plt.show()
Вывод
График отображается под редактором

Три линии — три города, и история данных видна сразу: Москва идёт ровно вверх, Казань чуть подрастает, Сочи выстреливает весной. На bar-графике тот же сюжет потребовал бы трёх групп столбцов и превратился бы в частокол. Правило выбора простое: сравниваем величины — bar; смотрим форму распределения — box; смотрим динамику по категориям — point.

col и row: сетка малых кратных

Главная способность catplot, которой нет у barplot и company, — раскладка в сетку. Параметр col="город" говорит: сделай по панели на каждое значение колонки «город» и поставь их в ряд по колонкам. Один вызов — и сравнение групп происходит взглядом слева направо:

col=город — по панели на каждый город
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd

df = pd.DataFrame({
    "город": ["Москва", "Москва", "Москва", "Москва",
              "Казань", "Казань", "Казань", "Казань",
              "Сочи", "Сочи", "Сочи", "Сочи"],
    "месяц": ["янв", "фев", "мар", "апр",
              "янв", "фев", "мар", "апр",
              "янв", "фев", "мар", "апр"],
    "выручка": [412, 385, 467, 501,
                254, 241, 289, 296,
                187, 224, 310, 342],
})

sns.catplot(
    data=df,
    x="месяц", y="выручка",
    col="город",
    kind="bar",
    height=3, aspect=0.8,
)
plt.show()
Вывод
График отображается под редактором

Параметры height и aspect задают размер панелей: height — высота каждой панели в дюймах, ширина получается умножением на aspect. У figure-level функций нет привычного figsize — фигуру собирает сама catplot, поэтому размер управляется именно так. Параметр row работает так же, но раскладывает панели по строкам; вместе они дают сетку col × row — об этом подробно в уроке про FacetGrid, который лежит под капотом catplot.

Что же возвращает catplot? Проверим тип и форму:

catplot возвращает FacetGrid
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd

df = pd.DataFrame({
    "город": ["Москва", "Казань", "Сочи", "Москва", "Казань", "Сочи"],
    "выручка": [412, 254, 187, 467, 289, 310],
})

g = sns.catplot(data=df, x="город", y="выручка", kind="bar")
print(type(g).__name__)
print(g.axes.shape)
plt.show()
Вывод
FacetGrid
(1, 1)

g — это FacetGrid: контейнер сетки панелей. Без col и row сетка состоит из одной панели, поэтому форма осей — (1, 1): одна строка, одна колонка. Добавьте col="город" с тремя городами — и shape станет (1, 3). С этим объектом можно дорабатывать график после отрисовки — тема урока 18.

Когда figure-level лучше axes-level

В Seaborn два этажа API, и выбирать между ними проще по задаче:

catplot (figure-level)barplot, boxplot, pointplot (axes-level)
Что возвращаетFacetGrid — контейнер сетки панелейобычный ax Matplotlib
Сетка панелей col/rowесть, из коробкинет — только вручную через subplots
Размерheight и aspectfigsize при создании фигуры
Встраивание в дашборднельзя — создаёт свою фигуруда, через ax=
Когда братьперебор видов, сравнение групп рядомодна панель, компоновка руками

Рабочее правило: если график один и его нужно встроить в свою композицию — axes-level функция с ax=. Если задача «покажи по каждой категории» или «перебери несколько видов» — catplot соберёт всё сам. Разбёрем финальный кадр урока: тот же point-тренд, но не наложением через hue, а сеткой по городам — каждому городу своя панель:

итог: сетка point-графиков одним вызовом
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd

df = pd.DataFrame({
    "город": ["Москва", "Москва", "Москва", "Москва",
              "Казань", "Казань", "Казань", "Казань",
              "Сочи", "Сочи", "Сочи", "Сочи"],
    "месяц": ["янв", "фев", "мар", "апр",
              "янв", "фев", "мар", "апр",
              "янв", "фев", "мар", "апр"],
    "выручка": [412, 385, 467, 501,
                254, 241, 289, 296,
                187, 224, 310, 342],
})

sns.catplot(
    data=df,
    x="месяц", y="выручка",
    col="город",
    kind="point",
    height=2.8, aspect=0.9,
)
plt.show()
Вывод
График отображается под редактором

Что дальше

catplot закрывает категориальный блок курса: один вызов, три вида, сетка панелей. Следующий урок — regplot: точки, линия регрессии и доверительная полоса, чтобы увидеть тренд двух числовых величин, а не групп. За ним — доводка любого из этих графиков до отчётного вида: заголовки, аннотации и сохранение в PNG.

catplot — одна функция с переключателем kind: bar, box или point вместо трёх отдельных вызовов.

Что выведет код?

Сначала предскажи ответ в голове — это главный навык программиста.

import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd

df = pd.DataFrame({
    "город": ["Москва", "Казань", "Сочи", "Москва", "Казань", "Сочи"],
    "выручка": [412, 254, 187, 467, 289, 310],
})

g = sns.catplot(data=df, x="город", y="выручка", kind="bar")
print(type(g).__name__)
import pandas as pd

df = pd.DataFrame({
    "город": ["Москва", "Казань", "Сочи", "Москва", "Казань", "Сочи"],
    "выручка": [412, 254, 187, 467, 289, 310],
})

print(df.groupby("город")["выручка"].mean().round(1).idxmax())
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd

df = pd.DataFrame({
    "город": ["Москва", "Казань", "Сочи"] * 2,
    "месяц": ["янв", "янв", "янв", "фев", "фев", "фев"],
    "выручка": [412, 254, 187, 467, 289, 310],
})

g = sns.catplot(data=df, x="месяц", y="выручка", col="город", kind="bar")
print(g.axes.shape)
Проверь себя
0 / 5

1. Что возвращает sns.catplot?

2. Какое значение kind нарисует точки средних, соединённые линией?

3. Что делает параметр col="город" в вызове catplot?

4. Почему вызову catplot нельзя передать параметр ax=?

5. За что отвечают height=3 и aspect=0.8 в вызове catplot?

Карточки терминов
Запомнено: 0 / 7
Практика

Постройте сетку catplot по данным двух категорий товаров в трёх городах: по панели на каждый город (col="город"), столбчатый график (kind="bar"), высота панели 3 дюйма. Данные уже в заготовке.

practice.py
Вопросы и ответы по уроку

Чем sns.catplot отличается от sns.barplot?

barplot — axes-level функция: рисует один график в готовую панель ax и возвращает её. catplot — figure-level надстройка: сама создаёт фигуру, возвращает FacetGrid и умеет раскладывать несколько панелей в сетку через col и row. kind="bar" у catplot внутри вызывает ту же логику barplot — столбцы средних с доверительными интервалами получаются одинаковыми.

Урок 18: FacetGrid — малые кратные

Как задать размер графика у catplot?

Параметрами height и aspect: height — высота каждой панели в дюймах, ширина равна height, умноженной на aspect. Например, height=3, aspect=0.8 даст панели 3 на 2.4 дюйма. Привычный figsize=(10, 4) catplot не принимает — он сам собирает фигуру, а размер сетки зависит ещё и от числа панелей.

Как задать свой порядок категорий в catplot?

Параметром order — списком значений по оси X, например order=["янв", "фев", "мар", "апр"]. Для категорий hue есть hue_order, для панелей сетки порядок задаёт col_order и row_order. Без них Seaborn берёт порядок первого появления значений в таблице.

Как добавить общий заголовок на график catplot?

Через Matplotlib-интерфейс фигуры: g = sns.catplot(...), затем g.figure.suptitle("Общий заголовок") перед plt.show(). Подписи отдельных панелей catplot расставляет сам методом set_titles — по значению категории. Доводке заголовков и аннотаций посвящён урок 17.

Урок 17: подписи, заголовки, аннотации

Понравился урок? Сошлитесь на него

«catplot — одна функция с переключателем kind: bar, box или point вместо трёх отдельных вызовов.»

Скопируйте готовую ссылку в формате HTML, Markdown или чистый адрес и вставьте в статью на Habr, VC, Telegram-канал или свой блог — так о проекте узнают новые читатели.

TelegramVK

Похожие уроки по темам

Подобраны автоматически по пересечению тем и ключевых слов.