Проблемы с форматом даты в галочках сюжета с помощью matplotlib.dates (и datestr2num) - PullRequest
1 голос
/ 14 января 2020

Я использую matplotlib.dates для построения гистограммы с экземплярами, происходящими в определенные даты c (представленные в виде списка строк), и использую matplotlib.dates.datestr2num для отображения двух наборов данных за дату (как согласно верхнему ответу в Python matplotlib, несколько баров ).

Однако для дат ниже 12-го числа месяца график интерпретирует даты в формате MM / DD / YY в то время как для дат выше 12-го числа месяца она интерпретирует даты как DD / MM / YY, вызывая скачок данных вокруг графика. Я думаю, что проблема может быть в том, как я использую 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 апреля, что делает данные не в порядке.

Любая помощь или разъяснение было бы полезно, спасибо!

Image of the output from above

1 Ответ

0 голосов
/ 14 января 2020

Похоже, что 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()

enter image description here

...