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

Немного рекламы

Оглавление

Введение

Помимо настройки положения меток на осях Matplotlib позволяет настраивать подписи под ними. Для этого используются специальные классы (форматеры), производные от класса matplotlib.ticker.Formatter. Для того, чтобы установить форматер для оси, нужно вызвать метод set_major_formatter() экземпляра класса matplotlib.axis.Axis - класса для работы с одной осью.

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

#!/usr/bin/python
# -*- coding: UTF-8 -*-

import numpy

import pylab


if __name__ == "__main__":
    xvals = numpy.arange (-10.0, 10.1, 0.1)
    yvals = numpy.sinc (xvals)

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

    pylab.plot (xvals, yvals)

    axes.grid()
    pylab.show()

Теперь рассмотрим, как можно менять форматирование с помощью метода set_major_formatter(), а заодно посмотрим, какие форматеры предоставляет библиотека Matplotlib. Все рассматриваемые здесь форматеры находятся в модуле matplotlib.ticker. Кроме того некоторые другие, более специфические модули предоставляют свои форматеры (например, модуль для работы с календарными данными), но в данной статье мы их рассматривать не будем.

NullFormatter

С помощью класса NullFormatter можно отключить вывод всех подписей у меток на оси (при этом сами метки остаются, для их отключения нужно использовать локатор NullLocator).

#!/usr/bin/python
# -*- coding: UTF-8 -*-

import numpy

import pylab
import matplotlib.ticker


if __name__ == "__main__":
    xvals = numpy.arange (-10.0, 10.1, 0.1)
    yvals = numpy.sinc (xvals)

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

    # Создаем форматер
    formatter = matplotlib.ticker.NullFormatter()

    # Установка форматера для оси X
    axes.xaxis.set_major_formatter (formatter)

    pylab.plot (xvals, yvals)

    axes.grid()
    pylab.show()

Из этого примера видно, что сначала создается форматер (в данном случае экземпляр класса NullFormatter), а затем он применяется с помощью метода set_major_formatter() для оси X, доступ к которой осуществляется с помощью свойства xaxis экземпляра класса matplotlib.axes.AxesSubplot' (переменная axes). Результат работы этого скрипта показан на следующем рисунке:

Как видите, сами метки (риски) остались, однако, подписи под ними исчезли.

Конструктор класса NullFormatter не принимает никакие параметры, и никаких дополнительных настроек в нем нет, поэтому перейдем к следующему форматеру.

FormatStrFormatter

По осям в большинстве случаев откладываются какие-либо числовые данные (календарный тип данных заслуживает отдельной статьи), поэтому логично предоставить пользователям класс для удобного выбора числового формата надписей (количество знакомест, количество значащих нулей, возможность использования экспоненциальной формы записи чисел и т.п.). Для этого и предназначен класс FormatStrFormatter.

В качестве единственного параметра его конструктор принимает строку форматирования, в которую при помощи оператора % будут подставляться числа, соответствующие меткам.

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

#!/usr/bin/python
# -*- coding: UTF-8 -*-

import numpy

import pylab
import matplotlib.ticker


if __name__ == "__main__":
    xvals = numpy.arange (-10.0, 10.1, 0.1)
    yvals = numpy.sinc (xvals)

    pylab.rc('font',**{'family':'verdana'})
    figure = pylab.figure()
    axes = figure.add_subplot (1, 1, 1)

    # Создаем форматер
    formatter = matplotlib.ticker.FormatStrFormatter ("%.3f")

    # Установка форматера для оси X
    axes.xaxis.set_major_formatter (formatter)

    pylab.plot (xvals, yvals)

    axes.grid()
    pylab.show()

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

FuncFormatter

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

def funcForFormatter (x, pos):
    ...

Параметр x представляет собой величину, которую нужно отобразить около метки, а параметр pos - это номер метки: 0, 1, 2,...

Эта функция должна вернуть строку, которая будет отображаться около соответствующей метки.

В следующем примере FuncFormatter используется для того, чтобы выводить числа в виде "плюс 10", "минус 5" и т.п.

import numpy

import pylab
import matplotlib.ticker


def funcForFormatter (x, pos):
    if x < 0:
        return u"минус {x}".format (x=abs(x))

    if x > 0:
        return u"плюс {x}".format (x=x)

    return u"0"


if __name__ == "__main__":
    xvals = numpy.arange (-10.0, 10.1, 0.1)
    yvals = numpy.sinc (xvals)

    pylab.rc('font',**{'family':'verdana'})
    figure = pylab.figure()
    axes = figure.add_subplot (1, 1, 1)

    # Создаем форматер
    formatter = matplotlib.ticker.FuncFormatter(funcForFormatter)

    # Установка форматера для оси X
    axes.xaxis.set_major_formatter (formatter)

    pylab.plot (xvals, yvals)

    axes.grid()
    pylab.show()

Обратите внимание, что здесь изменен шрифт на Verdana, чтобы не было проблем с русскими буквами (см. статью Как выводить текст и настраивать его внешний вид).

ScalarFormatter

Класс ScalarFormatter используется для простого вывода чисел. При этом у него есть несколько настроек, позволяющих сделать отображение больших чисел чуть более компактным. Именно этот форматер используется для отображения чисел по умолчанию (если не установлен никакой другой форматер).

Для начала, пусть наша функция sinc() умножается на большое число (например, на 105). По умолчанию график будет выглядеть следующим образом:

#!/usr/bin/python
# -*- coding: UTF-8 -*-

import numpy

import pylab
import matplotlib.ticker


if __name__ == "__main__":
    xvals = numpy.arange (-10.0, 10.1, 0.1)
    yvals = numpy.sinc (xvals) * 1e5

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

    pylab.plot (xvals, yvals)

    axes.grid()
    pylab.show()

Если же мы умножим нашу функцию на еще большее значение, например, на 1010, то график будет выглядеть несколько иначе.

#!/usr/bin/python
# -*- coding: UTF-8 -*-

import numpy

import pylab
import matplotlib.ticker


if __name__ == "__main__":
    xvals = numpy.arange (-10.0, 10.1, 0.1)
    yvals = numpy.sinc (xvals) * 1e10

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

    pylab.plot (xvals, yvals)

    axes.grid()
    pylab.show()

Обратите внимание, что библиотека Matplotlib вынесла множитель 1010, и надписи около оси Y стали более компактными.

Аналогично форматер работает и в том случае, если значения очень маленькие.

#!/usr/bin/python
# -*- coding: UTF-8 -*-

import numpy

import pylab
import matplotlib.ticker


if __name__ == "__main__":
    xvals = numpy.arange (-10.0, 10.1, 0.1)
    yvals = numpy.sinc (xvals) * 1e-10

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

    pylab.plot (xvals, yvals)

    axes.grid()
    pylab.show()

Самое интересное, что класс ScalarFormatter позволяет задавать пределы, когда нужно переходить на запись чисел в экспоненциальной форме. Для этого есть два пути. Первый - это использовать метод set_powerlimits(), который принимает кортеж из двух значений: первое значение - показатель степени 10 для маленьких чисел, второе значение - значение показатель степени 10 для больших чисел.

Следующий пример устанавливает, что, если максимальное значение по оси Y меньше (по модулю) 10-3 или больше (опять же, по модулю) 102, то будет использоваться экспоненциальная форма записи.

#!/usr/bin/python
# -*- coding: UTF-8 -*-

import numpy

import pylab
import matplotlib.ticker


if __name__ == "__main__":
    xvals = numpy.arange (-10.0, 10.1, 0.1)
    yvals = numpy.sinc (xvals) * 1e5

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

    # Создаем форматер
    formatter = matplotlib.ticker.ScalarFormatter ()
    formatter.set_powerlimits((-3, 2))

    # Установка форматера для оси Y
    axes.yaxis.set_major_formatter (formatter)

    pylab.plot (xvals, yvals)

    axes.grid()
    pylab.show()

Второй способ заключается в том, чтобы установить те же самые пределы глобально для всех графиков с помощью rcParams. Для этого параметру axes.formatter.limits нужно присвоить тот же самый кортеж.

#!/usr/bin/python
# -*- coding: UTF-8 -*-

import numpy

import pylab
import matplotlib
import matplotlib.ticker


if __name__ == "__main__":
    xvals = numpy.arange (-10.0, 10.1, 0.1)
    yvals = numpy.sinc (xvals) * 1e5

    matplotlib.rcParams["axes.formatter.limits"] = (-3, 2)
    figure = pylab.figure()
    axes = figure.add_subplot (1, 1, 1)

    pylab.plot (xvals, yvals)

    axes.grid()
    pylab.show()

Результат будет выглядеть точно так же, как и в предыдущем примере.

Другой способ представления чисел с помощью ScalarFormatter заключается в том, чтобы не умножать числа на какой-то коэффициент (степень 10), а добавлять ко всем значениям некоторую константу (смещение). Для этого нужно воспользоваться методом set_useOffset() класса ScalarFormatter, передав методу значение константы, или свойством useOffset этого же класса.

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

#!/usr/bin/python
# -*- coding: UTF-8 -*-

import numpy

import pylab
import matplotlib.ticker


if __name__ == "__main__":
    xvals = numpy.arange (-10.0, 10.1, 0.1)
    yvals = numpy.sinc (xvals) * 1e5

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

    # Создаем форматер
    formatter = matplotlib.ticker.ScalarFormatter ()

    # Следующие две строки равнозначны
    # formatter.set_useOffset (1e5)
    formatter.useOffset = 1e5

    # Установка форматера для оси Y
    axes.yaxis.set_major_formatter (formatter)

    pylab.plot (xvals, yvals)

    axes.grid()
    pylab.show()

Обратите внимание на запись чисел по оси Y.

FixedFormatter

Если заранее известно количество меток, то может оказаться полезным форматер FixedFormatter для задания нестандартных надписей под ними.

Конструктор FixedFormatter принимает список строк, и эти строки последовательно подписывает под соответствующей меткой. Это показано в следующем примере:

#!/usr/bin/python
# -*- coding: UTF-8 -*-

import numpy

import pylab
import matplotlib.ticker


if __name__ == "__main__":
    xvals = numpy.arange (-10.0, 10.1, 0.1)
    yvals = numpy.sinc (xvals)

    pylab.rc('font',**{'family':'verdana'})
    figure = pylab.figure()
    axes = figure.add_subplot (1, 1, 1)

    # Создаем форматер
    formatter = matplotlib.ticker.FixedFormatter([u"Раз", u"Два", u"Три", u"Четыре", u"Пять"])

    # Установка форматера для оси X
    axes.xaxis.set_major_formatter (formatter)

    pylab.plot (xvals, yvals)

    axes.grid()
    pylab.show()

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

#!/usr/bin/python
# -*- coding: UTF-8 -*-

import numpy

import pylab
import matplotlib.ticker


if __name__ == "__main__":
    xvals = numpy.arange (-10.0, 10.1, 0.1)
    yvals = numpy.sinc (xvals)

    pylab.rc('font',**{'family':'verdana'})
    figure = pylab.figure()
    axes = figure.add_subplot (1, 1, 1)

    # Создаем форматер
    formatter = matplotlib.ticker.FixedFormatter([u"Раз", u"Два", u"Три"])

    # Установка форматера для оси X
    axes.xaxis.set_major_formatter (formatter)

    pylab.plot (xvals, yvals)

    axes.grid()
    pylab.show()

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

Другие форматеры

За рамками статьи остались еще несколько форматеров, которым стоит уделить внимание в будущих статьях. Так, существуют форматеры, предназначенные для логарифмических осей: LogFormatter, LogFormatterExponent и LogFormatterMathtext. Кроме того, модуль matplotlib.dates содержит форматеры, предназначенные для отображения календарных данных на осях. Про эти форматеры мы поговорим в статьях, описывающих логарифмическое представление данных и календарные данные.

Другие статьи про Matplotlib


Немного рекламы

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

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




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