将分组刻度添加到条形图

Adding grouping ticks to a bar chart

我有一个从 pandas DataFrame 创建的图表,如下所示:

我已将刻度格式化为:

ax = df.plot(kind='bar')
ax.set_xticklabels(df.index.strftime('%I %p'))

但是,我想添加第二组更大的刻度,以实现这种效果:

我已经尝试了很多使用 set_major_locatorset_major_formatter 的变体(以及结合主要和次要格式化程序),但似乎我没有正确地接近它而且我没有也可以在网上找到类似组合报价的有用示例。

有人对如何实现类似于底部图像的效果有什么建议吗?

数据框有一个日期时间索引并且是分箱数据,来自 df.resample(bin_size, label='right', closed='right').sum())

一个想法是设置主刻度以在每天中午显示日期 (%-d-%b),并带有一些填充(例如,pad=40)。这将在中午留下一个小的滴答间隙,因此为了保持一致性,您可以只在奇数时间设置小滴答并给它们 rotation=90.

请注意,这使用了 matplotlib 的 bar(),因为 pandas' plot.bar() 不能很好地处理日期格式。

import matplotlib.dates as mdates

# toy data
dates = pd.date_range('2021-08-07', '2021-08-10', freq='1H')
df = pd.DataFrame({'date': dates, 'value': np.random.randint(10, size=len(dates))}).set_index('date')

# pyplot bar instead of pandas bar
fig, ax = plt.subplots(figsize=(14, 4))
ax.bar(df.index, df.value, width=0.02)

# put day labels at noon
ax.xaxis.set_major_locator(mdates.HourLocator(byhour=[12]))
ax.xaxis.set_major_formatter(mdates.DateFormatter('%-d-%b'))
ax.xaxis.set_tick_params(which='major', pad=40)

# put hour labels on odd hours
ax.xaxis.set_minor_locator(mdates.HourLocator(byhour=range(1, 25, 2)))
ax.xaxis.set_minor_formatter(mdates.DateFormatter('%-I %p'))
ax.xaxis.set_tick_params(which='minor', pad=0, rotation=90)

# add day separators at every midnight tick
ticks = df[df.index.strftime('%H:%M:%S') == '00:00:00'].index
arrowprops = dict(width=2, headwidth=1, headlength=1, shrink=0.02)
for tick in ticks:
    xy = (mdates.date2num(tick), 0) # convert date index to float coordinate
    xytext = (0, -65)               # draw downward 65 points
    ax.annotate('', xy=xy, xytext=xytext, textcoords='offset points',
                annotation_clip=False, arrowprops=arrowprops)