Использование библиотеки Matplotlib. Как управлять положением рисок на осях | jenyay.net

Использование библиотеки Matplotlib. Как управлять положением рисок на осях

Дата публикации: 19.12.2012
Дата последней правки: 14.01.2023

Оглавление

Введение

Под рисками (ticks) в данной статье подразумеваются отметки, нанесенные на оси, около которых отображаются числовые значения, и через которые проводится сетка, отображаемая с помощью функции grid(). Как правило, по умолчанию библиотека Matplotlib довольно разумно расставляет риски, однако, если их расположение по умолчанию вас не устраивает, то их положение можно изменить.

Для начала нарисуем график с рисками по умолчанию.

# coding: utf-8

import matplotlib.pyplot as plt
import numpy as np


if __name__ == '__main__':
    xmin = -10.0
    xmax = 10.0
    xcount = 201

    xvals = np.linspace(xmin, xmax, xcount)
    yvals = np.sinc(xvals)

    figure = plt.figure()
    axes = figure.add_subplot(1, 1, 1)

    plt.plot(xvals, yvals)
    axes.set_xlim(xmin, xmax)

    axes.grid()
    plt.show()

Результат выглядит следующим образом:

Обратите внимание, как библиотека Matplotlib разместила риски и подписи к ним на горизонтальной оси. Именно с ними мы и будем дальше работать.

Для того, чтобы изменять шаг расположения рисок, предназначены метод set_major_locator() класса matplotlib.axis.Axis для основных рисок и метод set_minor_locator() для промежуточных. В качестве единственного параметра, эти методы принимают экземпляр класса, производного от базового класса matplotlib.ticker.Locator (дальше для краткости будем называть эти классы "локатор"). Модуль matplotlib.ticker содержит несколько таких локаторов, использующие различные алгоритмы расположения рисок. Полный список классов, предназначенных для выбора алгоритма расстановки рисок, можно найти на этой странице документации. В следующих разделах мы рассмотрим подробнее некоторые из них. Во всех примерах мы будем изменять только основные риски по оси X.

Надо отметить, что нельзя применять один и тот же экземпляр локатора и к оси X, и к оси Y одновременно, надо обязательно делать для каждой оси свой экземпляр класса Locator. Это связано с внутренней работой библиотеки Matplotlib.

А теперь давайте посмотрим, некоторые из локаторов, которые нам предлагает библиотека Matplotlib.

NullLocator

Самый простой локатор - это NullLocator, который используется для отключения всех рисок. Применим его к оси X.

# coding: utf-8

import matplotlib.ticker
import matplotlib.pyplot as plt
import numpy as np


if __name__ == '__main__':
    xmin = -10.0
    xmax = 10.0
    xcount = 201

    xvals = np.linspace(xmin, xmax, xcount)
    yvals = np.sinc(xvals)

    figure = plt.figure()
    axes = figure.add_subplot(1, 1, 1)

    plt.plot(xvals, yvals)
    axes.set_xlim(xmin, xmax)

    # !!! Создаем экземпляр класса, который будет отвечать за расположение рисок
    locator = matplotlib.ticker.NullLocator()

    # !!! Установим локатор для главных рисок
    axes.xaxis.set_major_locator(locator)

    axes.grid()
    plt.show()

риски по оси X исчезли:

LinearLocator

Локатор LinearLocator используется, если на оси нужно отметить фиксированное количество рисок. Обычно это не самая лучшая идея для оформления графика из-за того, что риски могут попадать на не очень наглядные значения, как, например, в следующем примере, в котором используется 10 рисок по оси X.

# coding: utf-8

import matplotlib.ticker
import matplotlib.pyplot as plt
import numpy as np


if __name__ == '__main__':
    xmin = -10.0
    xmax = 10.0
    xcount = 201

    xvals = np.linspace(xmin, xmax, xcount)
    yvals = np.sinc(xvals)

    figure = plt.figure()
    axes = figure.add_subplot(1, 1, 1)

    plt.plot(xvals, yvals)
    axes.set_xlim(xmin, xmax)

    # Создаем экземпляр класса, который будет отвечать за расположение рисок
    # Этот локатор отобразит ровно 10 рисок
    locator = matplotlib.ticker.LinearLocator(10)

    # Установим локатор для главных рисок
    axes.xaxis.set_major_locator(locator)

    axes.grid()
    plt.show()

MultipleLocator

Класс MultipleLocator используется, если надо расставить риски через определенные равные интервалы. Размер интервала задается через единственный параметр конструктора base.

Выражаясь математическим языком, риски будут расположены около значений base * i, где i = 0, ±1, ±2, ... Обратите внимание, что отсчет начинается не от минимального значения данных (как у IndexLocator, о котором речь пойдет дальше), а от нуля.

Следующий пример демонстрирует работу MultipleLocator, расставляя риски с шагом 1.5.

# coding: utf-8

import matplotlib.ticker
import matplotlib.pyplot as plt
import numpy as np


if __name__ == '__main__':
    xmin = -10.0
    xmax = 10.0
    xcount = 201

    xvals = np.linspace(xmin, xmax, xcount)
    yvals = np.sinc(xvals)

    figure = plt.figure()
    axes = figure.add_subplot(1, 1, 1)

    plt.plot(xvals, yvals)
    axes.set_xlim(xmin, xmax)

    # Создаем экземпляр класса, который будет отвечать за расположение рисок
    # Риски будут следовать с шагом 1.5
    locator = matplotlib.ticker.MultipleLocator(1.5)

    # Установим локатор для главных рисок
    axes.xaxis.set_major_locator(locator)

    axes.grid()
    plt.show()

IndexLocator

Класс IndexLocator напоминает MultipleLocator в том смысле, что этот локатор также позволяет расставлять риски с равным шагом. Но, в отличие от него, IndexLocator отсчитывает риски не от нулевого значения, а начиная от наименьшего значения на графике.

Конструктор IndexLocator принимает два обязательных параметра:

  • base задает интервал между метками.
  • offset задает смещение относительно наименьшего значения на оси.

Проще всего это продемонстрировать на примерах. Первый пример расставляет риски с интервалом 1.5 и значением параметра offset = 0.

# coding: utf-8

import matplotlib.ticker
import matplotlib.pyplot as plt
import numpy as np


if __name__ == '__main__':
    xmin = -10.0
    xmax = 10.0
    xcount = 201

    xvals = np.linspace(xmin, xmax, xcount)
    yvals = np.sinc(xvals)

    figure = plt.figure()
    axes = figure.add_subplot(1, 1, 1)

    plt.plot(xvals, yvals)
    axes.set_xlim(xmin, xmax)

    # Создаем экземпляр класса, который будет отвечать за расположение рисок
    # риски будут следовать с шагом 1.5
    locator = matplotlib.ticker.IndexLocator(1.5, 0)

    # Установим локатор для главных рисок
    axes.xaxis.set_major_locator(locator)

    axes.grid()
    plt.show()

Чтобы показать, что риски действительно отсчитываются от самого левого значения в данных, а не от минимального значения, установленного по оси, изменим предыдущий пример таким образом, чтобы по оси X отображался интервал [-15; 10], не изменяя диапазон, в котором рассчитана функция.

# coding: utf-8

import matplotlib.ticker
import matplotlib.pyplot as plt
import numpy as np


if __name__ == '__main__':
    xmin = -10.0
    xmax = 10.0
    xcount = 201

    xvals = np.linspace(xmin, xmax, xcount)
    yvals = np.sinc(xvals)

    figure = plt.figure()
    axes = figure.add_subplot(1, 1, 1)

    plt.plot(xvals, yvals)
    axes.set_xlim(xmin - 5, xmax)

    # Создаем экземпляр класса, который будет отвечать за расположение рисок
    # риски будут следовать с шагом 1.5
    locator = matplotlib.ticker.IndexLocator(1.5, 0)

    # Установим локатор для главных рисок
    axes.xaxis.set_major_locator(locator)

    axes.grid()
    plt.show()

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

Теперь изменим второй параметр конструктора IndexLocator. Пусть параметр offset будет равен 2.0.

# coding: utf-8

import matplotlib.ticker
import matplotlib.pyplot as plt
import numpy as np


if __name__ == '__main__':
    xmin = -10.0
    xmax = 10.0
    xcount = 201

    xvals = np.linspace(xmin, xmax, xcount)
    yvals = np.sinc(xvals)

    figure = plt.figure()
    axes = figure.add_subplot(1, 1, 1)

    plt.plot(xvals, yvals)
    axes.set_xlim(xmin - 5, xmax)

    # Создаем экземпляр класса, который будет отвечать за расположение рисок
    # риски будут следовать с шагом 1.5
    locator = matplotlib.ticker.IndexLocator(1.5, 2.0)

    # Установим локатор для главных рисок
    axes.xaxis.set_major_locator(locator)

    axes.grid()
    plt.show()

Первая риска сместилась сместилась вправо на 2.0.

FixedLocator

С помощью локатора FixedLocator можно установить риски только в тех значениях, которые вы явно укажете.

# coding: utf-8

import matplotlib.ticker
import matplotlib.pyplot as plt
import numpy as np


if __name__ == '__main__':
    xmin = -10.0
    xmax = 10.0
    xcount = 201

    xvals = np.linspace(xmin, xmax, xcount)
    yvals = np.sinc(xvals)

    figure = plt.figure()
    axes = figure.add_subplot(1, 1, 1)

    plt.plot(xvals, yvals)
    axes.set_xlim(xmin, xmax)

    # Создаем экземпляр класса, который будет отвечать за расположение рисок
    # риски будут находиться только в тех значениях, которые перечислены в списке
    locator = matplotlib.ticker.FixedLocator ([-5, -4, -3, 0, 3, 4, 5])

    # Установим локатор для главных рисок
    axes.xaxis.set_major_locator(locator)

    axes.grid()
    plt.show()

В данном примере риски будут установлены только при значениях X = -5, -4, -3, 0, 3, 4, 5.

LogLocator

Если нужно расположить риски по логарифмическому закону (например, при значениях X = 1, 10, 100, 1000, ...), то для решения этой задачи пригодится локатор LogLocator. Конструктор класса LogLocator может принимать несколько параметров. Самый важный из них - это первый параметр base, который задает величину, которая будет последовательно возводиться в степень 0, 1, 2, ..., и в этих местах будет ставиться риска. Если не использовать второй параметр, о котором будет написано ниже, то риски будут выставляться в значениях, рассчитанных по формуле basei, где i = 0, 1, 2, ... По умолчанию параметр base принимает значение 10.

Следующий пример показывает использование локатора с base = 2.

# coding: utf-8

import matplotlib.ticker
import matplotlib.pyplot as plt
import numpy as np


if __name__ == '__main__':
    xmin = 0.0
    xmax = 65
    xcount = 201

    xvals = np.linspace(xmin, xmax, xcount)
    yvals = np.sinc(xvals)

    figure = plt.figure()
    axes = figure.add_subplot(1, 1, 1)

    plt.plot(xvals, yvals)
    axes.set_xlim(xmin, xmax)

    # Создаем экземпляр класса, который будет отвечать за расположение рисок
    locator = matplotlib.ticker.LogLocator(base=2)

    # Установим локатор для главных рисок
    axes.xaxis.set_major_locator(locator)

    axes.grid()
    plt.show()

Конструктору LogLocator можно передать дополнительный параметр subs, который представляет собой список множителей, на которые умножается, результат возведения в степень. То есть положения рисок определяется по формуле basei * subs[j], где i = 0, 1, 2, ..., а j = 0, 1,... len (subs) - 1. По умолчанию параметр subs = [1.0].

Следующий пример демонстрирует использование параметра subs.

# coding: utf-8

import matplotlib.ticker
import matplotlib.pyplot as plt
import numpy as np


if __name__ == '__main__':
    xmin = 0.0
    xmax = 65
    xcount = 201

    xvals = np.linspace(xmin, xmax, xcount)
    yvals = np.sinc(xvals)

    figure = plt.figure()
    axes = figure.add_subplot(1, 1, 1)

    plt.plot(xvals, yvals)
    axes.set_xlim(xmin, xmax)

    # Создаем экземпляр класса, который будет отвечать за расположение рисок
    locator = matplotlib.ticker.LogLocator(base=2, subs=[1, 5])

    # Установим локатор для главных рисок
    axes.xaxis.set_major_locator(locator)

    axes.grid()
    plt.show()

MaxNLocator

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

У конструктора этого локатора шесть не обязательных параметров. Здесь мы рассмотрим влияние двух их них: nbins и steps.

Начнем с параметра nbins. Этот параметр может принимать либо целочисленное значение, либо строку 'auto'. С его помощью ось разбивается на некоторое количество интервалов, но не больше указанного в этом параметре значения. Значение по молчанию для этого параметра равно 10. Если значение nbins равно 'auto', локатор MaxNLocator сам подберет количество интервалов оп своему внутреннему алгоритму.

Посмотрим, как будет выглядеть график, если в конструктор MaxNLocator не будут переданы никакие параметры (значение nbins будет равно 10).

# coding: utf-8

import matplotlib.ticker
import matplotlib.pyplot as plt
import numpy as np


if __name__ == '__main__':
    xmin = -20.0
    xmax = 20.0
    xcount = 401

    xvals = np.linspace(xmin, xmax, xcount)
    yvals = np.sinc(xvals)

    figure = plt.figure()
    axes = figure.add_subplot(1, 1, 1)

    plt.plot(xvals, yvals)
    axes.set_xlim(xmin, xmax)

    # Создаем экземпляр класса, который будет отвечать за расположение рисок
    locator = matplotlib.ticker.MaxNLocator()

    # Установим локатор для главных рисок
    axes.xaxis.set_major_locator(locator)

    axes.grid()
    plt.show()

Как видно, мы и поучили 10 интервалов.

Теперь укажем конструктору, что нам нужно не больше 5 интервалов (nbins=5).

# coding: utf-8

import matplotlib.ticker
import matplotlib.pyplot as plt
import numpy as np


if __name__ == '__main__':
    xmin = -20.0
    xmax = 20.0
    xcount = 401

    xvals = np.linspace(xmin, xmax, xcount)
    yvals = np.sinc(xvals)

    figure = plt.figure()
    axes = figure.add_subplot(1, 1, 1)

    plt.plot(xvals, yvals)
    axes.set_xlim(xmin, xmax)

    # Создаем экземпляр класса, который будет отвечать за расположение рисок
    locator = matplotlib.ticker.MaxNLocator(nbins=5)

    # Установим локатор для главных рисок
    axes.xaxis.set_major_locator(locator)

    axes.grid()
    plt.show()

Класс MaxNLocator решил, что 4 полных интервала и немного свободного места по краям будет смотреться лучше.

Как уже говорилось, значение nbins может может быть равным строке 'auto', в этом случае количество интервалов выбирается с помощью внутреннего алгоритма класса MaxNLocator. Посмотрим, как это сработает на нашем примере:

# coding: utf-8

import matplotlib.ticker
import matplotlib.pyplot as plt
import numpy as np


if __name__ == '__main__':
    xmin = -20.0
    xmax = 20.0
    xcount = 401

    xvals = np.linspace(xmin, xmax, xcount)
    yvals = np.sinc(xvals)

    figure = plt.figure()
    axes = figure.add_subplot(1, 1, 1)

    plt.plot(xvals, yvals)
    axes.set_xlim(xmin, xmax)

    # Создаем экземпляр класса, который будет отвечать за расположение рисок
    locator = matplotlib.ticker.MaxNLocator(nbins='auto')

    # Установим локатор для главных рисок
    axes.xaxis.set_major_locator(locator)

    axes.grid()
    plt.show()

Класс MaxNLocator решил, что для наших данных весь интервал лучше разбить на 8 частей.

Рассмотрим теперь параметр steps конструктора класса MaxNLocator. Этот параметр указывает локатору наши пожелания относительно того, какие числа мы бы хотели видеть около рисок. Этот параметр принимает список чисел в интервале от 1 до 10, включая концы, и риски будут созданы только около тех значений, которые кратны числам из этого списка.

Следующий пример указывает классу MaxNLocator, что мы хотели бы, чтобы риски стояли около значений, кратных 5.

# coding: utf-8

import matplotlib.ticker
import matplotlib.pyplot as plt
import numpy as np


if __name__ == '__main__':
    xmin = -20.0
    xmax = 20.0
    xcount = 401

    xvals = np.linspace(xmin, xmax, xcount)
    yvals = np.sinc(xvals)

    figure = plt.figure()
    axes = figure.add_subplot(1, 1, 1)

    plt.plot(xvals, yvals)
    axes.set_xlim(xmin, xmax)

    # Создаем экземпляр класса, который будет отвечать за расположение рисок
    locator = matplotlib.ticker.MaxNLocator(steps=[5])

    # Установим локатор для главных рисок
    axes.xaxis.set_major_locator(locator)

    axes.grid()
    plt.show()

В следующем примере мы укажем, что нас устроят риски около значений, кратных 2 и 6.

# coding: utf-8

import matplotlib.ticker
import matplotlib.pyplot as plt
import numpy as np


if __name__ == '__main__':
    xmin = -20.0
    xmax = 20.0
    xcount = 401

    xvals = np.linspace(xmin, xmax, xcount)
    yvals = np.sinc(xvals)

    figure = plt.figure()
    axes = figure.add_subplot(1, 1, 1)

    plt.plot(xvals, yvals)
    axes.set_xlim(xmin, xmax)

    # Создаем экземпляр класса, который будет отвечать за расположение рисок
    locator = matplotlib.ticker.MaxNLocator(steps=[2, 6])

    # Установим локатор для главных рисок
    axes.xaxis.set_major_locator(locator)

    axes.grid()
    plt.show()

Алгоритм, реализованный в MaxNLocator, решил, что для данного графика лучше оставить только числа, кратные 6 (они тоже кратные 2).

В библиотеке Matplotlib есть еще локатор AutoLocator, он является по сути локатором MaxNLocator со значениями параметров nbins = 'auto' и steps = [1, 2, 2.5, 5, 10].

На этом мы закончим рассматривать локаторы для расстановки рисок на осях графика, однако за рамками статьи остались еще несколько имеющихся классов локаторов, описанных в документации.

Похожие статьи


Вы можете подписаться на новости сайта через RSS, Группу Вконтакте или Канал в Telegram.
4.5 stars

Рейтинг 4.4/5. Всего 8 голос(а, ов)



Константин 05.01.2024 - 16:37

Было бы неплохо упомянуть set_minor_locator(AutoMinorLocator()) — лёгкий способ добавить промежуточные деления, не привязываясь к параметрам конкретного графика

1 07.08.2024 - 12:43

Спасибо. Отмечу, что у MultipleLocator есть параметр offset


Подписаться на комментарии
Автор:
Тема:
 Ваш комментарий
 
 
Введите код 199