【问题标题】:Set date time format of x-axis in Pandas-Matplotlib在 Pandas-Matplotlib 中设置 x 轴的日期时间格式
【发布时间】:2020-10-30 13:23:57
【问题描述】:

如标题所示,我正在尝试更改图表的日期时间格式。我做了一些研究,发现我的代码中包含了 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')

【问题讨论】:

    标签: pandas datetime matplotlib


    【解决方案1】:

    以下是针对您的选项的修复:

    • 选项 1(使用 strftime):您可以使用 set_xticks 来强制执行正确的刻度位置。
    • 选项 2(使用 mdates):您应该 a) 指定 MonthLocator 和 b) 您需要转换您的索引,以便它们是 datetime.date,而不是 datetime.datetime。这是一个烦人的问题I posted about in more detail。如果您从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
    

    【讨论】:

    • 谢谢汤姆!非常有用,也感谢您的解释。
    • 如果我想将折线图变成条形图,如何将月份定义为 x 轴类别?
    【解决方案2】:

    要使用 Pandas 和 Matplotlib 在条形图中自定义 DateTime 索引,我找到了以下解决方案,可以与上面的代码一起使用:

    #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
    

    这是最好的方法吗?

    非常感谢。

    【讨论】:

      猜你喜欢
      • 2020-12-07
      • 1970-01-01
      • 2019-06-28
      • 2020-02-02
      • 2017-09-27
      • 2017-08-01
      • 1970-01-01
      • 2013-01-04
      • 2015-05-02
      相关资源
      最近更新 更多