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

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

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

Оглавление

Введение

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

Сначала продемонстрируем проблему, построив график функции, приведенной ниже, в линейном масштабе.

Скрипт для построения графика этой функции с помощью функции plot() выглядит следующим образом:

# -*- coding: utf-8 -*-

import numpy as np
import matplotlib.pyplot as plt

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

# Количество точек на графике
count = 1001

# Создадим список координат по оси X на отрезке [xmin; xmax)
x = np.linspace(xmin, xmax, count)

# Вычислим значение функции в заданных точках
y = np.abs(np.sinc(x / np.pi)) * np.exp(-np.abs(x / 10))

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

# Добавление графика
axes.plot(x, y)
axes.set_xlim(xmin, xmax)
axes.set_ylim(0, 1)
axes.grid()
plt.show()

Дальнейшие примеры будут являться модификацией этого скрипта. График приведенной выше функции в линейном масштабе выглядит следующим образом:

Значение функции быстро убывает по экспоненте и поэтому в таком виде сложно оценить величины дальних боковых лепестков (локальных подъемов) функции.

Использование функций semilogx() / semilogy()

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

# -*- coding: utf-8 -*-

import numpy as np
import matplotlib.pyplot as plt

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

# Создадим список координат по оси X на отрезке [xmin; xmax)
x = np.linspace(xmin, xmax, count)
y = np.abs(np.sinc(x / np.pi)) * np.exp(-np.abs(x / 10))

figure, axes = plt.subplots()

# !!! Строим график в логарифмическом масштабе по оси Y
axes.semilogy(x, y)

axes.set_xlim(xmin, xmax)
axes.set_ylim(None, 1)
axes.grid()
plt.show()

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

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

Также обратите внимание, что в этом примере изменен вызов функции set_ylim(), предназначенной для установки интервала отображения графика (про изменение интервала по осям читайте статью Как изменять интервал осей). Поскольку логарифм от 0 не определен, в качестве минимального значения в функции set_ylim() передается None, чтобы библиотека Matplotlib сама определила, какое минимальное значение использовать.

Использование функций set_xscale() / set_yscale()

Того же самого эффекта можно добиться, если по-прежнему использовать функцию plot() для построения графика, а затем изменить масштаб по оси Y с помощью функции (метода) set_yscale() экземпляра класса matplotlib.axes.Axes. Эта функция ожидает один обязательный параметр value, который может принимать три строковых значения:

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

Разумеется, существует аналогичный метод set_xscale() для установки логарифмического масштаба по оси X.

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

# -*- coding: utf-8 -*-

import numpy as np
import matplotlib.pyplot as plt

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

# Создадим список координат по оси X на отрезке [xmin; xmax)
x = np.linspace(xmin, xmax, count)
y = np.abs(np.sinc(x / np.pi)) * np.exp(-np.abs(x / 10))

figure, axes = plt.subplots()

# Строим график
axes.plot(x, y)

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

axes.set_xlim(xmin, xmax)
axes.set_ylim(None, 1)
axes.grid()
plt.show()

Результат будет такой же, как и на предыдущей картинке. В дальнейших примерах мы в основном будем использовать второй подход, хотя необязательные параметры, которые мы будем передавать в функции set_xscale() и set_yscale() можно передавать и в функции semilogx() / semilogy().

Изменение положений промежуточных рисок

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

# -*- coding: utf-8 -*-

import numpy as np
import matplotlib.pyplot as plt

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

# Создадим список координат по оси X на отрезке [xmin; xmax)
x = np.linspace(xmin, xmax, count)
y = np.abs(np.sinc(x / np.pi)) * np.exp(-np.abs(x / 10))

figure, axes = plt.subplots()

# Строим график
axes.plot(x, y)

# !!! Устанавливаем логарифмический масштаб по оси Y
# !!! и устанавливаем промежуточные риски на значениях 2 и 5.
axes.set_yscale('log', subs=[2, 5])

axes.set_xlim(xmin, xmax)
axes.set_ylim(None, 1)
axes.grid()
plt.show()

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

Того же результата можно добиться при использовании аналогичного параметра subs, если строить график с помощью метода semilogy():

# -*- coding: utf-8 -*-

import numpy as np
import matplotlib.pyplot as plt

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

# Создадим список координат по оси X на отрезке [xmin; xmax)
x = np.linspace(xmin, xmax, count)
y = np.abs(np.sinc(x / np.pi)) * np.exp(-np.abs(x / 10))

figure, axes = plt.subplots()

# !!! Строим график в логарифмическом масштабе по оси Y
# !!! и устанавливаем промежуточные риски на значениях 2 и 5.
axes.semilogy(x, y, subs=[2, 5])

axes.set_xlim(xmin, xmax)
axes.set_ylim(None, 1)
axes.grid()
plt.show()

Изменение основания логарифма

С помощью именованного параметра base функций set_xscale() / set_yscale() (а также semilogx() и semilogy()) можно устанавливать основание логарифма в логарифмическом масштабе. По умолчанию используется основание 10, но мы можем изменить его, например, на 2, что и показано в следующем примере.

# -*- coding: utf-8 -*-

import numpy as np
import matplotlib.pyplot as plt

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

# Создадим список координат по оси X на отрезке [xmin; xmax)
x = np.linspace(xmin, xmax, count)
y = np.abs(np.sinc(x / np.pi)) * np.exp(-np.abs(x / 10))

figure, axes = plt.subplots()

# Строим график
axes.plot(x, y)

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

axes.set_xlim(xmin, xmax)
axes.set_ylim(None, 1)
axes.grid()
plt.show()

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

Объединение линейного и логарифмического масштабов

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

# -*- coding: utf-8 -*-

import numpy as np
import matplotlib.pyplot as plt

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

# Создадим список координат по оси X на отрезке [xmin; xmax)
x = np.linspace(xmin, xmax, count)
y = np.abs(np.sinc(x / np.pi))

figure, axes = plt.subplots()

# Строим график
axes.plot(x, y)

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

axes.set_xlim(None, xmax)
axes.set_ylim(0, 1)
axes.grid()
plt.show()

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

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

# -*- coding: utf-8 -*-

import numpy as np
import matplotlib.pyplot as plt

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

# Создадим список координат по оси X на отрезке [xmin; xmax)
x = np.linspace(xmin, xmax, count)
y = np.abs(np.sinc(x / np.pi))

figure, axes = plt.subplots()

# Строим график
axes.plot(x, y)

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

axes.set_xlim(0, xmax)
axes.set_ylim(0, 1)
axes.grid()
plt.show()

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

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

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

# -*- coding: utf-8 -*-

import numpy as np
import matplotlib.pyplot as plt

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

# Создадим список координат по оси X на отрезке [xmin; xmax)
x = np.linspace(xmin, xmax, count)
y = np.abs(np.sinc(x / np.pi))

figure, axes = plt.subplots()

# Строим график
axes.plot(x, y)

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

axes.set_xlim(0, xmax)
axes.set_ylim(0, 1)
axes.grid()
plt.show()

Логарифмический масштаб по обеим осям

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

# -*- coding: utf-8 -*-

import numpy as np
import matplotlib.pyplot as plt

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

# Создадим список координат по оси X на отрезке [xmin; xmax)
x = np.linspace(xmin, xmax, count)
y = np.abs(np.sinc(x / np.pi))

figure, axes = plt.subplots()

# !!! Строим график в логарифмическом масштабе по обоим осям
axes.loglog(x, y)

axes.set_xlim(None, xmax)
axes.set_ylim(None, 1)
axes.grid()
plt.show()

В результате функция f(x) = |sinc(x / π)| в таких осях будет выглядеть следующим образом:

Того же самого результата можно добиться с использованием методов set_xscale() и set_yscale() одновременно:

# -*- coding: utf-8 -*-

import numpy as np
import matplotlib.pyplot as plt

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

# Создадим список координат по оси X на отрезке [xmin; xmax)
x = np.linspace(xmin, xmax, count)
y = np.abs(np.sinc(x / np.pi))

figure, axes = plt.subplots()

# Строим график
axes.plot(x, y)

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

axes.set_xlim(None, xmax)
axes.set_ylim(None, 1)
axes.grid()
plt.show()

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

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

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




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