Регулировка оси X в Matplotlib - PullRequest
0 голосов
/ 30 апреля 2018

У меня есть диапазон значений для каждого часа года. Это означает, что есть 24 х 365 = 8760 значений. Я хочу аккуратно представить эту информацию с помощью matplotlib, с осью X, показывающей январь, февраль ...... Вот мой текущий код:

from matplotlib import pyplot as plt

plt.plot(x_data,y_data,label=str("Plot"))
plt.xticks(rotation=45)
plt.xlabel("Time")
plt.ylabel("Y axis values")
plt.title("Y axis values vs Time")
plt.legend(loc='upper right')
axes = plt.gca()
axes.set_ylim([0,some_value * 3])
plt.show() 

x_data - список, содержащий даты в формате datetime. y_data содержит значения, соответствующие значениям в x_data. Как я могу сделать сюжет аккуратно с месяцами по оси X? Пример:

enter image description here

1 Ответ

0 голосов
/ 30 апреля 2018

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

#creating a toy dataset for one year, random data points within month-specific limits
from datetime import date, timedelta
import random
x_data = [date(2017, 1, 1) + timedelta(days = i) for i in range(365)]
random.shuffle(x_data)
y_data = [random.randint(50 * (i.month - 1), 50 * i.month) for i in x_data]

#the actual plot starts here
from matplotlib import pyplot as plt
#get a scatter plot with horizontal markers for each data point
#in case the dates are not ordered, sort first the dates and the y values accordingly 
plt.scatter([day.strftime("%b") for day in sorted(x_data)], [y for _xsorted, y in  sorted(zip(x_data, y_data))], marker = "_", s = 900)
plt.show()

выход
enter image description here

Недостатком, очевидно, является то, что линии имеют фиксированную длину. Кроме того, если месяц не имеет точки данных, она не будет отображаться на графике.

Редактировать 1:
Вы также можете использовать Axes.hlines , как показано здесь .
Это имеет то преимущество, что длина линии изменяется в зависимости от размера окна. И вам не нужно предварительно сортировать списки, потому что каждая начальная и конечная точка рассчитывается отдельно. Набор данных игрушек создается, как указано выше.

from matplotlib import pyplot as plt
#prepare the axis with categories Jan to Dec
x_ax = [date(2017, 1, 1) + timedelta(days = 31 * i) for i in range(12)]
#create invisible bar chart to retrieve start and end points from automatically generated bars
Bars = plt.bar([month.strftime("%b") for month in x_ax], [month.month for month in x_ax], align = "center", alpha = 0)
start_1_12 = [plt.getp(item, "x") for item in Bars]
end_1_12   = [plt.getp(item, "x") + plt.getp(item, "width") for item in Bars]
#retrieve start and end point for each data point line according to its month
x_start = [start_1_12[day.month - 1] for day in x_data]
x_end = [end_1_12[day.month - 1] for day in x_data]

#plot hlines for all data points
plt.hlines(y_data, x_start, x_end, colors = "blue")
plt.show()

Выход enter image description here

Редактировать 2:
Теперь ваше описание проблемы полностью отличается от того, что вы показываете в своем вопросе. Вы хотите простой линейный график с определенным форматированием оси. Это легко найти в документации matplotlib и по всему SO. Пример того, как этого добиться с помощью созданного выше набора игрушечных данных:

import matplotlib.pyplot as plt
from matplotlib.dates import DateFormatter, MonthLocator

ax = plt.subplot(111)
ax.plot([day for day in sorted(x_data)], [y for _xsorted, y in  sorted(zip(x_data, y_data))], "r.-")
ax.xaxis.set_major_locator(MonthLocator(bymonthday=15))
ax.xaxis.set_minor_locator(MonthLocator())
ax.xaxis.set_major_formatter(DateFormatter("%B"))
plt.show()

Выход enter image description here

...