Matplotlib Subplot日期时间X轴刻度不按预期工作

时间:2016-03-10 17:09:51

标签: python datetime matplotlib plot

我正在尝试绘制许多图,下面是数据组织方式的示例:

dataframe

我的目的是使用谷歌分析数据建立一系列小时或数天的子图(例如一周7天,或一天24小时)。我的索引是日期时间对象。

以下是当轴正确完成时单个绘图的外观示例。

from datetime import datetime, date, timedelta
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
import matplotlib.dates as dates

#creating our graph and declaring our locator/formatters used in axis labelling.
hours = dates.HourLocator(interval=2)
hours_ = dates.DateFormatter('%I %p')

el = datetime(year=2016, day=1, month=3, hour=0)
fig, ax = plt.subplots(ncols = 1, nrows= 1)
fig.set_size_inches(18.5, 10.5)
fig.tight_layout()
ax.set_title(el.strftime('%a, %m/%d/%y'))
ax.plot(df_total.loc[el:el+timedelta(hours=23, minutes=59),:].index, 
                             df_total.loc[el:el+timedelta(hours=23, minutes=59),:].hits, '-')
ax.xaxis.set_major_locator(hours)
ax.xaxis.set_major_formatter(hours_) 
fig.show()

right graph!

正如您所看到的,x轴看起来很好,按照预期正确的刻度/日期标签工作。

然而,当我尝试在子图系列上运行相同的图时,我遇到了以下错误。这是我的代码:

fig, ax = plt.subplots(ncols = 3, nrows= 2)
fig.set_size_inches(18.5, 10.5)
fig.tight_layout()

nrows=2
ncols=3

count = 0

for row in range(nrows):
    for column in range(ncols):
        el = cleaned_date_range[count]
        ax[row][column].set_title(el.strftime('%a, %m/%d/%y'))
        ax[row][column].xaxis.set_major_locator(hours)
        ax[row][column].xaxis.set_major_formatter(hours_)
        ax[row][column].plot(df_total.loc[el:el+timedelta(hours=23,minutes=59),:].index, df_total.loc[el:el+timedelta(hours=23,minutes=59),:].hits)
        count += 1

        if count == 7:
            break

然而,这会产生下面非常时髦的情节,标签错误标记:

wrong graph!

我尝试添加一行以查看它是否因为垂直空间而被覆盖: enter image description here

但是遇到了相同的行为,只有最后一个子图的轴似乎正在使用其余的不工作。

任何见解都将受到赞赏!

2 个答案:

答案 0 :(得分:5)

所以答案是几年前提出的与set_major_locator()set_major_formatter()对象相关的github问题:

https://github.com/matplotlib/matplotlib/issues/1086/

引用埃里克:

“你遗漏了一些东西,但这是非常不直观且容易错过的东西:定位器不能在轴之间共享.set_major_locator()方法将其轴分配给该定位器,覆盖任何轴。以前分配的。“

所以解决方案是为每个新轴实例化一个新的dates.MinuteLocatordates.DateFormatter对象,例如:

for ax in list_of_axes:
    minutes = dates.MinuteLocator(interval=5)
    minutes_ = dates.DateFormatter('%I:%M %p')
    ax.xaxis.set_major_locator(minutes)
    ax.xaxis.set_major_formatter(minutes_)

我已经进行了实验,看起来你不需要在绘图之后引用dates.Locator和dates.Formatter对象,所以可以使用相同的名称重新实例化每个循环。 (虽然我可能错了!)

答案 1 :(得分:0)

我遇到了同样的子图日期时间x轴刻度线丢失的问题。以下代码与OP的代码非常相似,似乎可以正常工作,请参见附图。但是,我正在使用matplotlib 3.1.0,也许此版本已解决了该问题?但是我确实有一个观察:如果为第二个子图启用fig.autofmt_xdate(),则第一个子图的日期时间x轴将不会显示。

fig = plt.figure()
plt.rcParams['figure.figsize'] = (width, height)
plt.subplots_adjust(wspace=0.25, hspace=0.2)

ax = fig.add_subplot(2,1,1)
ax.xaxis.set_major_locator(MonthLocator(bymonthday=1))
ax.xaxis.set_major_formatter(DateFormatter('%Y-%b'))
ax.plot(df1['DATE'], df1['Movement'], '-')
plt.ylabel(r'$D$', fontsize=18)
plt.xticks(fontsize=12)
plt.yticks(fontsize=16)
plt.legend(fontsize=16, frameon=False)
fig.autofmt_xdate()

ax = fig.add_subplot(2,1,2)
ax.xaxis.set_major_locator(MonthLocator(bymonthday=1))
ax.xaxis.set_major_formatter(DateFormatter('%Y-%b'))
ax.plot(df2['DATE'], df2['Movement'], '-')
#plt.ylabel(r'$D`enter code here`$', fontsize=18)
plt.xticks(fontsize=16)
plt.yticks(fontsize=16)
plt.legend(fontsize=16, frameon=False)
#fig.autofmt_xdate()

plt.show()

enter image description here