#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) (название верхнего уровня в индексе столбца). Возможно, добавьте его в качестве заголовка.