Логарифмические шкалы в Matplotlib: преображение хаотичных данных

Пройдите тест, узнайте какой профессии подходите
Сколько вам лет
0%
До 18
От 18 до 24
От 25 до 34
От 35 до 44
От 45 до 49
От 50 до 54
Больше 55

Для кого эта статья:

  • Аналитики данных
  • Студенты и профессионалы в области статистики и визуализации данных
  • Специалисты, работающие с научными и финансовыми данными

    Работа с данными, показывающими экспоненциальный рост, бросает вызов любому аналитику. Представьте: вы визуализируете рост населения Земли за последние 2000 лет, и график выглядит как плоская линия с вертикальным скачком в конце. Бесполезно? Абсолютно. Здесь на помощь приходят логарифмические оси — инструмент, преображающий хаотичные данные в читаемые паттерны. В этой статье я покажу, как Matplotlib позволяет приручить "дикие" данные с большим диапазоном значений и превратить их в информативные визуализации, раскрывающие скрытые зависимости. 📊✨

Хотите превратить "пляшущие" данные в информативные визуализации? На курсе Профессия аналитик данных от Skypro вы освоите не только логарифмические шкалы в Matplotlib, но и десятки других техник визуализации. Наши студенты уже после 3 месяцев обучения создают профессиональные дашборды и презентации, впечатляющие работодателей. Начните превращать хаос данных в историю успеха прямо сейчас!

Логарифмические шкалы: когда и зачем их использовать

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

Приведу пример. Если у нас есть значения 1, 10, 100, 1000, то на логарифмической шкале (с основанием 10) они будут расположены на равных расстояниях друг от друга. Это радикально меняет восприятие данных! 🔍

Дмитрий Волков, старший аналитик данных

Однажды мне пришлось анализировать эффективность маркетинговой кампании для интернет-магазина. Клиент был озадачен: почему его показатели конверсии так сильно "скачут" по дням? Стандартный график показывал настоящий хаос — пики взлетали до 12%, а падения опускались до 0,01%.

Когда я переключился на логарифмическую шкалу по оси Y, картина мгновенно прояснилась. Оказалось, что на продажи влияли два ключевых фактора с разными порядками воздействия: сезонность (медленные, плавные изменения) и акции (резкие скачки). Благодаря log-шкале мы смогли увидеть оба эффекта на одном графике и оптимизировать маркетинговую стратегию, что привело к росту прибыли на 27% в следующем квартале.

Вот в каких случаях логарифмические шкалы становятся незаменимыми:

  • Данные с большим разбросом значений: например, доходы населения от самых бедных до миллиардеров
  • Экспоненциальный рост: рост населения, распространение вирусов, рост инвестиций
  • Степенные законы: землетрясения (шкала Рихтера), интенсивность звука (децибелы)
  • Сравнение относительных изменений: рост акций, где важны процентные изменения
  • Визуализация данных в широком диапазоне масштабов: астрономические расстояния, размеры частиц
Тип данных Проблема с линейной шкалой Преимущество логарифмической шкалы
Экспоненциальный рост Большинство точек "прижаты" к оси Равномерное распределение данных
Степенные законы Невозможно одновременно отобразить все события Все события видны в одном масштабе
Финансовые данные Процентные изменения не видны Равные процентные изменения выглядят одинаково
Научные измерения Маленькие значения теряются Все порядки величин отображаются чётко
Пошаговый план для смены профессии

Базовые способы создания логарифмических осей в Matplotlib

Создание графиков с логарифмическими осями в Matplotlib — процесс, который я бы охарактеризовал как "изящно простой". Библиотека предоставляет несколько интуитивно понятных способов трансформации осей, которые не требуют кардинального изменения вашего кода. 📝

Начнём с самых основных методов создания логарифмических осей:

  1. Метод plt.xscale() и plt.yscale() — самый распространённый способ
  2. Методы объекта Axes — удобно при работе с несколькими графиками
  3. Создание графиков с уже предустановленными логарифмическими осями

Рассмотрим каждый из них на практических примерах:

Python
Скопировать код
import matplotlib.pyplot as plt
import numpy as np

# Создаём данные с экспоненциальным ростом
x = np.linspace(1, 10, 100)
y = np.exp(x)

# Метод 1: Использование plt.xscale и plt.yscale
plt.figure(figsize=(10, 6))
plt.plot(x, y, 'b-')
plt.yscale('log') # Логарифмическая шкала для оси Y
plt.title('Экспоненциальная функция с логарифмической осью Y')
plt.grid(True)
plt.show()

# Метод 2: Использование методов объекта Axes
fig, ax = plt.subplots(figsize=(10, 6))
ax.plot(x, y, 'r-')
ax.set_yscale('log') # То же самое, но через объект осей
ax.set_title('Через методы объекта Axes')
ax.grid(True)
plt.show()

# Метод 3: Создание графика с предустановленными логарифмическими осями
fig, ax = plt.subplots(figsize=(10, 6), subplot_kw={'yscale': 'log'})
ax.plot(x, y, 'g-')
ax.set_title('Логарифмическая ось Y при создании графика')
ax.grid(True)
plt.show()

Обратите внимание, как с логарифмической осью Y экспоненциальная функция превращается в прямую линию. Это одно из визуальных преимуществ, которые дают логарифмические шкалы — они могут превращать некоторые нелинейные зависимости в линейные, что облегчает анализ. 🧮

Для создания графика с логарифмическими осями по обоим направлениям (логарифмический график) используйте:

Python
Скопировать код
plt.figure(figsize=(10, 6))
plt.loglog(x, y, 'b-') # Эквивалентно вызову plt.xscale('log') и plt.yscale('log')
plt.title('Логарифмический график по обеим осям')
plt.grid(True, which='both') # Отображает сетку и для основных, и для промежуточных делений
plt.show()

Также есть удобные комбинированные функции:

  • plt.semilogx() — логарифмическая шкала по оси X, линейная по оси Y
  • plt.semilogy() — линейная шкала по оси X, логарифмическая по оси Y
  • plt.loglog() — логарифмические шкалы по обеим осям

Алексей Корнеев, руководитель отдела аналитики

Вспоминаю свою первую встречу с логарифмическими осями в Matplotlib. Мы анализировали эффективность алгоритмов машинного обучения на разных объёмах данных. Линейный график времени выполнения выглядел катастрофически — алгоритмы казались практически идентичными на малых объёмах, но некоторые буквально "взрывались" на больших.

Когда я попробовал логарифмировать ось X (размер набора данных), откровением стало то, как чётко проявилась асимптотическая сложность алгоритмов. Алгоритмы с квадратичной сложностью образовывали кривые с постоянным наклоном, линейные алгоритмы формировали прямые линии, а логарифмические — вообще загибались вниз!

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

Типы логарифмических шкал и их настройка в Matplotlib

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

Рассмотрим основные типы логарифмических шкал в Matplotlib:

Тип шкалы Описание Ключевые параметры Типичное применение
log Стандартная логарифмическая шкала base, subs, nonpositive Данные с экспоненциальным ростом
symlog Симметричная логарифмическая шкала base, linthresh, linscale Данные, содержащие и отрицательные, и положительные значения
logit Логарифм шансов nonpositive, use_overline Вероятности, доли (значения от 0 до 1)
function Пользовательская функциональная шкала functions, base Специфические трансформации данных

Давайте рассмотрим каждый тип подробнее:

1. Стандартная логарифмическая шкала (log)

Это наиболее распространённый тип, где значения отображаются как логарифмы с указанным основанием (по умолчанию 10).

Python
Скопировать код
import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(1, 1000, 100)
y = x**2

plt.figure(figsize=(10, 6))
plt.plot(x, y)
plt.yscale('log', base=10) # Логарифмическая шкала с основанием 10
plt.title('Квадратичная функция с логарифмической осью Y')
plt.grid(True)
plt.show()

Ключевые параметры настройки:

  • base: основание логарифма (обычно 10, но можно использовать 2 для компьютерных данных или e для естественных процессов)
  • subs: список промежуточных делений между основными (например, [2, 5] добавит деления на 2 и 5 между степенями 10)
  • nonpositive: способ обработки нулевых и отрицательных значений ('mask', 'clip')

2. Симметричная логарифмическая шкала (symlog)

Идеальна для данных, которые содержат и положительные, и отрицательные значения, а также нули.

Python
Скопировать код
data = np.linspace(-1000, 1000, 1000)
y = data**3 – 100*data

plt.figure(figsize=(10, 6))
plt.plot(data, y)
plt.yscale('symlog', linthresh=10) # Симметричная логарифмическая шкала
plt.title('Кубическая функция с симметричной логарифмической осью Y')
plt.grid(True)
plt.axhline(y=0, color='r', linestyle='-', alpha=0.3)
plt.axvline(x=0, color='r', linestyle='-', alpha=0.3)
plt.show()

Параметры настройки symlog:

  • base: основание логарифма (по умолчанию 10)
  • linthresh: пороговое значение, до которого шкала линейная (помогает избежать проблем около нуля)
  • linscale: определяет относительный размер линейной области

3. Логит-шкала (logit)

Превосходно подходит для визуализации вероятностей или пропорций (значений от 0 до 1).

Python
Скопировать код
x = np.linspace(0.01, 0.99, 100)
y = 1 / (1 + np.exp(-10*(x-0.5))) # Сигмоидная функция

plt.figure(figsize=(10, 6))
plt.plot(x, y)
plt.xscale('logit') # Логит-шкала
plt.title('Сигмоидная функция с логит-шкалой по оси X')
plt.grid(True)
plt.show()

4. Функциональная шкала (function)

Позволяет создать собственную функцию преобразования данных.

Python
Скопировать код
from matplotlib.scale import FuncScale
from matplotlib.transforms import FuncTransform

# Определяем кубический корень как функцию преобразования
def cbrt(x):
return np.sign(x) * np.abs(x)**(1/3)

def cbrt_inv(x):
return np.sign(x) * np.abs(x)**3

# Создаём данные
x = np.linspace(-100, 100, 1000)
y = x**3

# Применяем кубический корень как шкалу
fig, ax = plt.subplots(figsize=(10, 6))
scale = FuncScale(ax, 'y', (cbrt, cbrt_inv))
ax.set_yscale(scale)
ax.plot(x, y)
ax.set_title('Кубическая функция с кубически-корневой шкалой Y')
ax.grid(True)
plt.show()

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

  • Если данные строго положительные и показывают экспоненциальный рост — используйте обычную 'log' шкалу
  • Если данные включают отрицательные значения — выбирайте 'symlog'
  • Для вероятностей и пропорций — 'logit' шкала
  • Если нужно специфическое преобразование — создайте функциональную шкалу

Форматирование меток и оформление логарифмических графиков

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

Основные аспекты форматирования логарифмических графиков:

  1. Настройка делений и сетки
  2. Форматирование меток осей
  3. Добавление второй оси с альтернативными единицами
  4. Визуальное выделение важных областей

Настройка делений и сетки

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

Python
Скопировать код
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.ticker as ticker

# Создаём данные
x = np.logspace(0, 5, 100) # от 10^0 до 10^5
y = x**0.5

# Создаём график
fig, ax = plt.subplots(figsize=(12, 6))
ax.plot(x, y)
ax.set_xscale('log')
ax.set_yscale('log')

# Настраиваем основную и вспомогательную сетку
ax.grid(True, which='major', linestyle='-', linewidth=0.5, color='gray')
ax.grid(True, which='minor', linestyle=':', linewidth=0.25, color='lightgray')

# Настраиваем деления для оси X
ax.xaxis.set_major_locator(ticker.LogLocator(base=10.0, numticks=6))
ax.xaxis.set_minor_locator(ticker.LogLocator(base=10.0, subs=np.arange(2, 10), numticks=10))

ax.set_title('Настройка делений и сетки для логарифмического графика')
plt.show()

Форматирование меток осей

Стандартные метки логарифмической шкалы (10^0, 10^1, 10^2, ...) могут быть неудобны для восприятия. Matplotlib позволяет изменить их формат:

Python
Скопировать код
fig, ax = plt.subplots(figsize=(12, 6))
ax.plot(x, y)
ax.set_xscale('log')

# Форматирование меток оси X как обычных чисел
ax.xaxis.set_major_formatter(ticker.ScalarFormatter())

# Альтернативный вариант – форматирование с определённым количеством знаков после запятой
# ax.xaxis.set_major_formatter(ticker.FuncFormatter(lambda x, _: f"{x:.0f}"))

# Более сложное форматирование с приставками СИ
def si_format(x, pos):
prefixes = ['', 'K', 'M', 'G', 'T']
power = max(0, min(4, int(np.log10(x) // 3)))
return f"{x / 10**(power*3):.1f}{prefixes[power]}"

ax.xaxis.set_major_formatter(ticker.FuncFormatter(si_format))

ax.set_title('Пользовательское форматирование меток логарифмической оси')
plt.grid(True)
plt.show()

Добавление второй оси с альтернативными единицами

Иногда полезно показать значения в различных единицах измерения:

Python
Скопировать код
fig, ax1 = plt.subplots(figsize=(12, 6))

# Основной график
ax1.plot(x, y, 'b-')
ax1.set_xscale('log')
ax1.set_xlabel('Логарифмическая шкала (основание 10)')
ax1.set_ylabel('Значение Y', color='b')
ax1.tick_params(axis='y', labelcolor='b')

# Создание второй оси Y с логарифмом по основанию 2
ax2 = ax1.twinx()
ax2.plot(x, y, 'r-', alpha=0) # Невидимая линия, просто для настройки оси
ax2.set_yscale('log', base=2)
ax2.set_ylabel('Логарифм по основанию 2', color='r')
ax2.tick_params(axis='y', labelcolor='r')

plt.title('График с двумя логарифмическими осями (разные основания)')
plt.grid(True)
plt.show()

Визуальное выделение важных областей

На логарифмических графиках часто бывает полезно выделить определённые значения или диапазоны:

Python
Скопировать код
fig, ax = plt.subplots(figsize=(12, 6))
ax.plot(x, y)
ax.set_xscale('log')
ax.set_yscale('log')

# Добавление горизонтальной линии
ax.axhline(y=100, color='r', linestyle='--', label='Пороговое значение')

# Выделение диапазона значений
ax.axvspan(1000, 10000, alpha=0.2, color='yellow', label='Интересующая область')

# Добавление аннотации
ax.annotate('Особая точка',
xy=(500, 22.36),
xytext=(1000, 10),
arrowprops=dict(facecolor='black', shrink=0.05, width=1.5, headwidth=8))

ax.legend()
ax.set_title('Выделение важных областей на логарифмическом графике')
plt.grid(True, which='both')
plt.show()

При оформлении логарифмических графиков помните несколько важных принципов:

  • Ясность превыше всего — указывайте в подписях, что шкала логарифмическая
  • Избегайте перегруженности — на логарифмической шкале легко создать слишком много делений
  • Подбирайте удобное основание логарифма — для компьютерных данных часто лучше использовать основание 2, для финансовых — 10
  • Используйте цвет и стили линий для разделения основной и второстепенной информации

Практические кейсы применения log-осей для научных данных

Логарифмические шкалы — не просто теоретический инструмент, а практический метод решения реальных аналитических задач. Рассмотрим несколько конкретных примеров, где логарифмирование осей в Matplotlib превращает сложные наборы данных в понятные и информативные визуализации. 🔬📈

Кейс 1: Визуализация закона Мура

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

Python
Скопировать код
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

# Данные о количестве транзисторов в процессорах по годам
years = [1971, 1972, 1974, 1978, 1982, 1985, 1989, 1993, 1997, 1999, 2000, 
2002, 2003, 2004, 2007, 2008, 2010, 2012, 2014, 2016, 2017, 2020]
transistors = [2300, 3500, 4500, 29000, 120000, 275000, 1180000, 3100000, 7500000, 
24000000, 42000000, 55000000, 220000000, 592000000, 1700000000, 
2300000000, 2600000000, 3100000000, 4300000000, 7200000000, 
19200000000, 28300000000]

# Создаём график
fig, ax = plt.subplots(figsize=(12, 7))

# Линейная шкала – экспоненциальный рост плохо виден
ax.plot(years, transistors, 'ro-', alpha=0.3, label='Линейная шкала')

# Логарифмическая шкала – видна линейная зависимость (соответствует закону)
ax.set_yscale('log')
ax.plot(years, transistors, 'bo-', label='Логарифмическая шкала')

# Добавление линии тренда (на логарифмической шкале это прямая)
z = np.polyfit(years, np.log10(transistors), 1)
p = np.poly1d(z)
ax.plot(years, 10**p(years), 'k--', label=f'Тренд (удвоение каждые {0.301/z[0]:.1f} лет)')

ax.set_title('Закон Мура: количество транзисторов в процессорах (1971-2020)')
ax.set_xlabel('Год')
ax.set_ylabel('Количество транзисторов (логарифмическая шкала)')
ax.grid(True, which='both', linestyle='--', linewidth=0.5)
ax.legend()

plt.tight_layout()
plt.show()

В этом примере логарифмическая шкала позволяет:

  • Визуализировать все данные в одном масштабе (от тысяч до миллиардов транзисторов)
  • Проверить соответствие закону Мура (на логарифмической шкале экспоненциальный рост становится прямой линией)
  • Точно определить период удвоения по наклону линии тренда

Кейс 2: Анализ эпидемиологических данных

При анализе распространения эпидемий логарифмическая шкала позволяет лучше выявлять фазы развития процесса:

Python
Скопировать код
# Имитация данных о распространении заболевания
days = np.arange(1, 101)
cases_early = 10 * 1.4**(days[:30]) # Экспоненциальный рост в начале
cases_mid = cases_early[-1] * 1.2**(days[30:70] – days[29]) # Замедление роста
cases_late = cases_mid[-1] * 1.05**(days[70:] – days[69]) # Выход на плато
cases = np.concatenate([cases_early, cases_mid, cases_late])

# Создание графика с двумя панелями
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 6))

# Линейная шкала
ax1.plot(days, cases)
ax1.set_title('Распространение заболевания (линейная шкала)')
ax1.set_xlabel('Дни')
ax1.set_ylabel('Количество случаев')
ax1.grid(True)

# Логарифмическая шкала
ax2.plot(days, cases)
ax2.set_yscale('log')
ax2.set_title('Распространение заболевания (логарифмическая шкала)')
ax2.set_xlabel('Дни')
ax2.set_ylabel('Количество случаев (log)')
ax2.grid(True, which='both')

# Добавляем вертикальные линии, разделяющие фазы эпидемии
for ax in [ax1, ax2]:
ax.axvline(x=30, color='r', linestyle='--', alpha=0.7)
ax.axvline(x=70, color='g', linestyle='--', alpha=0.7)
ax.text(15, ax.get_ylim()[1]*0.9, 'Фаза 1:\nЭкспоненциальный\nрост', color='r')
ax.text(45, ax.get_ylim()[1]*0.9, 'Фаза 2:\nЗамедление', color='g')
ax.text(80, ax.get_ylim()[1]*0.9, 'Фаза 3:\nПлато', color='b')

plt.tight_layout()
plt.show()

Преимущества логарифмической шкалы при анализе эпидемий:

  • Выявление изменений в скорости роста (на линейной шкале начальная фаза почти не видна)
  • Определение момента перехода от экспоненциального роста к линейному (на логарифмической шкале — изменение наклона)
  • Более точное сравнение разных регионов или заболеваний

Кейс 3: Визуализация спектра звуковых частот

В акустике и обработке сигналов логарифмические шкалы незаменимы для анализа частотных характеристик:

Python
Скопировать код
from scipy import signal

# Создаём тестовый сигнал с несколькими частотами
fs = 44100 # Частота дискретизации (Гц)
t = np.linspace(0, 1, fs) # 1 секунда
signal_440 = np.sin(2*np.pi*440*t) # Нота Ля (440 Гц)
signal_880 = 0.5 * np.sin(2*np.pi*880*t) # Октава выше
signal_1760 = 0.25 * np.sin(2*np.pi*1760*t) # Ещё октава выше
signal_110 = 0.7 * np.sin(2*np.pi*110*t) # Октава ниже
mixed_signal = signal_440 + signal_880 + signal_1760 + signal_110

# Вычисляем спектр с помощью БПФ
f, Pxx = signal.welch(mixed_signal, fs, nperseg=4096)

# Создаём график
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(12, 8))

# Линейная шкала частот
ax1.semilogy(f, Pxx)
ax1.set_title('Спектр сигнала (линейная шкала частот)')
ax1.set_xlabel('Частота (Гц)')
ax1.set_ylabel('Спектральная плотность')
ax1.grid(True)

# Логарифмическая шкала частот
ax2.loglog(f, Pxx)
ax2.set_title('Спектр сигнала (логарифмическая шкала частот)')
ax2.set_xlabel('Частота (Гц) – log')
ax2.set_ylabel('Спектральная плотность – log')
ax2.grid(True, which='both')

# Отмечаем основные частоты на обоих графиках
for ax in [ax1, ax2]:
for freq, label in [(110, "110 Гц"), (440, "440 Гц"), (880, "880 Гц"), (1760, "1760 Гц")]:
ax.axvline(x=freq, linestyle='--', alpha=0.7)
idx = np.argmin(np.abs(f – freq))
ax.annotate(label, xy=(freq, Pxx[idx]), xytext=(freq*1.1, Pxx[idx]*1.2),
arrowprops=dict(arrowstyle="->", connectionstyle="arc3"))

plt.tight_layout()
plt.show()

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

  • Восприятие высоты звука: человеческое ухо воспринимает частоту логарифмически (октава — это удвоение частоты)
  • Диапазон слышимых частот: от 20 Гц до 20 кГц — три порядка величины, которые сложно отобразить на линейной шкале

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

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

Загрузка...