Использование библиотеки Matplotlib. Как установить логарифмический масштаб по осям

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

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

Для первых примеров мы будем использовать следующую функцию:

Сначала нарисуем ее в линейных осях:

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

import numpy
import pylab

# Будем рисовать график этой функции
def func (x):
    """
    sinc (x)
    """

    if x == 0:
        return 1.0
    return numpy.abs (numpy.sin (x) / x) * numpy.exp (-numpy.abs (x / 10))

# Интервал изменения переменной по оси X
xmin = -50.0
xmax = 50.0

# Шаг между точками
dx = 0.1

# Создадим список координат по оси X на отрезке [xmin; xmax)
xlist = numpy.arange (xmin, xmax, dx)

# Вычислим значение функции в заданных точках
ylist = [func (x) for x in xlist]

# Создадим новую фигуру
figure = pylab.figure()

# Создадим поле для рисования и получим его оси
axes = figure.add_subplot (1, 1, 1)

# Добавление графика
pylab.plot (xlist, ylist)

pylab.show()

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

Теперь сделаем так, чтобы по оси Y был не линейный, а логарифмический масштаб (логарифм будет по основанию 10). Для этого достаточно заменить функцию plot на semilogy (если бы нам нужен быть логарифмический масштаб только по оси x, то нужно было бы использовать функцию semilogx, для использования логарифмического масштаба по обоим осям предназначена функция loglog).

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

import numpy
import pylab

# Будем рисовать график этой функции
def func (x):
    if x == 0:
        return 1.0
    return numpy.abs (numpy.sin (x) / x) * numpy.exp (-numpy.abs (x / 10))

# Интервал изменения переменной по оси X
xmin = -50.0
xmax = 50.0

# Шаг между точками
dx = 0.01

# Создадим список координат по оси X на отрезке [xmin; xmax)
xlist = numpy.arange (xmin, xmax, dx)

# Вычислим значение функции в заданных точках
ylist = [func (x) for x in xlist]

# Построим график с логарифмической осью Y
pylab.semilogy (xlist, ylist)

pylab.show()

Теперь та же функция на графике будет выглядеть по-другому.

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

Того же самого эффекта можно добиться, используя более объектно-ориентированный стиль программирования. Для этого нужно получить экземпляр класса осей matplotlib.axes.Axes, после чего вызвать его метод set_yscale (set_xscale). Метод set_yscale ожидает один обязательный параметр value, который может принимать три строковых значения:

  • "linear" - график по оси будет отображаться в линейном масштабе.
  • "log" - график по оси будет отображаться в логарифмическом масштабе.
  • "symlog" - график вблизи нуля будет отображаться в линейном масштабе, а дальше в логарифмическом (про этот режим еще поговорим отдельно).

Изменим предыдущий пример, чтобы использовать метод set_yscale.

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

import numpy
import pylab

# Будем рисовать график этой функции
def func (x):
    if x == 0:
        return 1.0
    return numpy.abs (numpy.sin (x) / x) * numpy.exp (-numpy.abs (x / 10))

# Интервал изменения переменной по оси X
xmin = -50.0
xmax = 50.0

# Шаг между точками
dx = 0.01

# Создадим список координат по оси X на отрезке [xmin; xmax)
xlist = numpy.arange (xmin, xmax, dx)

# Вычислим значение функции в заданных точках
ylist = [func (x) for x in xlist]

# Создадим новую фигуру
figure = pylab.figure()

# Создадим поле для рисования и получим его оси
axes = figure.add_subplot (1, 1, 1)

# Добавление графика
pylab.plot (xlist, ylist)

# Установим логарифмический масштаб по оси Y
axes.set_yscale ('log')

pylab.show()

Результат будет такой же, как и на предыдущей картинке. В дальнейших примерах будем использовать объектно-ориентированный подход, хотя необязательные параметры, которые мы будем использовать при value="log" можно передавать и в функции semilogx / semilogy.

Если вы хорошенько присмотритесь к вертикальной оси на последней картинке, то увидите, что между главными рисками есть промежуточные черточки, расставленные с шагом 1 * 10n, то есть по умолчанию между рисками 10-1 и 10-2 есть риски 0.09, 0.08, 0.07, 0.06, 0.05, 0.04, 0.03 и 0.02. Можно изменить количество рисок, добавив в вызов метода set_yscale параметр subsy, который должен быть списком целых чисел. Например, если мы хотим оставить промежуточные риски только на значениях 0.02 и 0.05, то этот параметр должен быть равен [2, 5]. Это продемонстрировано в следующем примере.

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

import numpy
import pylab

# Будем рисовать график этой функции
def func (x):
    if x == 0:
        return 1.0
    return numpy.abs (numpy.sin (x) / x) * numpy.exp (-numpy.abs (x / 10))

# Интервал изменения переменной по оси X
xmin = -50.0
xmax = 50.0

# Шаг между точками
dx = 0.01

# Создадим список координат по оси X на отрезке [xmin; xmax)
xlist = numpy.arange (xmin, xmax, dx)

# Вычислим значение функции в заданных точках
ylist = [func (x) for x in xlist]

# Создадим новую фигуру
figure = pylab.figure()

# Создадим поле для рисования и получим его оси
axes = figure.add_subplot (1, 1, 1)

# Добавление графика
pylab.plot (xlist, ylist)

# Установим логарифмический масштаб по оси Y
axes.set_yscale ('log', subsy=[2, 5])

pylab.show()

Результат показан на следующем рисунке:

С помощью дополнительного параметра basey (basex) можно устанавливать основание логарифма в логарифмическом масштабе. По умолчанию используется основание 10, но мы можем изменить его, например, на 2, что и показано в следующем примере.

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

import numpy
import pylab

# Будем рисовать график этой функции
def func (x):
    if x == 0:
        return 1.0
    return numpy.abs (numpy.sin (x) / x) * numpy.exp (-numpy.abs (x / 10))

# Интервал изменения переменной по оси X
xmin = -50.0
xmax = 50.0

# Шаг между точками
dx = 0.01

# Создадим список координат по оси X на отрезке [xmin; xmax)
xlist = numpy.arange (xmin, xmax, dx)

# Вычислим значение функции в заданных точках
ylist = [func (x) for x in xlist]

# Создадим новую фигуру
figure = pylab.figure()

# Создадим поле для рисования и получим его оси
axes = figure.add_subplot (1, 1, 1)

# Добавление графика
pylab.plot (xlist, ylist)

# Установим логарифмический масштаб по оси Y
axes.set_yscale ('log', basey=2)

pylab.show()

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

Как было сказано выше, методы set_xscale / set_yscale, в качестве обязательного параметра могут принимать строку symlog.

Для наглядности демонстрации этого параметра изменим отображаемую функцию и интервал, где она рисуется. Пусть функция f(x) = sin(x) / x рисуется по оси X в интервале [0; 500), в этом случае есть смысл установить логарифмический масштаб по оси X, тогда скрипт и соответствующий график будут выглядеть следующим образом:

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

import numpy
import pylab

# Будем рисовать график этой функции
def func (x):
    if x == 0:
        return 1.0
    return numpy.abs (numpy.sin (x) / x)

# Интервал изменения переменной по оси X
xmin = 0.0
xmax = 500.0

# Шаг между точками
dx = 0.1

# Создадим список координат по оси X на отрезке [xmin; xmax)
xlist = numpy.arange (xmin, xmax, dx)

# Вычислим значение функции в заданных точках
ylist = [func (x) for x in xlist]

# Создадим новую фигуру
figure = pylab.figure()

# Создадим поле для рисования и получим его оси
axes = figure.add_subplot (1, 1, 1)

# Добавление графика
pylab.plot (xlist, ylist)

# Установим логарифмический масштаб по оси X
axes.set_xscale ('log')

pylab.show()

Значение symlog параметра функций set_xscale / set_yscale позволяет сделать так, чтобы на части оси график имел линейный масштаб, а на части - логарифмический. Линейный масштаб может быть только вблизи нуля. Эта возможность полезна, чтобы избежать бесконечных значений вблизи нуля. Дополнительный параметр linthreshx (linthreshy для метода set_yscale) позволяет установить, от 0 до какого значения масштаб должен быть линейным.

Изменим предыдущий пример таким образом, чтобы от 0 до 5 масштаб был линейным, а потом становился логарифмическим.

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

import numpy
import pylab

# Будем рисовать график этой функции
def func (x):
    if x == 0:
        return 1.0
    return numpy.abs (numpy.sin (x) / x)

# Интервал изменения переменной по оси X
xmin = 0.0
xmax = 500.0

# Шаг между точками
dx = 0.01

# Создадим список координат по оси X на отрезке [xmin; xmax)
xlist = numpy.arange (xmin, xmax, dx)

# Вычислим значение функции в заданных точках
ylist = [func (x) for x in xlist]

# Создадим новую фигуру
figure = pylab.figure()

# Создадим поле для рисования и получим его оси
axes = figure.add_subplot (1, 1, 1)

# Добавление графика
pylab.plot (xlist, ylist)

# Установим логарифмический масштаб по оси X
axes.set_xscale ('symlog', linthreshx=5)

pylab.show()

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

Там, где на графике виден излом, это и есть точка x = 5.

С помощью необязательного параметра linscalex (linscaley при использовании метода set_yscale) можно установить, насколько будет растянут интервал с линейным масштабом. Следующий пример делает линейную часть оси в три раза длиннее (при этом координата точки перегиба останется равной x = 5).

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

import numpy
import pylab

# Будем рисовать график этой функции
def func (x):
    if x == 0:
        return 1.0
    return numpy.abs (numpy.sin (x) / x)

# Интервал изменения переменной по оси X
xmin = 0.0
xmax = 500.0

# Шаг между точками
dx = 0.01

# Создадим список координат по оси X на отрезке [xmin; xmax)
xlist = numpy.arange (xmin, xmax, dx)

# Вычислим значение функции в заданных точках
ylist = [func (x) for x in xlist]

# Создадим новую фигуру
figure = pylab.figure()

# Создадим поле для рисования и получим его оси
axes = figure.add_subplot (1, 1, 1)

# Добавление графика
pylab.plot (xlist, ylist)

# Установим логарифмический масштаб по оси X
axes.set_xscale ('symlog', linthreshx=5, linscalex=3)

pylab.show()

И в завершении статьи посмотрим, как работает функция loglog для установки логарифмического масштаба по обоим осям.

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

import numpy
import pylab

# Будем рисовать график этой функции
def func (x):
    if x == 0:
        return 1.0
    return numpy.abs (numpy.sin (x) / x)

# Интервал изменения переменной по оси X
xmin = 0.0
xmax = 500.0

# Шаг между точками
dx = 0.01

# Создадим список координат по оси X на отрезке [xmin; xmax)
xlist = numpy.arange (xmin, xmax, dx)

# Вычислим значение функции в заданных точках
ylist = [func (x) for x in xlist]

# Создание графика с обоими осями в логарифмическом масштабе
pylab.loglog (xlist, ylist)

pylab.show()

В результате функция синк в таких осях будет выглядеть следующим образом:

Того же самого результата можно добиться и в объектно-ориентированном стиле:

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

import numpy
import pylab

# Будем рисовать график этой функции
def func (x):
    if x == 0:
        return 1.0
    return numpy.abs (numpy.sin (x) / x)

# Интервал изменения переменной по оси X
xmin = 0.0
xmax = 500.0

# Шаг между точками
dx = 0.01

# Создадим список координат по оси X на отрезке [xmin; xmax)
xlist = numpy.arange (xmin, xmax, dx)

# Вычислим значение функции в заданных точках
ylist = [func (x) for x in xlist]

# Создадим новую фигуру
figure = pylab.figure()

# Создадим поле для рисования и получим его оси
axes = figure.add_subplot (1, 1, 1)

# Добавление графика
pylab.plot (xlist, ylist)

# Установим логарифмический масштаб по оси X
axes.set_xscale ('log')

# Установим логарифмический масштаб по оси Y
axes.set_yscale ('log')

pylab.show()

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


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

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




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