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

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

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

regplot: тренд и регрессия на графике рассеяния

Точки, линия регрессии и доверительная полоса одним вызовом regplot: как увидеть тренд двух величин, когда прямая врёт и что говорит наклон.

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

На диаграмме рассеяния из урока 5 облако точек отвечает на вопрос «есть ли связь» — но полуточно: глаз ловит направление облака, а где именно проходит тренд и насколько он надёжен, приходится угадывать. sns.regplot доводит ответ до конца: рисует те же точки и добавляет линию регрессии — прямую, проведённую через облако методом наименьших квадратов, — и обводит её доверительной полосой, которая показывает, насколько линии можно верить.

Разберём на данных, к которым вернёмся весь урок: интернет-магазин 12 недель меняет рекламный бюджет и записывает выручку. Обе величины — в тысячах рублей.

Точки, линия и доверительная полоса

regplot: реклама против выручки
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 позволяют заодно довести стиль — цвет и толщину линии, форму маркеров:

ci=None и стиль линии
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 подогнать полином второй степени — параболу:

order=2: прямая против параболы
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 логарифмируется, и кривая насыщения выпрямляется в линию.

logx=True: кривая насыщения
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))
Проверь себя
0 / 5

1. Что рисует один вызов sns.regplot?

2. Что делает параметр ci=None?

3. Когда regplot нужен параметр order=2?

4. Зависимость растёт всё медленнее и выходит на плато. Какую настройку выбрать?

5. Наклон линии регрессии равен 5.7. Как это прочитать?

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

Постройте regplot зависимости цены квартиры от площади: уберите доверительную полосу, увеличьте точки через scatter_kws={"s": 40} и покрасьте линию в цвет "crimson" через line_kws. Данные в заготовке.

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

Чем 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-канал или свой блог — так о проекте узнают новые читатели.

TelegramVK

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

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