matplotlib 子图日期时间X轴刻度未按预期工作

v2g6jxz6  于 2023-06-06  发布在  其他
关注(0)|答案(2)|浏览(345)

我试图绘制许多图,这里有一个数据组织方式的示例:

我的意图是利用谷歌分析数据,建立一系列小时或天(比如一周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()

正如您所看到的,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

然而,这产生了下面非常时髦的图,带有错误标记的轴:

我尝试添加额外的一行,看看它是否只是因为垂直空间而被覆盖:

但面对同样的行为,只有最后一个子情节的轴似乎是工作与其余不工作。
任何见解将不胜感激!

0vvn1miw

0vvn1miw1#

我有同样的失踪子情节日期时间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()

zfycwa2u

zfycwa2u2#

所以答案是几年前提出的与set_major_locator()set_major_formatter()对象相关的github问题:
https://github.com/matplotlib/matplotlib/issues/1086/
引用Eric的话:
“你错过了一些东西,但这是一个非常不直观和容易错过的东西:定位器不能在轴之间共享。set_major_locator()方法将其轴分配给该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_)

我做过实验,看起来你不需要引用日期。定位器和日期。格式化对象后的情节,所以它是确定的,只是重新示例化与每个循环使用相同的名称。(我可能是错的!)

相关问题