1. Введение
Знакомство с визуализацией данных на Python почти всегда начинается с Matplotlib. И чаще всего это знакомство приносит боль.
Открываешь официальную документацию — перед тобой неповоротливый монстр. Идешь за быстрым решением на StackOverflow — и запутываешься окончательно. В одном ответе пишут plt.plot(), в другом используют какой-то ax.plot(). Почему синтаксиса два? Какой из них правильный? В итоге нужный график собирается методом Франкенштейна из кусков чужого кода, а малейшая попытка поменять цвет или добавить вторую ось всё ломает.
Цель этой статьи — раз и навсегда избавить вас от этой путаницы. Мы разберем философию библиотеки и саму «анатомию» графика. Я покажу, как работает Matplotlib под капотом, чтобы вы могли осознанно строить основные визуализации с нуля и больше не зависели от слепой копипасты.
Небольшой совет на полях: визуализацию редко делают ради самой визуализации — обычно это финал работы с таблицами. Если вы чувствуете, что пока плаваете в датафреймах, фильтрациях и группировках, очень рекомендую параллельно со статьей пробежаться по бесплатному курсу «Pandas для анализа данных: Полный курс». Правило тут простое: чем лучше вы подготовите данные до отрисовки, тем меньше костылей придется городить в самом Matplotlib.
2. Подготовка к работе
Установка библиотеки банальна до невозможности. Открываем терминал и пишем стандартную мантру:
pip install matplotlib
Теперь импорт. Если вы откроете любой чужой скрипт с визуализацией, то в 99.9% случаев увидите там такую строчку:
import matplotlib.pyplot as plt
Почему именно plt? Это не строгое требование самого языка, а негласное правило комьюнити аналитиков и разработчиков. Точно так же, как pandas всегда импортируют как pd, а numpy как np. Общепринятый алиас экономит кучу времени при наборе кода и позволяет другим людям мгновенно считывать ваши намерения. А pyplot — это тот самый подмодуль внутри огромного Matplotlib, в котором как раз и лежат все нужные нам инструменты для рисования.
Где писать код? Если вы попытаетесь строить графики в обычном .py файле через PyCharm или VS Code, то каждый новый график будет открываться в отдельном системном окне. Пока вы это окно не закроете, выполнение скрипта будет стоять на паузе. Это дико неудобно, когда нужно быстро поэкспериментировать с цветами или формой.
Именно поэтому для визуализации (и вообще для работы с данными) человечество придумало Jupyter Notebook и его облачного брата Google Colab. Их главная филлер-фича — интерактивность. Вы пишете код в ячейке, нажимаете Shift+Enter, и график появляется прямо под ней, сохраняясь в самом документе.
Часто в начале старых ноутбуков можно встретить такую строчку:
%matplotlib inlineimport matplotlib.pyplot as plt
Это так называемая «магическая команда» Jupyter. Она буквально приказывает среде: «Встраивай все нарисованные графики прямо сюда, в веб-страницу, а не пытайся открыть их в новом окне». Справедливости ради, современные версии Jupyter и встроенные среды в IDE поумнели и отлично рисуют графики и без этой команды, применяя её под капотом. Но знать о ней полезно, чтобы не пугаться, встретив в чужом коде.
Инструменты готовы. Теперь давайте разбираться, как эта штука вообще работает.
3. Самое важное: Анатомия графика (Figure и Axes)
Большинство новичков ломают зубы о Matplotlib именно здесь. Вся путаница со StackOverflow растет из непонимания того, из чего состоит график и какими способами к нему можно обращаться.
Давайте разберем простую аналогию с рисованием:
-
Figure (Фигура): Это ваш мольберт, чистый холст или окно программы. Сам по себе холст не содержит графиков, это просто пространство. На одном холсте (
Figure) может располагаться как один рисунок, так и целая сетка из множества рисунков. -
Axes (График): Это непосредственно сам рисунок на холсте. Именно здесь живут ваши данные, оси координат (X и Y), легенда и подписи.
-
Важное уточнение: слово «Axes» дословно переводится как «оси», но в терминологии Matplotlib это область графика целиком. Не путайте это с
Axis(непосредственно математической осью).
-
Из-за того, что библиотека развивалась годами, в ней исторически сложилось два разных подхода к созданию этих самых холстов и графиков. И именно их вы постоянно видите вперемешку в интернете.
Подход 1: Процедурный (через plt)
Этот подход достался Matplotlib в наследство от языка MATLAB. Вы просто говорите библиотеке «рисуй», а она сама невидимо создает Figure, создает Axes и помещает туда данные.
# Быстро, просто, но не гибкоplt.plot([1, 2, 3], [4, 5, 2])plt.title("Мой первый график")

В чем минус? Это так называемый state-based (основанный на состояниях) подход. Все ваши команды (добавить заголовок, поменять цвет) применяются к «текущему активному» графику. Если у вас на холсте три графика, управлять тем, куда именно добавится заголовок через plt, становится очень больно. Это как рисовать картину с завязанными глазами, надеясь, что кисть попадет куда надо.
Подход 2: Объектно-ориентированный (через fig, ax)
Это современный, явный и самый правильный способ взаимодействия с Matplotlib. Мы сразу своими руками создаем объекты мольберта (fig) и рисунка (ax), а потом обращаемся напрямую к ним.
# Создаем холст (fig) и один график на нем (ax)fig, ax = plt.subplots()# Обращаемся напрямую к конкретному графикуax.plot([1, 2, 3], [4, 5, 2])ax.set_title("Мой первый график")
В чем плюс? У вас появляется абсолютный контроль. Если графиков будет десять, у вас будет десять независимых переменных ax, и вы никогда не запутаетесь, к какому из них применяется настройка.
Золотое правило Matplotlib: Забудьте про
plt.plot(). Возьмите за привычку всегда начинать построение сfig, ax = plt.subplots()и работать через объектax. Это спасет вам тысячи нервных клеток.
Дальше в статье (и вообще в жизни) мы будем использовать только этот, второй подход. Поехали строить графики!
4. Поехали: Строим базовые графики
С теорией покончено, переходим к практике. Чтобы нам было с чем работать, сгенерируем немного фейковых данных. Для этого будем использовать списки и библиотеку numpy — стандартный инструмент для работы с числами в Python.
Не забудьте выполнить import numpy as np перед запуском кода.
1. Линейный график (ax.plot)
Зачем нужен: Идеален для показа динамики во времени. Как менялась температура за неделю, курс валют за год или ваш пульс во время дедлайна.
import numpy as npimport matplotlib.pyplot as plt# Данные: дни недели и температураdays = np.arange(1, 8) # Массив от 1 до 7temperature = [20, 22, 21, 25, 28, 26, 24]fig, ax = plt.subplots() # Создаем холст и графикax.plot(days, temperature) # Рисуем линиюplt.show() # Отрисовываем результат

Обратите внимание: plot по умолчанию просто соединяет точки прямыми линиями в том порядке, в котором они идут в массивах.
2. Диаграмма рассеяния (ax.scatter)
Зачем нужна: Для поиска зависимостей (корреляций) между двумя разными параметрами. Например, зависит ли вес человека от его роста? Каждая точка на графике — это один объект.
# Генерируем 50 случайных значений: рост (в районе 170) и вес (в районе 70)height = np.random.normal(170, 10, 50) weight = height * 0.4 + np.random.normal(0, 5, 50) # Вес немного зависит от ростаfig, ax = plt.subplots()ax.scatter(height, weight) # Строим точкиplt.show()

Если точки выстраиваются в четкую линию — связь есть. Если разбросаны как попало — параметры друг от друга не зависят.
3. Столбчатая диаграмма (ax.bar)
Зачем нужна: Для сравнения разных категорий. Кто продал больше айфонов, какой язык программирования популярнее и так далее. По оси X идут имена категорий, по оси Y — их значения.
categories = ['Янв', 'Фев', 'Мар', 'Апр']sales = [120, 90, 150, 200]fig, ax = plt.subplots()ax.bar(categories, sales) # Строим столбцыplt.show()

4. Гистограмма (ax.hist)
Зачем нужна: Чтобы посмотреть, как распределены данные внутри одного параметра. Важно: Новички часто путают bar и hist. Столбчатая диаграмма (bar) сравнивает разные категории. Гистограмма (hist) берет один набор чисел (например, возраст тысячи пользователей), разбивает его на корзины (от 10 до 20 лет, от 20 до 30 и т.д.) и показывает, сколько человек попало в каждую корзину.
# Генерируем возраст 1000 пользователей (в среднем 30 лет)ages = np.random.normal(30, 8, 1000)fig, ax = plt.subplots()# bins=20 означает, что мы разобьем все возраста на 20 "корзин"ax.hist(ages, bins=20) plt.show()

Отлично! Мы научились строить «скелеты» графиков. Но пока они выглядят так, будто их нарисовал робот из 90-х. В следующем разделе будем наводить красоту.
5. Наводим красоту: Кастомизация
Базовые графики — это отлично для быстрого анализа «на коленке». Но если вы принесете дефолтный синий график без подписей на презентацию, коллеги вас не поймут. Что это за цифры? К чему они относятся?
Давайте возьмем наш линейный график и превратим его во что-то осмысленное. Заодно построим сразу две линии, чтобы было что сравнивать.
В объектно-ориентированном подходе (через ax) большинство команд для добавления текста начинаются с приставки set_. Это важное отличие от устаревшего процедурного подхода, где писали просто plt.title().
# Данные для двух линийdays = np.arange(1, 8)expected = [20, 25, 30, 40, 50, 70, 90]actual = [20, 22, 28, 35, 45, 55, 100]# figsize задает размер холста в дюймах (ширина, высота)fig, ax = plt.subplots(figsize=(8, 5)) # 1. Настраиваем внешний вид линий и добавляем label для легендыax.plot(days, expected, color='gray', linestyle='--', linewidth=2, label='Ожидания')ax.plot(days, actual, color='crimson', marker='o', markersize=6, linewidth=2.5, label='Реальность')# 2. Добавляем заголовки и подписи осейax.set_title('Прогресс понимания Matplotlib по дням', fontsize=14, fontweight='bold')ax.set_xlabel('День недели', fontsize=12)ax.set_ylabel('Уровень просветления (%)', fontsize=12)# 3. Включаем сетку для удобства чтения# alpha делает сетку полупрозрачной, чтобы она не перетягивала вниманиеax.grid(True, linestyle=':', alpha=0.6)# 4. Выводим легенду (она автоматически подхватит аргументы label из ax.plot)ax.legend()plt.show()

Давайте разберем основные параметры, которые мы использовали внутри ax.plot():
-
color— цвет. Можно писать базовые названия ('red','green'), расширенные ('crimson','teal') или вообще HEX-коды ('#FF5733'). -
linewidth— толщина линии. -
linestyle— стиль линии. Например,'--'для пунктира или':'для точек. -
marker— маркеры на пересечении данных.'o'нарисует кружочки,'*'— звездочки,'s'— квадраты (от слова square).
Лайфхак: если вы вызвали ax.legend(), но легенда не появилась, проверьте, задали ли вы параметр label="..." при отрисовке самих графиков. Нет ярлыков — нет легенды!
6. Несколько графиков на одном холсте (Subplots)
Часто одного графика недостаточно. Представьте, что вам нужно сравнить динамику продаж, конверсию, распределение пользователей и еще что-нибудь, и всё это должно поместиться на одном экране или слайде. Строить четыре отдельных окна — плохая идея. Лучше разбить один большой холст на сетку из нескольких графиков.
Вспомните нашу главную команду: fig, ax = plt.subplots(). По умолчанию она создает сетку размером 1х1. Но если передать в нее количество строк и столбцов, мы получим матрицу графиков.
Давайте построим сетку 2х2 и выведем в ней все четыре типа графиков, которые мы изучили ранее:
# Создаем холст и сетку графиков 2х2# figsize=(10, 8) сделает холст побольше, чтобы графикам не было тесноfig, ax = plt.subplots(nrows=2, ncols=2, figsize=(10, 8))# Генерируем немного простых данных для примеровx = np.arange(1, 6)y1 = [1, 4, 9, 16, 25]y2 = [2, 3, 5, 7, 11]# 1. Верхний левый график (строка 0, столбец 0)ax[0, 0].plot(x, y1, color='blue')ax[0, 0].set_title('Линейный график')# 2. Верхний правый график (строка 0, столбец 1)ax[0, 1].scatter(x, y2, color='red')ax[0, 1].set_title('Диаграмма рассеяния')# 3. Нижний левый график (строка 1, столбец 0)ax[1, 0].bar(x, y1, color='green')ax[1, 0].set_title('Столбчатая диаграмма')# 4. Нижний правый график (строка 1, столбец 1)ax[1, 1].hist(np.random.randn(100), bins=15, color='purple')ax[1, 1].set_title('Гистограмма')plt.tight_layout() plt.show()

Как работать с массивом ax? Когда вы создаете сетку больше чем 1х1, переменная ax перестает быть одним графиком и превращается в массив (список) графиков. Поскольку у нас сетка 2х2, это двумерный массив. Мы обращаемся к каждому конкретному квадратику по его индексам: ax[индекс_строки, индекс_столбца]. Помним, что в Python счет начинается с нуля, поэтому левый верхний угол — это [0, 0], а правый нижний — [1, 1].
Зачем нужен plt.tight_layout()? Это главный лайфхак, о котором новички узнают слишком поздно. Если вы закомментируете эту строчку и запустите код, то с вероятностью 99% увидите неприятную картину: заголовок нижнего графика налезет на ось X верхнего графика. Они буквально «слипнутся».
Команда plt.tight_layout() автоматически пересчитывает отступы между графиками так, чтобы никакие тексты, легенды и оси не перекрывали друг друга. Просто возьмите за правило всегда писать эту команду перед plt.show(), если у вас больше одного графика на холсте.
7. Сохранение результата
Итак, шедевр готов. Вы настроили цвета, подобрали идеальную толщину линий, и график выглядит великолепно. Теперь его нужно вставить в презентацию, отчет или отправить коллеге в мессенджер.
Делать скриншот экрана — это путь в никуда (особенно если вам нужно прозрачное окно или высокое разрешение). У нашего объекта fig (холста) есть специальный метод для сохранения картинки на диск.
# ... здесь был ваш код отрисовки графика ...# Сохраняем холст в файлfig.savefig('my_awesome_plot.png', dpi=300, bbox_inches='tight')plt.show()
Давайте разберем параметры:
-
'my_awesome_plot.png'— имя файла. Matplotlib достаточно умен, чтобы понять по расширению, в каком формате сохранять. Можно написать.jpg,.pdfили даже.svg(для векторной графики). -
dpi=300— количество точек на дюйм (Dots Per Inch). 300 — это золотой стандарт для печати и четких презентаций. Без этого параметра картинка может получиться мыльной. -
bbox_inches='tight'— еще один полезный бонус. Он гарантирует, что все подписи осей и заголовки, которые могли случайно вылезти за край холста, будут аккуратно вписаны в итоговую картинку.
Главная ловушка новичка: Синдром белого квадрата
Рано или поздно вы столкнетесь с ситуацией: вы пишете код, видите в Jupyter Notebook красивый график, открываете сохраненный PNG-файл, а там… просто абсолютно белый пустой квадрат.
Это происходит из-за одной классической ошибки — вызова сохранения после показа:
# КАК ДЕЛАТЬ НЕЛЬЗЯ:ax.plot([1, 2, 3], [4, 5, 2])plt.show() # Отрисовали и "сбросили" холстfig.savefig('plot.png') # Сохраняем пустоту! ❌
Почему так происходит? Когда вы вызываете plt.show(), Matplotlib рендерит ваш холст на экран, а затем неявно очищает текущую фигуру (чтобы освободить память для следующих графиков). К моменту, когда интерпретатор доходит до savefig, рисовать уже нечего — холст чист.
Запомните правило: Сначала сохраняем (fig.savefig), и только в самом конце показываем (plt.show()).
8. Заключение
Вот и всё! Мы проделали путь от пугающей документации до уверенной работы с базой Matplotlib. Давайте кратко подытожим, что мы сегодня узнали:
-
Поняли анатомию: разделили понятие холста (
Figure) и самого рисунка (Axes). -
Выяснили, почему объектно-ориентированный подход (
fig, ax = plt.subplots()) — это лучший друг разработчика и аналитика. -
Научились строить четыре базовых типа графиков: линии, точки, столбцы и гистограммы.
-
Посмотрели, как наводить красоту, настраивать цвета и аккуратно выводить графики сеткой.
-
Узнали, как правильно сохранять картинки на диск, навсегда забыв про ошибку «белого квадрата».
Куда двигаться дальше?
Matplotlib — это надежный, проверенный временем фундамент. Но в мире Python есть и другие инструменты, которые могут сильно упростить вам жизнь. Когда вы освоите базу, настоятельно рекомендую посмотреть в сторону этих двух библиотек:
-
Seaborn. Это библиотека, которая написана поверх Matplotlib. Ее главная фишка — она делает всё красиво прямо «из коробки» и идеально подходит для сложного статистического анализа. Там, где в Matplotlib нужно написать цикл и десять строк кода, в Seaborn часто хватает одной изящной команды.
-
Plotly. Если в какой-то момент вам станет мало статичных картинок и захочется интерактива (чтобы пользователь мог навести мышку на точку и увидеть цифры, приблизить нужный участок графика или скрыть лишние линии кликом по легенде) — смело берите Plotly. Это стандарт для современных дашбордов.
Анонсы новых статей, полезные материалы, а так же если в процессе у вас возникнут сложности, обсудить их или задать вопрос по этой статье можно в моём Telegram-сообществе. Смело заходите, если что-то пойдет не так, — постараемся разобраться вместе.
ссылка на оригинал статьи https://habr.com/ru/articles/1028868/