Дата клещей и вращение в matplotlib
У меня возникла проблема с тем, чтобы мои титры даты были повернуты в matplotlib. Ниже приводится небольшая примерная программа. Если я попытаюсь повернуть тики в конце, тики не будут вращаться. Если я попытаюсь повернуть тики, как показано в комментариях 'crashes', то matplot lib сработает.
Это происходит только в том случае, если значения x являются датами. Если я заменю переменную dates
на переменную t
при вызове avail_plot
, вызов xticks(rotation=70)
работает нормально внутри avail_plot
.
Любые идеи?
import numpy as np
import matplotlib.pyplot as plt
import datetime as dt
def avail_plot(ax, x, y, label, lcolor):
ax.plot(x,y,'b')
ax.set_ylabel(label, rotation='horizontal', color=lcolor)
ax.get_yaxis().set_ticks([])
#crashes
#plt.xticks(rotation=70)
ax2 = ax.twinx()
ax2.plot(x, [1 for a in y], 'b')
ax2.get_yaxis().set_ticks([])
ax2.set_ylabel('testing')
f, axs = plt.subplots(2, sharex=True, sharey=True)
t = np.arange(0.01, 5, 1)
s1 = np.exp(t)
start = dt.datetime.now()
dates=[]
for val in t:
next_val = start + dt.timedelta(0,val)
dates.append(next_val)
start = next_val
avail_plot(axs[0], dates, s1, 'testing', 'green')
avail_plot(axs[1], dates, s1, 'testing2', 'red')
plt.subplots_adjust(hspace=0, bottom=0.3)
plt.yticks([0.5,],("",""))
#doesn't crash, but does not rotate the xticks
#plt.xticks(rotation=70)
plt.show()
Ответы
Ответ 1
Если вы предпочитаете не объектно-ориентированный подход, переместите plt.xticks(rotation = 70) прямо перед двумя вызовами avail_plot, например
plt.xticks(rotation=70)
avail_plot(axs[0], dates, s1, 'testing', 'green')
avail_plot(axs[1], dates, s1, 'testing2', 'red')
Это устанавливает свойство вращения перед настройкой меток. Поскольку у вас есть две оси, plt.xticks запутывается после того, как вы сделали два сюжета. В тот момент, когда plt.xticks ничего не делает, plt.gca() не дает вам оси, которые вы хотите изменить, и поэтому plt.xticks, который действует на текущие оси, не будет работать.
Для объектно-ориентированного подхода, не использующего plt.xticks, вы можете использовать
plt.setp( axs[1].xaxis.get_majorticklabels(), rotation=70 )
после двух вызовов avail_plot. Это задает вращение на соответствующих точках.
Ответ 2
Решение работает для matplotlib 2.1 +
Существует метод осей tick_params
, который может изменять свойства тика. Он также существует как метод оси как set_tick_params
ax.tick_params(axis='x', rotation=45)
Или
ax.xaxis.set_tick_params(rotation=45)
В качестве побочного примечания, текущее решение смешивает интерфейс состояния (используя pyplot) с объектно-ориентированным интерфейсом с помощью команды plt.xticks(rotation=70)
. Поскольку код в вопросе использует объектно-ориентированный подход, лучше всего придерживаться этого подхода. Решение действительно дает хорошее явное решение с plt.setp( axs[1].xaxis.get_majorticklabels(), rotation=70 )
Ответ 3
Простое решение, которое позволяет избежать циклирования над ticklabes, состоит в том, чтобы просто использовать
fig.autofmt_xdate()
Эта команда автоматически поворачивает метки xaxis и корректирует их положение. Значения по умолчанию представляют собой угол поворота 30 ° и горизонтальное выравнивание "вправо". Но они могут быть изменены при вызове функции
fig.autofmt_xdate(bottom=0.2, rotation=30, ha='right')
Дополнительный аргумент bottom
эквивалентен настройке plt.subplots_adjust(bottom=bottom)
, что позволяет установить дополнение нижних осей к большему значению для размещения повернутых меток.
Итак, в основном здесь у вас есть все настройки, которые вам нужны, чтобы иметь хорошую ось даты в одной команде.
A хороший пример можно найти на странице matplotlib.
Ответ 4
Другой способ применить horizontalalignment
и rotation
к каждой метке тика - сделать цикл for
над метками тика, которые вы хотите изменить:
import numpy as np
import matplotlib.pyplot as plt
import datetime as dt
now = dt.datetime.now()
hours = [now + dt.timedelta(minutes=x) for x in range(0,24*60,10)]
days = [now + dt.timedelta(days=x) for x in np.arange(0,30,1/4.)]
hours_value = np.random.random(len(hours))
days_value = np.random.random(len(days))
fig, axs = plt.subplots(2)
fig.subplots_adjust(hspace=0.75)
axs[0].plot(hours,hours_value)
axs[1].plot(days,days_value)
for label in axs[0].get_xmajorticklabels() + axs[1].get_xmajorticklabels():
label.set_rotation(30)
label.set_horizontalalignment("right")
![enter image description here]()
И вот пример, если вы хотите контролировать расположение основных и второстепенных тиков:
import numpy as np
import matplotlib.pyplot as plt
import datetime as dt
fig, axs = plt.subplots(2)
fig.subplots_adjust(hspace=0.75)
now = dt.datetime.now()
hours = [now + dt.timedelta(minutes=x) for x in range(0,24*60,10)]
days = [now + dt.timedelta(days=x) for x in np.arange(0,30,1/4.)]
axs[0].plot(hours,np.random.random(len(hours)))
x_major_lct = mpl.dates.AutoDateLocator(minticks=2,maxticks=10, interval_multiples=True)
x_minor_lct = matplotlib.dates.HourLocator(byhour = range(0,25,1))
x_fmt = matplotlib.dates.AutoDateFormatter(x_major_lct)
axs[0].xaxis.set_major_locator(x_major_lct)
axs[0].xaxis.set_minor_locator(x_minor_lct)
axs[0].xaxis.set_major_formatter(x_fmt)
axs[0].set_xlabel("minor ticks set to every hour, major ticks start with 00:00")
axs[1].plot(days,np.random.random(len(days)))
x_major_lct = mpl.dates.AutoDateLocator(minticks=2,maxticks=10, interval_multiples=True)
x_minor_lct = matplotlib.dates.DayLocator(bymonthday = range(0,32,1))
x_fmt = matplotlib.dates.AutoDateFormatter(x_major_lct)
axs[1].xaxis.set_major_locator(x_major_lct)
axs[1].xaxis.set_minor_locator(x_minor_lct)
axs[1].xaxis.set_major_formatter(x_fmt)
axs[1].set_xlabel("minor ticks set to every day, major ticks show first day of month")
for label in axs[0].get_xmajorticklabels() + axs[1].get_xmajorticklabels():
label.set_rotation(30)
label.set_horizontalalignment("right")
![enter image description here]()