К сожалению, столбчатые графики matplotlib, кажется, не очень хорошо сочетаются с pandas датами.
Теоретически, matplotlib выражает ширину столбцов в днях. Но если вы попробуете что-то вроде ax.bar(df4.index,df4['count'], width=30)
, вы увидите сюжет с чрезвычайно широкими полосами, почти полностью заполняющий сюжет. Экспериментируя с width
, происходит нечто странное. Когда width
меньше 2, это выглядит так, будто оно выражено в днях. Но с width
больше, чем 2, он внезапно переходит к чему-то гораздо более широкому.
В моей системе (matplotlib 3.1.2, pandas 0.25.3, Windows) это выглядит так:
Обходной путь использует гистограммы от pandas. Похоже, что они делают бары категоричными, с одним тиком на такт. Но они помечены полной датой, включая часы, минуты и секунды. Вы можете перемаркировать их, например, как:
df4.plot.bar(y='count', width=0.9, ax=ax)
plt.xticks(range(len(df4.index)),
[t.to_pydatetime().strftime("%b '%y") for t in df4.index],
rotation=90)
Дальнейшее расследование, непоследовательное прыгание вокруг ширины бара matplotlib, похоже, связано со сборкой frequency
в pandas раз. Таким образом, решением может быть преобразование дат в даты matplotlib. Если попытаться это сделать, да, значения ширины будут последовательно выражаться в днях.
К сожалению, квартальные даты не имеют одинаковое количество дней между ними, в результате чего некоторые столбцы становятся слишком широкими, а другие - слишком узкими. Решением этой следующей проблемы является явное вычисление количества дней для каждого бара. Чтобы получить хорошее разделение между столбиками, их края должны быть белыми.
from datetime import datetime
x = [datetime.date(t) for t in df4.index] # convert the pandas datetime to matplotlib's
widths = [t1-t0 for t0, t1 in zip(x, x[1:])] # time differences between dates
widths += [widths[-1]] # the very last bar didn't get a width, just repeat the last width
ax.bar(x, df4['count'], width=widths, edgecolor='white')