Установить формат даты и времени оси x в Pandas -Matplotlib - PullRequest
0 голосов
/ 09 июля 2020

Как и в заголовке, я пытаюсь изменить формат даты и времени моего графика. Я провел небольшое исследование и нашел 2 строки, которые я включил в свой код (#option 1 и #option 2). Они не выдают ошибок, но формат вывода не тот, который я указал. Пожалуйста, прочтите код ниже и посмотрите загруженное изображение. Что я делаю не так? Любая помощь будет очень принята.

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

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


# create an array of 5 dates starting at '2020-02-24', one every month
rng = pd.date_range('2020-02-24', periods=5, freq='MS')
df_1 = pd.DataFrame({ 'Date': rng, 'Val' : np.random.randn(len(rng))})
df_1.set_index("Date", inplace = True)
df_2 = pd.DataFrame({ 'Date': rng, 'Val' : np.random.randn(len(rng))})
df_2.set_index("Date", inplace = True)
print(df_1, "\n")
print(df_2)

#Set up figure
fig, ax = plt.subplots(1,2, figsize=(11,5))
plt.subplots_adjust(left=None, bottom=None, right=None, top=None, wspace=0.3, hspace=None) #Adjust space between graphs

#Plot 1
df_1.plot(ax=ax[0], kind="line", color="forestgreen", stacked=False, rot=90)
ax[0].set_axisbelow(True)  # To put plot grid below plots
ax[0].yaxis.grid(color='gray', linestyle='dashed')
ax[0].xaxis.grid(color='gray', linestyle='dashed')
# option 1
ax[0].set_xticklabels([pandas_datetime.strftime("%d %b %Y") for pandas_datetime in df_1.index])
# option 2
ax[0].xaxis.set_major_formatter(DateFormatter('%d %b %Y'))
ax[0].legend(bbox_to_anchor=(0., 1.02, 1., .102), loc=3, ncol=2, mode="expand", borderaxespad=0.)  # Put legend on top
ax[0].set(xlabel=None, ylabel="Amount %")  # Set axis label


#Plot 2
df_2.plot(ax=ax[1], kind='line', stacked=False, color="violet", rot=90)
ax[1].set_axisbelow(True)  # To put plot grid below plots
ax[1].yaxis.grid(color='gray', linestyle='dashed')
ax[1].xaxis.grid(color='gray', linestyle='dashed')
# option 1
ax[1].set_xticklabels([pandas_datetime.strftime("%d %b %Y") for pandas_datetime in df_2.index])
# option 2
ax[1].xaxis.set_major_formatter(DateFormatter('%d %b %Y'))
ax[1].legend(bbox_to_anchor=(0., 1.02, 1., .102), loc=3, ncol=2, mode="expand", borderaxespad=0.)  # Put legend on top
ax[1].set(xlabel=None, ylabel="Amount %")  # Set axis label


#Save file as png
date_now = datetime.now().strftime('%d-%m-%Y')
fig.savefig("Test_{}.png".format(date_now), bbox_inches='tight')

Ответы [ 2 ]

2 голосов
/ 10 июля 2020

Вот исправления для ваших опций:

  • Вариант 1 (с strftime): вы можете использовать set_xticks, чтобы также обеспечить правильные позиции тиков.
  • Опция 2 (с mdates): вы должны a) указать a MonthLocator и b) вам нужно преобразовать ваш индекс, чтобы они были datetime.date, а не datetime.datetime. Это досадная проблема , о которой более подробно писал . Это не проблема, если вы строите все из matplotlib, но делаете это через pandas, по-видимому, так и есть.

Вот полный код и результат, с графиком 1 с использованием опции 1 и график 2 с использованием варианта 2. Между этими двумя вариантами все еще есть небольшие различия, которые можно отформатировать (как ни странно, галочки в варианте 2 отображаются вертикально, а вариант 1 - нет):

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


# create an array of 5 dates starting at '2020-02-24', one every month
rng = pd.date_range('2020-02-24', periods=5, freq='MS')
df_1 = pd.DataFrame({ 'Date': rng, 'Val' : np.random.randn(len(rng))})
df_1.set_index("Date", inplace = True)
df_2 = pd.DataFrame({ 'Date': rng, 'Val' : np.random.randn(len(rng))})
df_2.set_index("Date", inplace = True)
print(df_1, "\n")
print(df_2)

#Set up figure
fig, ax = plt.subplots(1,2, figsize=(11,5))
plt.subplots_adjust(left=None, bottom=None, right=None, top=None, wspace=0.3, hspace=None) #Adjust space between graphs

#Plot 1
df_1.plot(ax=ax[0], kind="line", color="forestgreen", stacked=False, rot=90)
ax[0].set_axisbelow(True)  # To put plot grid below plots
ax[0].yaxis.grid(color='gray', linestyle='dashed')
ax[0].xaxis.grid(color='gray', linestyle='dashed')
# option 1
ax[0].set_xticks([pandas_datetime.strftime("%d %b %Y") for pandas_datetime in df_1.index])
ax[0].set_xticklabels([pandas_datetime.strftime("%d %b %Y") for pandas_datetime in df_1.index])

ax[0].legend(bbox_to_anchor=(0., 1.02, 1., .102), loc=3, ncol=2, mode="expand", borderaxespad=0.)  # Put legend on top
ax[0].set(xlabel=None, ylabel="Amount %")  # Set axis label


#Plot

#SEE THIS NEW LINE!!!
df_2.index = [pd.to_datetime(date).date() for date in df_2.index]

df_2.plot(ax=ax[1], kind='line', stacked=False, color="violet", rot=90)
ax[1].set_axisbelow(True)  # To put plot grid below plots
ax[1].yaxis.grid(color='gray', linestyle='dashed')
ax[1].xaxis.grid(color='gray', linestyle='dashed')

# option 2
#see new line before df_2.plot
ax[1].xaxis.set_major_locator(MonthLocator())
ax[1].xaxis.set_major_formatter(DateFormatter('%d %b %Y'))
plt.xticks(rotation=0, fontsize=8)

ax[1].legend(bbox_to_anchor=(0., 1.02, 1., .102), loc=3, ncol=2, mode="expand", borderaxespad=0.)  # Put legend on top
ax[1].set(xlabel=None, ylabel="Amount %")  # Set axis label

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

0 голосов
/ 10 июля 2020

Чтобы настроить индекс DateTime в столбчатой ​​диаграмме с использованием Pandas и Matplotlib, я нашел следующее решение, которое можно использовать с приведенным выше кодом:

#Plot 1
df_1.plot(ax=ax[0], kind="bar", color="forestgreen", stacked=False, rot=90)
ax[0].set_axisbelow(True)  # To put plot grid below plots
ax[0].yaxis.grid(color='gray', linestyle='dashed')
ax[0].xaxis.grid(color='gray', linestyle='dashed')

#Grab xticklabels after plotting
ticks = [tick.get_text() for tick in ax[0].get_xticklabels()]
ticks = pd.to_datetime(ticks).strftime('%b %Y')
ax[0].set_xticklabels(ticks)

ax[0].legend(bbox_to_anchor=(0., 1.02, 1., .102), loc=3, ncol=2, mode="expand", borderaxespad=0.)  # Put legend on top
ax[0].set(xlabel=None, ylabel="Amount %")  # Set axis label

Это лучший способ сделать это ?

Большое спасибо.

...