DateFormatters с pandas для построения с использованием DatetimeIndex

#python #pandas #matplotlib

#python #pandas #matplotlib

Вопрос:

Я изо всех сил пытаюсь разобраться с форматированием даты на графиках python pandas. Я хочу иметь возможность обрезать свои даты только до месяца по оси x.

                       Amount (EUR)                                                                                            
Transaction type Cash26 Withdrawal Direct Debit Direct Debit Reversal    Income MasterCard Payment MoneyBeam Outgoing Transfer
Date                                                                                                                          
2020-02-29                  -400.0       -73.86                   NaN  13678.00            -862.01       NaN         -16521.00
2020-03-31                  -450.0      -268.00                  30.0   1431.00            -223.03       NaN          -1889.65
2020-04-30                     NaN          NaN                   NaN  18804.00           -1177.51       NaN         -17889.00
2020-05-31                     NaN          NaN                   NaN   1000.00           -1105.95       NaN               NaN
2020-06-30                  -100.0          NaN                   NaN   5479.01            -955.38       NaN          -4337.00
2020-07-31                     NaN          NaN                   NaN       NaN            -120.84       NaN               NaN
2020-08-31                  -200.0          NaN                   NaN   3300.00            -647.60       NaN           -230.00
2020-09-30                     NaN          NaN                   NaN       NaN           -1454.61       NaN            -50.50
2020-10-31                  -200.0       -25.21                   NaN  12180.00           -1278.63    -100.0          -1917.42
2020-11-30                  -400.0       -18.44                   NaN    590.74           -1509.21       NaN          -2104.62



<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 10 entries, 2020-02-29 to 2020-11-30
Freq: M
Data columns (total 7 columns):
 #   Column                                 Non-Null Count  Dtype  
---  ------                                 --------------  -----  
 0   (Amount (EUR), Cash26 Withdrawal)      6 non-null      float64
 1   (Amount (EUR), Direct Debit)           4 non-null      float64
 2   (Amount (EUR), Direct Debit Reversal)  1 non-null      float64
 3   (Amount (EUR), Income)                 8 non-null      float64
 4   (Amount (EUR), MasterCard Payment)     10 non-null     float64
 5   (Amount (EUR), MoneyBeam)              1 non-null      float64
 6   (Amount (EUR), Outgoing Transfer)      8 non-null      float64
dtypes: float64(7)
 

Я создаю свой график, используя:

 grouped_dataframe_unstacked = grouped_dataframe.unstack()
fig, ax = plt.subplots(figsize=(6, 10))
grouped_dataframe_unstacked.plot(kind='bar', ax=ax, stacked=True)
plt.show()
 

У меня такое чувство, что что-то не так с этими основными метками, но я не могу найти никаких указаний в Интернете.

 for i in ax.xaxis.get_majorticklabels():
    print(i)

Text(0, 0, '2020-02-29 00:00:00')
Text(0, 0, '2020-03-31 00:00:00')
Text(0, 0, '2020-04-30 00:00:00')
Text(0, 0, '2020-05-31 00:00:00')
Text(0, 0, '2020-06-30 00:00:00')
Text(0, 0, '2020-07-31 00:00:00')
Text(0, 0, '2020-08-31 00:00:00')
Text(0, 0, '2020-09-30 00:00:00')
Text(0, 0, '2020-10-31 00:00:00')
Text(0, 0, '2020-11-30 00:00:00')
 

rcParams["date.autoformatter.month"] = "%b %Y" похоже, это не имеет никакого эффекта.

Я пытался использовать различные параметры set_major_locator, но, похоже, это что-то ломает.

 ax.xaxis.set_major_locator(mdates.MonthLocator())
ax.xaxis.set_major_formatter(mdates.DateFormatter('%b'))
 

Я получаю сообщение об ошибке ValueError: DateFormatter found a value of x=0, which is an illegal date; this usually occurs because you have not informed the axis that it is plotting dates, e.g., with ax.xaxis_date() .

У меня такое чувство, что мои даты не передаются в диаграмму должным образом. Кто-нибудь может подсказать мне, как это исправить?

Спасибо,

Эндрюмой график с разбитыми датами

Ответ №1:

Вы пробовали переформатировать столбец даты в исходном фрейме данных, чтобы включить только месяц? Предполагая, что столбец даты имеет тип datetime, вы могли бы сделать что-то вроде:

 df['Date'] = df['Date'].dt.month
 

Если дата представляет собой строку (а не дату), вы могли бы сделать что-то вроде

 df['Date'] = pd.to_datetime(df['Date']).dt.month
 

Оба этих решения преобразуют ваши столбцы даты только в месяц.

Ответ №2:

К сожалению, существуют некоторые коллизии между форматерами и локаторами и тем, как генерируется изображение при вызове из фрейма данных.

Но вы можете форматировать даты в оси, которую вы можете вызвать, например, set_xticklabels с правильно отформатированными датами.

Я предлагаю также другое исправление, касающееся названия легенды. На вашем рисунке в начале не печатается None, потому что имя верхнего уровня столбца MultiIndex — это просто None . Чтобы избежать этого, вы должны удалить верхний уровень индекса столбца.

Чтобы сгенерировать график, используйте следующий код (df — ваш исходный фрейм данных):

 fig, ax = plt.subplots(figsize=(8, 6))
df.droplevel(level=0, axis=1).plot(kind='bar', ax=ax, stacked=True, width=0.8)
ax.set_xticklabels(df.index.to_series().dt.strftime('%b %Y'), rotation=30)
ax.set_xlabel('Month')
plt.show()
 

Другие исправления:

  • Я добавил width = 0.8, потому что в противном случае столбцы (на мой взгляд) слишком узкие,
  • Я изменил заголовок оси x на месяц, поскольку исходная дата не отражает используемые метки,
  • Я установил поворот меток x на 30 градусов (на мой взгляд, теперь они выглядят лучше).

Для вашего образца данных я получил следующую картинку:

введите описание изображения здесь

Вам решать, указывать ли / куда сумму (EUR) (название верхнего уровня в индексе столбца). Возможно, добавьте его в качестве заголовка.