Проблемы с форматом даты в тиках графика с matplotlib.dates (и datestr2num)
Я использую matplotlib.dates для построения гистограммы с экземплярами, встречающимися в определенные даты (представленные в виде списка строк), и использую matplotlib.dates.datestr2num для отображения двух наборов данных на дату (согласно верхнему ответу в Python matplotlib несколько баров).
Однако для дат ниже 12-го числа месяца график интерпретирует даты в формате ММ / ДД / ГГ, тогда как для дат выше 12-го числа месяца он интерпретирует даты как ДД / ММ / ГГ, в результате чего данные, чтобы прыгать по графику. Я думаю, что проблема может быть в том, как я использую datestr2num, но не знаю, как заставить его быть в том или ином формате.
import matplotlib.pyplot as plt
from matplotlib.dates import DateFormatter, AutoDateLocator, AutoDateFormatter, datestr2num
days = ['30/01/2019', '31/01/2019', '01/02/2019', '02/02/2019', '03/02/2019', '04/02/2019']
adata = [1, 9, 10, 3, 7, 6]
bdata = [1, 2, 11, 3, 6, 2]
x=datestr2num(days)
w=0.25
fig = plt.figure(figsize = (8,4))
ax = fig.add_subplot(111)
ax.bar(x-w, adata, width=2*w, color='g', align='center', tick_label = days)
ax.bar(x+w, bdata, width=2*w, color='r', align='center', tick_label = days)
ax.xaxis_date()
ax.xaxis.set_major_locator(AutoDateLocator(minticks=3, interval_multiples=False))
ax.xaxis.set_major_formatter(DateFormatter("%d/%m/%y"))
plt.show()
В приведенном выше примере adata
а также bdata
относятся к последующим датам (с 30 января по 4 февраля), при этом все столбцы показаны рядом друг с другом, но на графике отображаются данные между 2 января и 2 апреля, поэтому данные отображаются не по порядку.
Любая помощь или разъяснение будут полезны, спасибо!
1 ответ
Кажется, что datestr2num()
звонки dateutil.parser.parse(d, default=default)
. dateutil.parser.parse
есть kwarg dayfirst
но datestr2num()
не дает возможности передать аргумент вперед. Если вы передадите список дат вdatesttr2num()
сначала будет месяц.
>>> [dateutil.parser.parse(day, dayfirst=True) for day in days]
[
datetime.datetime(2019, 1, 30, 0, 0),
datetime.datetime(2019, 1, 31, 0, 0),
datetime.datetime(2019, 2, 1, 0, 0),
datetime.datetime(2019, 2, 2, 0, 0),
datetime.datetime(2019, 2, 3, 0, 0),
datetime.datetime(2019, 2, 4, 0, 0)
]
>>> datestr2num(days)
[737089. 737090. 737061. 737092. 737120. 737151.]
>>> datestr2num(days, dayfirst=True)
Traceback (most recent call last):
File "C:\Users\bcohan\Downloads\so.py", line 22, in <module>
print(datestr2num(days, dayfirst=True))
TypeError: datestr2num() got an unexpected keyword argument 'dayfirst'
Я бы предложил обрабатывать даты с помощью datetime
сначала, а затем запуск остальных. (Если нет смысла переписывать строки в исходномdays
список.)
x = datestr2num([
datetime.strptime(day, '%d/%m/%Y').strftime('%m/%d/%Y')
for day in days
])
Вот полностью рабочий сценарий.
from datetime import datetime
import matplotlib.pyplot as plt
from matplotlib.dates import (
DateFormatter, AutoDateLocator, AutoDateFormatter, datestr2num
)
days = [
'30/01/2019', '31/01/2019', '01/02/2019',
'02/02/2019', '03/02/2019', '04/02/2019'
]
adata = [1, 9, 10, 3, 7, 6]
bdata = [1, 2, 11, 3, 6, 2]
x = datestr2num([
datetime.strptime(day, '%d/%m/%Y').strftime('%m/%d/%Y')
for day in days
])
w = 0.25
fig = plt.figure(figsize=(8, 4))
ax = fig.add_subplot(111)
ax.bar(x - w, adata, width=2 * w, color='g', align='center', tick_label=days)
ax.bar(x + w, bdata, width=2 * w, color='r', align='center', tick_label=days)
ax.xaxis_date()
ax.xaxis.set_major_locator(
AutoDateLocator(minticks=3, interval_multiples=False))
ax.xaxis.set_major_formatter(DateFormatter("%d/%m/%y"))
plt.show()