Matplotlib DateFormatter для метки оси не работает

Я пытаюсь настроить форматирование меток даты на оси абсцисс, чтобы в нем отображались только значения года и месяца. Из того, что я нашел в Интернете, я должен использовать mdates.DateFormatter, но он не вступает в силу с моим текущим кодом, как есть. Кто-нибудь видит, где проблема? (даты - это индекс пирамиды данных)

import matplotlib.dates as mdates
import matplotlib.pyplot as plt
import pandas as pd 

fig = plt.figure(figsize = (10,6))
ax = fig.add_subplot(111)

ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m'))

basicDF['some_column'].plot(ax=ax, kind='bar', rot=75)

ax.xaxis_date()

enter image description here

Воспроизводимый код сценария:

import numpy as np
import matplotlib.dates as mdates
import matplotlib.pyplot as plt
import pandas as pd 

rng = pd.date_range('1/1/2014', periods=20, freq='m')

blah = pd.DataFrame(data = np.random.randn(len(rng)), index=rng)

fig = plt.figure(figsize = (10,6))
ax = fig.add_subplot(111)

ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m'))

blah.plot(ax=ax, kind='bar')

ax.xaxis_date()

До сих пор не могу найти только год и месяц.

Если я установлю формат после .plot, получим ошибку, подобную этой:

ValueError: DateFormatter обнаружил значение x = 0, что является недопустимой датой. Обычно это происходит потому, что вы не сообщили оси, что она наносит на график даты, например, с помощью x.xaxis_date().

То же самое, если я поставлю его перед ax.xaxis_date() или после.

Ответ 1

Панды просто плохо работают с пользовательскими форматами даты и времени.

Вам просто нужно использовать raw matplotlib в подобных случаях.

import numpy
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import pandas

N = 20
numpy.random.seed(N)

dates = pandas.date_range('1/1/2014', periods=N, freq='m')
df = pandas.DataFrame(
    data=numpy.random.randn(N), 
    index=dates,
    columns=['A']
)

fig, ax = plt.subplots(figsize=(10, 6))
ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m'))
ax.bar(df.index, df['A'], width=25, align='center')

И это дает мне:

enter image description here

Ответ 2

В принятом ответе утверждается, что "панды не будут хорошо работать с пользовательскими форматами даты и времени", но вы можете использовать функцию панд to_datetime(), чтобы использовать существующий ряд даты и времени в фрейме данных:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.dates import DateFormatter
import pandas as pd

rng = pd.date_range('1/1/2014', periods=20, freq='m')

blah = pd.DataFrame(data = np.random.randn(len(rng)), index=pd.to_datetime(rng))

fig, ax = plt.subplots()

ax.xaxis.set_major_formatter(DateFormatter('%m-%Y'))
ax.bar(blah.index, blah[0], width=25, align='center')

В результате:

a bar graph with the dates formatted as described

Вы можете увидеть различные доступные форматы здесь.