heatmap в Seaborn: тепловая карта матрицы и корреляции
Матрица превращается в картинку: корреляции признаков и активность по дням-часам загораются цветом. annot, fmt, cmap, vmin и vmax — четыре ручки тепловой карты.
Редакция Питоники
Некоторые данные сами просятся в таблицу: посещения клуба по дням недели и часам, корреляции между признаками, расписание занятости. Семь строк на шесть колонок — сорок два числа, и глазу нужна минута, чтобы найти максимум. heatmap («тепловая карта») перекладывает эту работу на цвет: каждая ячейка таблицы получает оттенок пропорционально величине, и горячие зоны находятся за секунду.
Построим тепловую карту активности, разберём аннотации и формат чисел, а затем — второй классический сценарий: корреляционную матрицу df.corr() с дивергентной палитрой и фиксированной шкалой.
Активность по дням и часам
Сеть фитнес-клубов считает посещения: по строкам дни недели, по колонкам часы суток. Данные уже сведены в матрицу — DataFrame с индексом-днями и колонками-часами:
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
visits = pd.DataFrame(
[[14, 8, 5, 9, 22, 30],
[12, 7, 4, 8, 20, 28],
[16, 9, 6, 10, 25, 33],
[15, 8, 5, 9, 24, 31],
[20, 12, 8, 14, 38, 55],
[34, 28, 22, 30, 52, 61],
[30, 25, 18, 26, 47, 58]],
index=["Пн", "Вт", "Ср", "Чт", "Пт", "Сб", "Вс"],
columns=["9:00", "12:00", "15:00", "18:00", "21:00", "23:00"],
)
sns.set_theme()
ax = sns.heatmap(visits, annot=True, fmt="d", cmap="YlGnBu")
ax.set_title("Посещения клуба: тёплые зоны видны сразу")
plt.show()
График отображается под редактором
Выводы читаются с одного взгляда: выходные — два самых жарких ряда, вечер 21:00 — самый горячий столбец, а полдень вторника — ледяная ячейка. Тепловая карта делает незаметное видимым: сорок два числа таблицы превращаются в картинку, где горячие зоны светятся сами. Маркетинг клуба получит расписание акций без единого фильтра в Excel.
annot и fmt: числа в ячейках
Параметр annot=True подписывает каждую ячейку значением, а fmt задаёт формат числа: "d" — целое, ".1f" и ".2f" — один и два знака после запятой. Без annot карта остаётся чистым цветом — красиво, но нечитаемо точно; с annot график самодостаточен и в отчёте, и на печати.
Матрица корреляций: df.corr()
Второй классический сценарий — разведочный анализ: какие признаки вообще связаны. Возьмём неделю работы магазина: рекламный бюджет, посетители и выручка по дням. Метод df.corr() возвращает таблицу парных корреляций — чисел от -1 до 1, где 1 означает идеальную прямую связь, -1 — идеальную обратную, а 0 — отсутствие линейной связи:
import pandas as pd
shop = pd.DataFrame({
"ads": [12, 18, 25, 31, 40, 47, 55, 62],
"visitors": [130, 165, 240, 255, 350, 380, 470, 505],
"sales": [95, 140, 205, 230, 300, 345, 400, 455],
})
corr = shop.corr()
print(corr)
ads visitors sales ads 1.000000 0.995941 0.998877 visitors 0.995941 1.000000 0.996866 sales 0.998877 0.996866 1.000000
Читаем таблицу. Диагональ всегда единицы — признак коррелирует сам с собой идеально. Матрица симметрична: связь ads-visitors и visitors-ads — одно число. Вне диагонали три числа близки к 1: реклама, трафик и выручка в этой неделе идут рука об руку. Вытащим одну ячейку поименованно — так удобнее в коде отчёта:
import pandas as pd
shop = pd.DataFrame({
"ads": [12, 18, 25, 31, 40, 47, 55, 62],
"visitors": [130, 165, 240, 255, 350, 380, 470, 505],
"sales": [95, 140, 205, 230, 300, 345, 400, 455],
})
corr = shop.corr()
print(round(corr.loc["ads", "sales"], 2))
1.0
Округление до двух знаков даёт 1.0: связь бюджета с выручкой почти функциональная — 0.998877, как показала полная матрица. В реальных данных такие числа встречаются редко и заслуживают проверки: а не дублируют ли колонки друг друга?
heatmap корреляций: дивергентная палитра и vmin/vmax
Корреляция живёт на шкале от -1 до 1, и для неё нужна палитра с бледной серединой: слабые связи бледнеют, сильные прямые и обратные — загораются двумя цветами. Заодно фиксируем шкалу параметрами vmin=-1 и vmax=1, чтобы цвета были сравнимы между разными матрицами:
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
shop = pd.DataFrame({
"ads": [12, 18, 25, 31, 40, 47, 55, 62],
"visitors": [130, 165, 240, 255, 350, 380, 470, 505],
"sales": [95, 140, 205, 230, 300, 345, 400, 455],
})
sns.set_theme()
corr = shop.corr()
ax = sns.heatmap(corr, annot=True, fmt=".2f",
cmap="RdBu_r", vmin=-1, vmax=1, center=0)
ax.set_title("Корреляции магазина: красное минус, синее плюс")
plt.show()
График отображается под редактором
fmt=".2f" округлил числа до двух знаков — в ячейках ровно столько точности, сколько читается. center=0 поставил бледный цвет в ноль шкалы. Без vmin и vmax Seaborn растянул бы палитру на фактический диапазон данных, и в матрице без отрицательных связей даже слабая корреляция выглядела бы насыщенно-красной — сравнивать две такие карты между собой было бы нельзя.
Параметры vmin= и vmax= работают и на картах величин: явные границы удобны, когда данные имеют понятный потолок — проценты от 0 до 100 или число мест в зале. С ними две тепловые карты за разные недели сравниваются честно, ячейка в ячейку.
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
visits = pd.DataFrame(
[[14, 8, 5, 9, 22, 30],
[12, 7, 4, 8, 20, 28],
[16, 9, 6, 10, 25, 33],
[15, 8, 5, 9, 24, 31],
[20, 12, 8, 14, 38, 55],
[34, 28, 22, 30, 52, 61],
[30, 25, 18, 26, 47, 58]],
index=["Пн", "Вт", "Ср", "Чт", "Пт", "Сб", "Вс"],
columns=["9:00", "12:00", "15:00", "18:00", "21:00", "23:00"],
)
sns.set_theme()
ax = sns.heatmap(visits, annot=True, fmt="d",
cmap="YlGnBu", vmin=0, vmax=70)
ax.set_title("Шкала от 0 до 70: цвет сравним с прошлой неделей")
plt.show()
График отображается под редактором
cmap: какой набор цветов взять
Параметр cmap= принимает те же наборы, что мы разбирали в уроке про палитры, и выбор снова определяется смыслом цвета:
| Данные | Тип палитры | Примеры cmap |
|---|---|---|
| Величина «от малого к большому» | Последовательная | YlGnBu, Blues, viridis |
| Отклонение от середины | Дивергентная | RdBu_r, coolwarm, PiYG |
| Особая точка данных | Категориальная не подходит: heatmap кодирует величину | — |
Для посещений клуба подошла последовательная YlGnBu: больше visits — темнее клетка. Для корреляций — дивергентная RdBu_r: два смысла по обе стороны нуля. Проверим границы наших данных числом — они и попадут в края палитры:
import pandas as pd
visits = pd.DataFrame(
[[14, 8, 5, 9, 22, 30],
[12, 7, 4, 8, 20, 28],
[16, 9, 6, 10, 25, 33],
[15, 8, 5, 9, 24, 31],
[20, 12, 8, 14, 38, 55],
[34, 28, 22, 30, 52, 61],
[30, 25, 18, 26, 47, 58]],
index=["Пн", "Вт", "Ср", "Чт", "Пт", "Сб", "Вс"],
columns=["9:00", "12:00", "15:00", "18:00", "21:00", "23:00"],
)
print(visits.values.min(), visits.values.max())
4 61
От четырёх посещений в полдень вторника до 61 в воскресенье ночью — именно эти ячейки станут крайними точками шкалы цвета. Промежуточные оттенки распределятся линейно между ними; адресовать отдельную ячейку можно через .loc, как мы делали с корреляцией.
Сводная таблица перед heatmap
В реальных проектах данные чаще лежат длинным форматом: строка на каждое посещение с колонками day, hour, visits. Тепловой карте нужна широкая матрица — и её собирает pivot_table, знакомый по уроку про группировку Pandas: pv = df.pivot_table(index="day", columns="hour", values="visits", aggfunc="sum"). Дальше — знакомый вызов sns.heatmap(pv). Единственная ловушка уже описана выше: если в ячейках появились NaN, fmt="d" упадёт, и понадобится либо fillna(0), либо fmt=".0f".
Что дальше
Тепловая карта закрыла таблицы: матрица активности и корреляции признаков читаются в цвете. Следующий шаг — pairplot: сетка диаграмм рассеяния по всем парам числовых колонок сразу, разведочный анализ всего набора данных двумя строками. Вместе они — стандартный старт любого нового датасета.
Тепловая карта делает незаметное видимым: сорок два числа таблицы превращаются в картинку, где горячие зоны светятся сами.
Сначала предскажи ответ в голове — это главный навык программиста.
import pandas as pd
df = pd.DataFrame({
"x": [1, 2, 3, 4],
"y": [2, 4, 6, 8],
})
print(df["x"].corr(df["y"]))
import pandas as pd
df = pd.DataFrame({
"x": [1, 2, 3, 4],
"y": [8, 6, 4, 2],
})
print(df["x"].corr(df["y"]))
import pandas as pd
visits = pd.DataFrame(
[[14, 8],
[12, 7],
[16, 9]],
index=["Пн", "Вт", "Ср"],
columns=["9:00", "21:00"],
)
print(visits.shape)
1. Что ожидает sns.heatmap на входе?
2. Зачем в корреляционной heatmap параметры vmin=-1 и vmax=1?
3. Почему на диагонали корреляционной матрицы стоят единицы?
4. Код упал с ValueError: Unknown format code 'd' for object of type 'float'. Что произошло?
5. Какую палитру логично взять для heatmap корреляций от -1 до 1?
В редакторе — таблица цены товара и спроса за шесть недель. Посчитайте корреляции df.corr() и выведите одним числом связь колонок price и demand, округлённую до двух знаков после запятой.
Что показывает sns.heatmap?
Тепловая карта перекрашивает матрицу в цвет: каждая ячейка DataFrame получает оттенок по величине. Классические сценарии — активность по дням и часам, корреляционная матрица df.corr(), расписание загрузки. annot=True добавляет числа в ячейки, cmap выбирает набор цветов.
Урок 12: heatmap — тепловая картаКак построить матрицу корреляций в Python?
Две строки: corr = df.corr() считает парные корреляции числами от -1 до 1, затем sns.heatmap(corr, annot=True, cmap="RdBu_r", vmin=-1, vmax=1) рисует их в цвете. Дивергентная палитра и фиксированная шкала обязательны: сильная обратная связь должна красным отличаться от слабой.
Почему heatmap выдаёт ValueError с fmt="d"?
Формат "d" работает только с целыми числами. Дробные значения или пропуски NaN в матрице вызывают ValueError: Unknown format code 'd' for object of type 'float'. Используйте fmt=".0f" или приведите таблицу к целым: df.astype(int).
Диагональ корреляционной матрицы всегда единичная — это нормально?
Да: признак коррелирует сам с собой идеально, поэтому на диагонали единицы, а матрица симметрична. На heatmap диагональ часто скрывают (np.fill_diagonal или маска), чтобы взгляд цеплялся за связи между разными признаками.
Понравился урок? Сошлитесь на него
«Тепловая карта делает незаметное видимым: сорок два числа таблицы превращаются в картинку, где горячие зоны светятся сами.»
Скопируйте готовую ссылку в формате HTML, Markdown или чистый адрес и вставьте в статью на Habr, VC, Telegram-канал или свой блог — так о проекте узнают новые читатели.
Что читать дальше
Seaborn · Урок 11
violinplot в Seaborn: форма распределения вместо ящика
Скрипка показывает распределение целиком: где масса наблюдений, где хвосты и есть ли второй горб. Сравниваем с boxplot, режем скрипку параметром split.
Seaborn · Урок 13
pairplot в Seaborn: все связи между колонками одной сеткой
Одна строка — и все пары числовых колонок нарисованы: scatter вне диагонали, распределения на ней, hue раскрашивает группы. Разведочный анализ квартир за минуту.
Похожие уроки по темам
Подобраны автоматически по пересечению тем и ключевых слов.
Matplotlib / Seaborn · Урок 9
Тепловая карта в Matplotlib: imshow и colorbar
Матрица чисел превращается в карту за один вызов: plt.imshow, colorbar, выбор cmap, аннотации через plt.text и кейс — корреляционная матрица np.corrcoef на чистых numpy-массивах. Код запускается на странице.
matplotlib heatmapтепловая карта python
Matplotlib / Seaborn · Урок 4
Диаграммы рассеяния scatter: ищем связи между величинами
scatter для поиска связей между величинами: форма облака точек, цвет и размер как третье измерение, alpha против оверплоттинга и кейс с 300 измерениями.
корреляция на графикесвязь между величинами график python
Seaborn · Урок 5
scatterplot в Seaborn: связь двух величин на точках
Диаграмма рассеяния показывает связь двух числовых столбцов: одна строка таблицы — одна точка. Управляем размером s и прозрачностью alpha и учимся видеть кластеры.
seaborn scatterplotточечный график python