jointplot в Seaborn: связь двух величин и распределения по краям
jointplot рисует связь двух величин в центре и их распределения по краям: сгущения и выбросы видны одновременно. kind="kde" и kind="hex" для плотных данных.
Редакция Питоники
Scatterplot из пятого урока отвечает на вопрос «связаны ли величины» облаком точек. Но у внимательного читателя сразу два вопроса: как связаны — и как каждая величина распределена сама по себе. Pairplot прошлой минуты рисует все пары сразу, но мелко. jointplot — крупный план одной пары: диаграмма рассеяния в центре и распределения обеих величин по краям той же картинки.
Строим первый jointplot, разбираемся с JointGrid, добавляем подписи, пробуем kind="kde" и kind="hex" и формулируем, когда этот график лучше обычного scatter.
Первый jointplot: часы подготовки и балл
Сквозной пример — выпускники курса: часы подготовки против балла за экзамен. Один вызов — и три панели вместо трёх отдельных графиков:
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
exam = pd.DataFrame({
"hours": [2, 3, 4, 5, 6, 7, 8, 9, 10, 12],
"score": [45, 52, 58, 65, 70, 74, 80, 84, 88, 95],
})
sns.set_theme()
g = sns.jointplot(data=exam, x="hours", y="score")
plt.show()
График отображается под редактором
В центре — знакомое вытянутое облако: больше часов, выше балл. Сверху — гистограмма часов, справа — гистограмма баллов. Правая гистограмма сразу показывает деталь, которую в облаке легко пропустить: баллы сгущаются у верхней границы — потолок экзамена подтянул к себе верхнюю часть распределения.
JointGrid: это не Axes
jointplot возвращает не оси, а объект JointGrid — контейнер из трёх осей: центральной ax_joint и двух краевых ax_marg_x и ax_marg_y. Проверим:
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
exam = pd.DataFrame({
"hours": [2, 3, 4, 5, 6, 7, 8, 9, 10, 12],
"score": [45, 52, 58, 65, 70, 74, 80, 84, 88, 95],
})
g = sns.jointplot(data=exam, x="hours", y="score")
print(type(g).__name__)
print(len(g.figure.axes))
JointGrid 3
JointGrid, и на фигуре три оси — центральная и две краевые гистограммы. Из этого следует всё остальное: у JointGrid свои методы доводки, а к центральной панели можно обращаться напрямую, как к обычным осям Matplotlib.
Доводка: подписи и заголовок
Подписи через g.set_axis_labels(), заголовок центральной панели — привычным методом у g.ax_joint:
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
exam = pd.DataFrame({
"hours": [2, 3, 4, 5, 6, 7, 8, 9, 10, 12],
"score": [45, 52, 58, 65, 70, 74, 80, 84, 88, 95],
})
sns.set_theme()
g = sns.jointplot(data=exam, x="hours", y="score")
g.set_axis_labels("Часы подготовки", "Баллы")
g.ax_joint.set_title("Экзамен: чем больше часов, тем выше балл")
plt.show()
График отображается под редактором
Через ax_joint доступна вся техника Matplotlib: сетка, аннотации, сохранение. Есть и встречное движение — метод g.plot_joint(sns.regplot) дорисует в центр линию регрессии; ей посвящён шестнадцатый урок про regplot, а следующий, пятнадцатый, отдаёт сеткам категориальных графиков — catplot.
kind="kde": плавные контуры
Аргумент kind= меняет тип центрального и краевых графиков. Значение "kde" рисует сглаженные контуры плотности — облако точек превращается в топографическую карту:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
np.random.seed(42)
hours = np.random.normal(6, 2, 300).clip(0.5, 12)
score = 40 + 5 * hours + np.random.normal(0, 6, 300)
exam = pd.DataFrame({"hours": hours.round(1), "score": score.round(1)})
sns.set_theme()
g = sns.jointplot(data=exam, x="hours", y="score", kind="kde",
fill=True, cmap="Blues")
g.set_axis_labels("Часы подготовки", "Баллы")
plt.show()
График отображается под редактором
Контуры сгущаются к центру массы — самый тёмный бугор показывает, где сидит типичный выпускник: около шести часов и семидесяти баллов. Краевые кривые тоже стали KDE — тот же вид плотности, что в уроке про violinplot. Для трёхсот точек это честная картина; для десяти наблюдений KDE нарисовал бы горы из ничего.
kind="hex": соты для плотных данных
На тысячах точек scatter перестаёт читаться: точки ложатся друг на друга, и график чернеет — это оверплоттинг из четвёртого урока Matplotlib. Лечение — kind="hex": плоскость делится на шестиугольные ячейки, цвет показывает число точек в ячейке:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
np.random.seed(42)
ages = np.random.normal(45, 12, 3000).clip(18, 80)
spend = 300 + 8 * ages + np.random.normal(0, 60, 3000)
mall = pd.DataFrame({"age": ages.round(0), "spend": spend.round(0)})
sns.set_theme()
g = sns.jointplot(data=mall, x="age", y="spend", kind="hex")
g.set_axis_labels("Возраст посетителя", "Средний чек, руб.")
plt.show()
График отображается под редактором
Тёмные соты — сгущения, светлые — редкие зоны; краевые гистограммы остались на месте. Мини-наблюдение за один взгляд: скопление аудитории 35–55 лет с чеком 600–750 рублей. Scatter из трёх тысяч точек показал бы вместо этого чёрный прямоугольник.
Когда jointplot лучше scatterplot
Выбор между ними — выбор вопроса. Если интересует только связь, scatterplot быстрее и гибче: в него встраиваются hue, размер и стиль точек. jointplot платит местом за краевые распределения и берёт своё, когда форму распределений нужно видеть рядом со связью:
| Задача | Инструмент |
|---|---|
| Связь двух величин и их распределения | sns.jointplot |
| Только связь, с разбивкой по группам | sns.scatterplot с hue= |
| Все пары колонок сразу | sns.pairplot (урок 13) |
| Тысячи точек вместо чёрного пятна | sns.jointplot(kind="hex") |
hue= поддерживается и в jointplot — краевые распределения станут KDE по группам. Но с ростом числа групп картинка теснится, и для сравнения групп обычно честнее вернуться к scatterplot на полной ширине.
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
prep = pd.DataFrame({
"hours": [2, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7],
"score": [48, 55, 60, 68, 73, 80, 42, 50, 57, 61, 66, 74],
"school": ["первая"] * 6 + ["вторая"] * 6,
})
sns.set_theme()
g = sns.jointplot(data=prep, x="hours", y="score", hue="school")
g.set_axis_labels("Часы подготовки", "Баллы")
plt.show()
График отображается под редактором
Что дальше
Теперь у нас есть крупный план пары величин с их распределениями. Следующий урок снова меняет масштаб: catplot строит сетки категориальных графиков — один вызов рисует bar или box отдельно для каждой группы, малые кратные для сравнения городов и категорий.
jointplot честнее scatterplot: он показывает не только связь двух величин, но и их распределения по краям — сгущения и выбросы видны сразу.
Сначала предскажи ответ в голове — это главный навык программиста.
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
df = pd.DataFrame({
"x": [1, 2, 3, 4, 5],
"y": [2, 4, 5, 4, 5],
})
g = sns.jointplot(data=df, x="x", y="y")
print(type(g).__name__)
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
df = pd.DataFrame({
"x": [1, 2, 3, 4, 5],
"y": [2, 4, 5, 4, 5],
})
g = sns.jointplot(data=df, x="x", y="y")
print(len(g.figure.axes))
import pandas as pd
exam = pd.DataFrame({
"hours": [2, 3, 4, 5, 6, 7, 8, 9, 10, 12],
"score": [45, 52, 58, 65, 70, 74, 80, 84, 88, 95],
})
print(round(exam["hours"].corr(exam["score"]), 2))
1. Что рисует sns.jointplot(data=df, x="a", y="b") по умолчанию?
2. Какой объект возвращает jointplot?
3. Код g = sns.jointplot(...); g.set_title("Заголовок") упал. Как исправить?
4. На графике три тысячи точек слились в чёрное пятно. Что выбрать?
5. Когда обычный scatterplot предпочтительнее jointplot?
В редакторе — данные о стримах кафе: минуты музыки (minutes) и число новых подписчиков (followers). Постройте jointplot с плавными контурами плотности (kind="kde") и подпишите оси «Минуты стрима» и «Новые подписчики».
Что показывает jointplot в Seaborn?
Связь двух величин в центре и распределения каждой по краям: scatter плюс две гистограммы на одной фигуре. Так видны сразу и связь, и сгущения, и выбросы — один график вместо трёх.
Урок 14: jointplot — две величины и краяПочему у jointplot не работает set_title?
jointplot возвращает JointGrid, а не Axes — у этого объекта нет метода set_title. Заголовок центральной панели ставят через g.ax_joint.set_title(), общий заголовок фигуры — через g.figure.suptitle(), подписи обеих осей — через g.set_axis_labels().
Что выбрать — kind="kde" или kind="hex"?
kde рисует плавные контуры плотности и хорош на сотнях точек с одной сгущённой массой. hex делит плоскость на соты и честнее показывает сгущения на тысячах точек, где scatter чернеет. На малых выборках оба вводят в заблуждение — оставайтесь на scatter.
Можно ли добавить hue в jointplot?
Да: sns.jointplot(..., hue="group") раскрасит центральный scatter и превратит краевые гистограммы в KDE по группам. Для трёх и более групп картинка становится тесной — тогда лучше обычный scatterplot с hue на полной ширине.
Понравился урок? Сошлитесь на него
«jointplot честнее scatterplot: он показывает не только связь двух величин, но и их распределения по краям — сгущения и выбросы видны сразу.»
Скопируйте готовую ссылку в формате HTML, Markdown или чистый адрес и вставьте в статью на Habr, VC, Telegram-канал или свой блог — так о проекте узнают новые читатели.
Что читать дальше
Seaborn · Урок 13
pairplot в Seaborn: все связи между колонками одной сеткой
Одна строка — и все пары числовых колонок нарисованы: scatter вне диагонали, распределения на ней, hue раскрашивает группы. Разведочный анализ квартир за минуту.
Seaborn · Урок 15
catplot: категориальные сетки графиков в Seaborn
Одна функция catplot заменяет полдесятка категориальных графиков: переключатель kind, раскладка по сетке col и row — и сравнение групп превращается в три панели рядом.
Похожие уроки по темам
Подобраны автоматически по пересечению тем и ключевых слов.
Matplotlib / Seaborn · Урок 4
Диаграммы рассеяния scatter: ищем связи между величинами
scatter для поиска связей между величинами: форма облака точек, цвет и размер как третье измерение, alpha против оверплоттинга и кейс с 300 измерениями.
plt.scatter описаниеmatplotlib scatter
Matplotlib / Seaborn · Урок 10
Проект по визуализации: дашборд данных о фильмах на Matplotlib и Seaborn
Финальный проект курса: датасет из 200 фильмов, EDA, дашборд 2x2 с трендом, жанрами, гистограммой и scatter — плюс чек-лист «график готов к показу» и итоги десяти уроков.
matplotlib seabornгистограмма python matplotlib
Seaborn · Урок 5
scatterplot в Seaborn: связь двух величин на точках
Диаграмма рассеяния показывает связь двух числовых столбцов: одна строка таблицы — одна точка. Управляем размером s и прозрачностью alpha и учимся видеть кластеры.
seaborn scatterplotточечный график python