Смещение вторичной оси в матплотлибе - PullRequest
1 голос
/ 04 мая 2020

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

Итак, что я знаю, так это то, как добавить один или больше осей со смещением по оси Y для построения различных данных относительно одной и той же оси X с использованием ax.twinx(). Третья ось Y называется ось паразита в примере демо оси паразита . Однако, если вы хотите добавить дополнительную ось, которая является только масштабированной версией существующей, вы можете использовать ax.secondary_yaxis(), как показано в демоверсии Secondary axis . Нет дополнительных данных для построения графика.

Чего я пока не смог добиться, так это вторичной оси Y, которая смещена относительно исходной. Это может быть очень полезно, чтобы сделать графики более читабельными в научных сообществах c. Например, в то время как некоторые ученые используют частоту в качестве эталона для спектра электромагнитного поля c, другие используют длину волны или волновое число. Афсар [1] использовал очень удобное обозначение оси, которое включает в себя все три переменные на одном графике:

Absorption of dielectrics in mmWave

Я хотел бы что-то подобное, только по оси Y вместо оси X. Есть ли способ сместить вторичную ось от первичной оси? Я попробовал несколько параметров, но не смог понять.

Спасибо за любую помощь!

[1] Афсар, Мухаммед Нурул. «Прецизионные измерения миллиметровых волн комплексного показателя преломления, комплексной диэлектрической проницаемости c и тангенса потерь обычных полимеров». IEEE Транзакции по измерительным приборам и измерениям IM – 36, нет. 2 (июнь 1987 г.): 530–36. https://doi.org/10.1109/TIM.1987.6312733.

[1]:

Ответы [ 2 ]

2 голосов
/ 04 мая 2020

Полный пример. Третья до последней строки является соответствующей.

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

dates = [datetime.datetime(2018, 1, 1) + datetime.timedelta(hours=k * 6)
         for k in range(240)]
temperature = np.random.randn(len(dates)) * 4 + 6.7
fig, ax = plt.subplots(constrained_layout=True)

ax.plot(dates, temperature)
ax.set_ylabel(r'$T\ [^oC]$')
plt.xticks(rotation=70)


def date2yday(x):
    """Convert matplotlib datenum to days since 2018-01-01."""
    y = x - mdates.date2num(datetime.datetime(2018, 1, 1))
    return y


def yday2date(x):
    """Return a matplotlib datenum for *x* days after 2018-01-01."""
    y = x + mdates.date2num(datetime.datetime(2018, 1, 1))
    return y


secax_x = ax.secondary_xaxis('top', functions=(date2yday, yday2date))
secax_x.set_xlabel('yday [2018]')


def celsius_to_fahrenheit(x):
    return x * 1.8 + 32


def fahrenheit_to_celsius(x):
    return (x - 32) / 1.8


secax_y = ax.secondary_yaxis(
    'right', functions=(celsius_to_fahrenheit, fahrenheit_to_celsius))
secax_y.set_ylabel(r'$T\ [^oF]$')


def celsius_to_anomaly(x):
    return (x - np.mean(temperature))


def anomaly_to_celsius(x):
    return (x + np.mean(temperature))


# document use of a float for the position:
secax_y2 = ax.secondary_yaxis(
    1.2, functions=(celsius_to_anomaly, anomaly_to_celsius))
secax_y2.set_ylabel(r'$T - \overline{T}\ [^oC]$')


plt.show()

enter image description here

0 голосов
/ 04 мая 2020

Вот другой подход, хотя, возможно, это скорее хак:

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


@FuncFormatter
def twin1_formatter(x, pos):
    return f'{x/np.pi*180:.0f}'


@FuncFormatter
def twin2_formatter(x, pos):
    return f'{x/np.pi:.1f} $\pi$'


data = np.arange(0, 2*np.pi, 0.1)

fig, ax = plt.subplots()

twin1 = ax.twiny()
twin1.spines['top'].set_position(('axes', 1.2))
twin1.set_xlabel('Degrees')
twin1.xaxis.set_major_formatter(FuncFormatter(twin1_formatter))

twin2 = ax.twiny()
twin2.set_xlabel('Pies')
twin2.xaxis.set_major_formatter(FuncFormatter(twin2_formatter))
twin2.xaxis.set_ticks(np.array([0, 1/2, 1, 3/2, 2])*np.pi)

ax.plot(data, np.sin(data))
ax.set_xlabel('Radians')
twin1.set_xlim(ax.get_xlim())
twin2.set_xlim(ax.get_xlim())
fig.show()

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...