#python #matplotlib #twinx
Вопрос:
У меня есть три массива: time
, steps
и volume
. Я хочу построить график изменения volume
(оси Y) по time
(оси X) и продемонстрировать, как time
это соотносится с steps
(2-й осью X).
time = np.array([1.280000e-07, 1.322240e-07, 1.364480e-07, 1.288448e-06,
1.288448e-06, 1.288448e-06, 1.292672e-06, 1.292672e-06,
1.420672e-06, 1.424896e-06, 1.429120e-06, 2.581120e-06,
2.581120e-06, 2.581120e-06, 2.585344e-06, 2.585344e-06,
2.586400e-06, 2.587456e-06, 2.603456e-06])
steps = np.arange(1,20)
volume = np.array([256., 384., 512., 512., 384., 256., 128., 0., 256., 384., 512.,
512., 384., 256., 128., 0., 32., 64., 96.])
Значения времени от time
связаны с соответствующими steps
значениями, такими как step[1]
происходит в time[1]
, step[2]
в time[2]
и т. Д.
Я пробовал twiny()
, но, похоже, это работает только в том случае, если масштаб между двумя осями одинаков. На графике ниже обе оси имеют одинаковые интервалы между значениями и равномерно распределены.
fig, ax1 = plt.subplots(1, 1, figsize=(10, 4.5), dpi=160, facecolor='w', edgecolor='k', sharey=True)
ax1.plot(t,volume)
ax2 = ax1.twiny()
ax2.set_xticks(steps)
Как масштабировать steps
ось в соответствии с time
осью?
Ответ №1:
A twin ax
-это новый ax
, помещенный в ту же позицию, что и исходный, но устанавливающий свои тики с другой стороны. По умолчанию нет связи между исходными отметками и новыми отметками, хотя такая связь может подразумеваться тщательным установлением ограничений по оси.
Напротив, a secondary ax
устанавливает фиксированную связь между тиками. Если явно не задано отношение, это будет отношение идентичности.
Чтобы получить желаемый результат, вы можете установить такую вторичную ось и поместить метки steps
as, используя time
для позиционирования.
Это выглядело бы так:
import numpy as np
import matplotlib.pyplot as plt
time = np.array([1.28e-07, 1.32224e-07, 1.36448e-07, 1.288448e-06, 1.288448e-06, 1.288448e-06, 1.292672e-06, 1.292672e-06, 1.420672e-06, 1.424896e-06, 1.42912e-06, 2.58112e-06, 2.58112e-06, 2.58112e-06, 2.585344e-06, 2.585344e-06, 2.5864e-06, 2.587456e-06, 2.603456e-06])
steps = np.arange(1, 20)
volume = np.array([256., 384., 512., 512., 384., 256., 128., 0., 256., 384., 512., 512., 384., 256., 128., 0., 32., 64., 96.])
fig, ax1 = plt.subplots(1, 1, figsize=(10, 4.5), facecolor='w', edgecolor='k')
ax1.plot(time, volume)
secax = ax1.secondary_xaxis('top')
secax.set_xticks(time)
secax.set_xticklabels(steps)
plt.show()
Поскольку многие временные позиции либо идентичны, либо близки друг к другу, полученные метки перекрываются. Решением может быть объединение этих перекрывающихся меток и создание диапазона меток:
pos = []
labels = []
start_step = steps[0]
for prev_t, t, prev_step, step in zip(time,
np.append(time[1:], np.inf),
steps,
np.append(steps[1:], 0)):
if (t - prev_t) > prev_t / 20:
pos = [prev_t]
if start_step == prev_step:
labels = [f'{start_step}']
else:
labels = [f'{start_step}-{prev_step}']
start_step = step
secax.set_xticks(pos)
secax.set_xticklabels(labels)
Комментарии:
1. Это определенно так. Большое спасибо!