Используйте Matplotlib как абсолютный босс!

У меня было правило ...

Когда я был новичком в обучении визуализации данных, у меня было правило - никогда и никогда не заходить в документацию Matplotlib.

Ничего хорошего оттуда не вышло. Когда я был на его страницах, мои глаза обрабатывали английские слова, но каким-то образом они интерпретировались в моем мозгу, как я расшифровываю иностранный язык. Тогда я наткнулся бы на какие-то шедевры, подобные этим, и подумал бы, могу ли я вообще использовать одну и ту же библиотеку?

Даже если вы опытный программист, я уверен, что вы сталкивались с аналогичными проблемами при изучении Maplotlib. Это непростая библиотека. Так много классов и чертовски много способов решать простейшие задачи - полная путаница.

Если вы находитесь в таком положении или хотите улучшить свою игру в Matplotlib, у меня есть необходимое руководство. Я покажу вам, как добраться глубоко до корней джунглей Матплотлиб, поджечь их и улететь на реактивном ранце. Вы готовы? Давайте начнем!

Художники создали Матплотлиб

Хотя выдающиеся программисты написали Matplotlib, он состоит из базовых классов, называемых Artists.

Каждый аннотированный кружком компонент графика реализован как отдельный класс, который наследует от базового художника. Но у этой способности представлять все как класс есть свои плюсы и минусы.

С одной стороны, это дает Matplotlib беспрецедентную гибкость. Используя соответствующий класс, вы можете настроить практически любой компонент сюжета, пока не будете удовлетворены. Часто у вас есть несколько вариантов для выполнения одной и той же задачи, что позволяет переключаться между разными интерфейсами.

Возможно, именно это больше всего расстраивает питонистов в MPL. Согласно дзену Python, должен быть один, а желательно только один очевидный способ что-то сделать. И API Matplotlib является нарушением этого правила всеми возможными способами.

В результате новички сбиты с толку. Они не знают, какой класс или функцию использовать для выполнения простой задачи. Они не понимают документацию, потому что, честно говоря, ее чертовски сложно понять. Даже опытные разработчики могут не понимать, что означают такие ошибки:

Естественно, вы расстроены, потому что не знаете, где, черт возьми, вы использовали объект Lined2D и откуда он взялся.

Если вы один из этих людей, я покажу вам несколько уловок, которые я усвоил, которые сделают вас профессиональным пользователем Matplotlib и прочтете документацию, как если бы вы читали детские сказки на ночь.

Создание собственного единого рабочего процесса

Начнем с выбора единого подхода к решению задач. Есть много способов сделать один-единственный, поэтому важно придерживаться только одного стиля и овладеть им.

Рабочий процесс, который я использую для создания графика и его настройки, выглядит следующим образом:

  1. Создавайте сам сюжет с базовыми элементами и небольшими настройками.
  2. Выясните слабые стороны сюжета и отметьте компоненты, которые вы хотите улучшить.
  3. Изолируйте эти слабые компоненты с помощью соответствующих функций Matplotlib.
  4. Настраивайте их, пока не будете удовлетворены, используя швейцарский армейский нож Matplotlib (подробнее об этом позже).
  5. Сохраните или отобразите график.

Мы подробно научимся делать каждый шаг. Я гарантирую вам, что этот фреймворк работает практически для любого типа сюжета, который вы создаете, и настройки, которые вы хотите сделать.

Образно говоря…

Начнем с того, что научимся создавать графики с помощью фигур. Объект Figure в MPL - это художник самого высокого уровня, который можно рассматривать как холст, на котором вы все рисуете.

Вы можете создать фигуру, на которой ничего не нарисовано, с помощью функции figure. Сама по себе фигура ничего не делает - помните, что это чистая белая страница, на которой вы рисуете свои сюжеты.

К цифрам мы вернемся позже.

Кидаем топоры!

Самое интересное начинается, когда мы добавляем оси к фигуре. Класс Axes - это художник, который представляет набор систем координат x, y в сюжете:

Функция добавления пустых осей к фигуре - add_axes, но на практике вы никогда ее не используете. Вместо этого вы обычно создаете одну фигуру и одну или несколько осей одновременно с помощью функции subplots:

>>> fig, ax = plt.subplots()

Это сразу создает фигуру и прикрепляет оси (систему координат). Далее мы начинаем наносить данные на оси, используя методы построения графиков.

Эти графики имеют такие имена, как bar, hist, scatter, boxplot и т. Д. Давайте создадим простую диаграмму рассеяния и нарисуем пару линий:

Мы уже видим, что для сюжета нужно несколько текстовых надписей. Кроме того, нам не нравятся стандартные цвета точек и линий. К тому же сама фигура немного мала.

Видите, что мы здесь сделали? Сначала мы создали базовый график и определили компоненты, которые хотим улучшить. Теперь нам нужно выяснить, как извлечь эти компоненты и настроить их.

Разбивка компонентов сюжета, их компонентов и их компонентов

Поскольку мы создали оси и фигуры в начале, они уже изолированы как объекты (fig и ax).

Теперь предположим на мгновение, что у нас есть фигура, но нет осей. Как нам извлечь это из рисунка?

У каждого художника matplotlib есть несколько методов, которые начинаются с префикса get_*. Если мы вызовем функцию dir на fig, мы увидим несколько примеров:

В списке мы видим небольшую функцию с именем get_axes, поэтому воспользуемся ею.

Официальное имя класса осей AxesSubplot и, как мы видим, в списке только один:

ax = axes_list[0]

Я знаю, что это фундаментальные концепции, но урок, который вы должны извлечь из этого, заключается в том, что каждый класс в MPL имеет такие get_* функции, которые позволяют вам извлекать различные части этого класса компонентов.

Швейцарские армейские ножи Матплотлиба

Теперь, когда у нас есть пара объектов, пора настроить их, используя их параметры. Но сначала мы должны спросить - какие параметры принимает мой объект и какие значения они принимают?

Вот где в игру вступает швейцарский армейский нож Матплотлиб. Это функция plt.setp (установить параметр), и она доступна через PyPlot API.

Итак, давайте посмотрим, какие параметры принимает объект figure:

Вызов функции для объекта без параметров распечатывает документацию всех аргументов объекта. В списке параметров мы видим тот, который хотим изменить, это размер фигуры. Это тот, который называется size_inches:

Передача объекта и его имени параметра в виде строки является сокращением для вывода возможных значений параметров. Теперь, наконец, изменим размер фигуры:

Функция возвращает None, что означает, что операция прошла успешно. А теперь еще раз посмотрим на сюжет:

>>> fig.get_figure()

Пришло время топоров:

Мы хотим изменить метки осей, ограничения, заголовок и цвет корешка оси. Если нам неизвестны текущие значения этих параметров, мы вызываем plt.getp - друга setp:

>>> plt.getp(ax, "xlim")
(0.35, 3.65)

Подобно setp, getp возвращает значения по умолчанию или текущие значения параметров. Вызов его без каких-либо аргументов для объекта возвращает все значения по умолчанию. Давайте изменим те, которые хотели:

А как насчет цветов линий и маркеров? Мы также сказали, что будем настраивать осевые линии? Ну, это отдельные классы, поэтому нам нужно извлечь их из осей. Но прежде чем мы это сделаем, нам нужно изучить несколько важных концепций. Этот раздел служил только введением в функции setp и getp.

Контейнеры и примитивы

Чтобы перейти от базовых художников к красочным сюжетам, компоненты должны пройти длинную цепочку наследования многих классов MPL. Вдоль этой цепочки две группы классов важны для того, как вы используете Matplotlib. Эти группы называются контейнерами и примитивами.

Мы уже видели два экземпляра контейнеров - фигур и топоров. Фигура содержит оси, а оси содержат почти все.

Примитивы - это все графические или геометрические объекты, которые входят в контейнер. Вы редко используете эти примитивы напрямую. Они создаются динамически, когда вы вызываете функции построения графиков. Вы можете получить доступ ко всем их именам в модуле patches Matplotlib:

Как видите, у нас есть все необходимое для создания гистограмм, диаграмм рассеяния, коробчатых диаграмм и линейных диаграмм. Все они могут быть созданы с помощью патчей, таких как круги, прямоугольники, многоугольники и линии.

На приведенной выше карте классов Matplotlib мы видим маленький Lind2D, о котором я упоминал ранее. Это класс, который рисует линии и маркеры, когда мы строим диаграммы рассеяния и линии с использованием функций plot или scatter.

Теперь, возвращаясь к нашему сюжету - вот шаги, которые мы сделали на данный момент:

Давайте посмотрим на всех художников в theax:

Мы видим наши линии. Мы также видим четыре шипа, которые являются отдельными классами. Объекты осей X и Y видны вместе с первым элементом, которого мы раньше не видели.

PathCollection представляет собой группы точек. Итак, давайте извлечем его и дадим точкам несколько настроек:

Мы немного увеличили размер и дали точкам красный цвет с черными краями,

Точно так же мы можем настроить шипы:

Последний трюк, который я рекомендую, - это сохранение всех созданных графиков в переменной, чтобы вы могли работать с ними отдельно, не обращаясь к ним через оси:

Собираем все вместе

Давайте структурируем всю беспорядочную информацию, которую мы узнали сегодня:

  1. Создайте сюжет и отметьте части, которые хотите улучшить.
  2. Извлеките единственный компонент. Позвоните dir по осям или фигурному объекту, если вы не знаете, что ищете. Кроме того, в этом случае полезны функции с префиксом get_*.
  3. После того, как у вас есть компонент, посмотрите значения его параметров по умолчанию, вызвав plt.getp.
  4. Отметьте необходимые параметры и вызовите plt.setp для каждого из них, чтобы увидеть возможные значения, которые они принимают.
  5. Задайте свои собственные значения, используя ту же функцию.
  6. Повторяйте шаги 2–5, пока не получите идеальный сюжет, который вам нужен.

Пройдя через этот рабочий процесс несколько раз, вы почувствуете себя более комфортно с функциями более высокого уровня. Вместо извлечения каждого компонента из осей и примитивов вы начнете передавать аргументы непосредственно в вызовы функций или при создании осей.

Но функции setp, getp и dir - это все, что вам нужно, если вы когда-нибудь столкнетесь с неизвестным классом или функцией Matplotlib.

Кроме того, изучение концепций художников, патчей и контейнеров / примитивов позволило вам понять документацию во всей ее полноте. Это термины, которые чаще всего встречаются в документации. Я настоятельно рекомендую пройти их с вашими новыми знаниями, чтобы узнать еще больше.

Резюме

Визуализация данных - это не изучение библиотеки для построения графиков. Это сочетание творчества, понимания аудитории и профессионального и информативного предоставления идей.

Я жду всех этих трех навыков с твоей стороны. Моя часть заключалась в том, чтобы показать, как вы можете использовать одну из сильнейших библиотек построения графиков в экосистеме Python, чтобы дополнить эти навыки. Я научил вас мощному итеративному процессу, который позволяет вам разумно и структурированно улучшать графики Matplotlib.

Возможно, вас заинтересуют эти хиты…