regplot: тренд и регрессия на графике рассеяния
Точки, линия регрессии и доверительная полоса одним вызовом regplot: как увидеть тренд двух величин, когда прямая врёт и что говорит наклон.
Редакция Питоники
На диаграмме рассеяния из урока 5 облако точек отвечает на вопрос «есть ли связь» — но полуточно: глаз ловит направление облака, а где именно проходит тренд и насколько он надёжен, приходится угадывать. sns.regplot доводит ответ до конца: рисует те же точки и добавляет линию регрессии — прямую, проведённую через облако методом наименьших квадратов, — и обводит её доверительной полосой, которая показывает, насколько линии можно верить.
Разберём на данных, к которым вернёмся весь урок: интернет-магазин 12 недель меняет рекламный бюджет и записывает выручку. Обе величины — в тысячах рублей.
Точки, линия и доверительная полоса
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
df = pd.DataFrame({
"реклама": [12, 18, 25, 30, 35, 41, 48, 55, 60, 68, 75, 82],
"выручка": [340, 372, 415, 452, 470, 521, 548, 601, 623, 655, 702, 738],
})
sns.regplot(data=df, x="реклама", y="выручка")
plt.show()
График отображается под редактором
На графике три слоя. Точки — сами недели, как их отрисовал бы scatterplot. Прямая — итог линейной регрессии: единственная прямая, сумма квадратов расстояний до которой минимальна. Полупрозрачная полоса вокруг — 95-процентный доверительный интервал: диапазон, в котором, скорее всего, лежит настоящая линия зависимости. Полоса уже в середине, где точки плотные, и расширяется к краям, где данных мало, — это её честная работа.
Что говорит наклон
Наклон — главный вывод графика. Уравнение прямой regplot не пишет, но его можно получить тем же методом наименьших квадратов через np.polyfit:
import pandas as pd
import numpy as np
df = pd.DataFrame({
"реклама": [12, 18, 25, 30, 35, 41, 48, 55, 60, 68, 75, 82],
"выручка": [340, 372, 415, 452, 470, 521, 548, 601, 623, 655, 702, 738],
})
slope, intercept = np.polyfit(df["реклама"], df["выручка"], 1)
print(round(slope, 1))
print(round(intercept, 1))
5.7 275.0
Наклон 5.7 означает: каждый дополнительный рубль рекламы приносит в среднем 5.7 рубля выручки, а свободный член 275 — базовая выручка без рекламы. Формулировка «в среднем» здесь принципиальна: точки не лежат на прямой идеально, и это нормально. О силе связи говорит коэффициент корреляции — в наших данных 0.999, связь практически функциональная. И ещё принципиальнее: регрессия показывает совместное движение, а не причину — возможно, обе величины растут от третьего фактора, например сезонности.
ci=None: когда полоса мешает
Полоса полезна при чтении, но в презентации её часто убирают: она утолщает линию и спорит за внимание. Параметр ci=None отключает доверительный интервал, а line_kws и marker позволяют заодно довести стиль — цвет и толщину линии, форму маркеров:
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
df = pd.DataFrame({
"реклама": [12, 18, 25, 30, 35, 41, 48, 55, 60, 68, 75, 82],
"выручка": [340, 372, 415, 452, 470, 521, 548, 601, 623, 655, 702, 738],
})
sns.regplot(
data=df, x="реклама", y="выручка",
ci=None,
marker="x", color="seagreen",
line_kws={"linewidth": 2},
)
plt.show()
График отображается под редактором
Когда зависимость не прямая: order и logx
Прямая — частный случай. Температура за день растёт до полудня и падает после: точки выгибаются дугой, и прямая проходит мимо пика. Параметр order=2 просит regplot подогнать полином второй степени — параболу:
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
# Температура по часам относительно полудня
day = pd.DataFrame({
"часы": [-3, -2, -1, 0, 1, 2, 3],
"температура": [18, 21, 24, 25, 24, 21, 18],
})
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 4))
sns.regplot(data=day, x="часы", y="температура", order=1, ax=ax1)
ax1.set_title("order=1: прямая не ловит пик")
sns.regplot(data=day, x="часы", y="температура", order=2, ax=ax2)
ax2.set_title("order=2: кривая ловит пик")
plt.tight_layout()
plt.show()
График отображается под редактором
Слева прямая легла почти плашмя и сообщает: «время суток с температурой не связано», — очевидный абсурд. Справа order=2 выгибает кривую и находит пик в нуле — в полдень. Степень order подбирают по форме облака и не задирают без нужды: каждая лишняя степень заставляет линию выгибаться в погоне за отдельными точками. Второй частый изгиб — быстрый рост, выходящий на плато: охват рекламы растёт от бюджета всё медленнее. Здесь помогает logx=True: перед подгонкой ось X логарифмируется, и кривая насыщения выпрямляется в линию.
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
# Охват рекламы от бюджета: растёт всё медленнее
ads = pd.DataFrame({
"бюджет": [10, 20, 40, 80, 160, 320, 640],
"охват": [11000, 19500, 31000, 46000, 59000, 68000, 73000],
})
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 4))
sns.regplot(data=ads, x="бюджет", y="охват", ax=ax1)
ax1.set_title("Прямая: явно не то")
sns.regplot(data=ads, x="бюджет", y="охват", logx=True, ax=ax2)
ax2.set_title("logx=True: лог-кривая легла в точки")
plt.tight_layout()
plt.show()
График отображается под редактором
Соберём параметры регрессии в одну таблицу:
| Параметр | Что делает | Когда включать |
|---|---|---|
| ci=None | Убирает доверительную полосу | Чистый стиль для презентации |
| order=2 | Подгоняет параболу вместо прямой | Облако выгибается дугой |
| logx=True | Логарифмирует X перед подгонкой | Быстрый рост с выходом на плато |
| scatter=False | Рисует только линию | Линия поверх готовых точек |
| line_kws | Стиль линии: цвет, толщина | Доводка под палитру отчёта |
Заметьте: у regplot нет параметра hue. Провести две линии на одной панели можно двумя вызовами с одним ax — regplot относится к axes-level функциям и встраивается в любую композицию subplots:
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
online = pd.DataFrame({
"реклама": [12, 25, 35, 48, 60, 75],
"выручка": [380, 460, 530, 610, 680, 750],
})
offline = pd.DataFrame({
"реклама": [12, 25, 35, 48, 60, 75],
"выручка": [330, 360, 400, 440, 470, 510],
})
fig, ax = plt.subplots(figsize=(8, 4))
sns.regplot(data=online, x="реклама", y="выручка", ax=ax, ci=None, label="онлайн")
sns.regplot(data=offline, x="реклама", y="выручка", ax=ax, ci=None, label="офлайн")
ax.legend()
ax.set_title("Наклон у каналов разный")
plt.show()
График отображается под редактором
Что дальше
regplot отвечает на вопрос «куда идёт тренд» — но график без заголовка, подписей осей и аннотации пика в отчёте никто не поймёт. Следующий урок — подписи, заголовки и аннотации: дорабатываем всё, что нарисовал Seaborn, руками Matplotlib и сохраняем в PNG для презентации.
Доверительная полоса — честность графика: она шире там, где данных мало, и сжимается там, где данные плотные.
Сначала предскажи ответ в голове — это главный навык программиста.
import pandas as pd
import numpy as np
df = pd.DataFrame({
"реклама": [12, 18, 25, 30, 35, 41, 48, 55, 60, 68, 75, 82],
"выручка": [340, 372, 415, 452, 470, 521, 548, 601, 623, 655, 702, 738],
})
slope, intercept = np.polyfit(df["реклама"], df["выручка"], 1)
print(round(slope, 1), round(intercept, 1))
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
df = pd.DataFrame({
"x": [1, 2, 3, 4],
"y": [10, 20, 15, 30],
})
ax = sns.regplot(data=df, x="x", y="y")
print(type(ax).__name__)
import pandas as pd
df = pd.DataFrame({
"реклама": [12, 18, 25, 30, 35, 41, 48, 55, 60, 68, 75, 82],
"выручка": [340, 372, 415, 452, 470, 521, 548, 601, 623, 655, 702, 738],
})
print(df["реклама"].corr(df["выручка"]).round(3))
1. Что рисует один вызов sns.regplot?
2. Что делает параметр ci=None?
3. Когда regplot нужен параметр order=2?
4. Зависимость растёт всё медленнее и выходит на плато. Какую настройку выбрать?
5. Наклон линии регрессии равен 5.7. Как это прочитать?
Постройте regplot зависимости цены квартиры от площади: уберите доверительную полосу, увеличьте точки через scatter_kws={"s": 40} и покрасьте линию в цвет "crimson" через line_kws. Данные в заготовке.
Чем regplot отличается от lmplot?
regplot — axes-level функция: рисует одну панель в готовый ax. lmplot — figure-level обёртка над ней: сама создаёт фигуру, умеет раскрашивать по hue и раскладывать линии в сетку панелей col и row. Внутри lmplot вызывает ту же регрессию — линии совпадают один в один.
Урок 15: catplot и figure-level APIЧто означает доверительная полоса на regplot?
Это 95-процентный доверительный интервал линии регрессии: диапазон, где с высокой вероятностью лежит настоящая зависимость. Полоса расширяется к краям графика, где точек мало, и сужается в плотной середине. Узкая полоса — линии можно верить, широкая — данных не хватает и наклон определён грубо.
Как нарисовать только линию регрессии без точек?
Параметром scatter=False: sns.regplot(data=df, x="реклама", y="выручка", scatter=False). Приём используют, когда точки уже нарисованы другим вызовом — например, цветным scatterplot по категориям — и поверх добавляют одну общую линию тренда.
Почему линия регрессии не доказывает причинность?
Регрессия фиксирует совместное движение: рост X сопровождается ростом Y в среднем на величину наклона. Но обе величины могут реагировать на третий фактор — сезонность, курс валюты, рост самой компании. Линия — описание данных, а не вывод о механизме; причинность проверяют экспериментом, а не графиком.
Понравился урок? Сошлитесь на него
«Доверительная полоса — честность графика: она шире там, где данных мало, и сжимается там, где данные плотные.»
Скопируйте готовую ссылку в формате HTML, Markdown или чистый адрес и вставьте в статью на Habr, VC, Telegram-канал или свой блог — так о проекте узнают новые читатели.
Что читать дальше
Seaborn · Урок 15
catplot: категориальные сетки графиков в Seaborn
Одна функция catplot заменяет полдесятка категориальных графиков: переключатель kind, раскладка по сетке col и row — и сравнение групп превращается в три панели рядом.
Seaborn · Урок 17
Подписи, заголовки и аннотации: график Seaborn для отчёта
Seaborn строит график за строку, а отчёт требует заголовка, подписей осей, аннотации пика и файла в PNG. Собираем всё это через Matplotlib API — поверх любого sns-графика.
Похожие уроки по темам
Подобраны автоматически по пересечению тем и ключевых слов.
Matplotlib / Seaborn · Урок 4
Диаграммы рассеяния scatter: ищем связи между величинами
scatter для поиска связей между величинами: форма облака точек, цвет и размер как третье измерение, alpha против оверплоттинга и кейс с 300 измерениями.
диаграмма рассеяния pythonдиаграмма рассеяния matplotlib
Matplotlib / Seaborn · Урок 2
Линейные графики в Matplotlib: plot, цвета, стили и подписи
plt.plot() под микроскопом: цвета, маркеры, стили линий, легенды, диапазоны осей и кейс с двумя температурными кривыми за месяц.
линейный график pythonкак построить линейный график в python
Seaborn · Урок 5
scatterplot в Seaborn: связь двух величин на точках
Диаграмма рассеяния показывает связь двух числовых столбцов: одна строка таблицы — одна точка. Управляем размером s и прозрачностью alpha и учимся видеть кластеры.
seaborn scatterplotточечный график python