繁体   English   中英

使用 matplotlib 在上部子图上显示 xtick 标签

[英]Show xtick labels on upper subplot with matplotlib

我觉得我已经尝试了我能在这里找到的所有东西、谷歌、matplotlib 文档和其他几个论坛。 我无法让 xticks 显示在上部子图/图形和下部。 我在一个与 matplotlib 相关的论坛中读到,其他人也有与我相同的问题,使用早期版本的 matplotlib,但该线程几年前就死了,并且建议的修复程序在我的情况下不起作用。

数据从 CSV 文件中提取,并转换为浮点数和日期时间值

import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import datetime as dt
import numpy as np

y = [26.0, 24.6, 23.9, 23.7, 23.6, 21.8, 22.0, 23.6]
x = [datetime.datetime(2020, 9, 2, 14, 13), datetime.datetime(2020, 9, 2, 14, 23), datetime.datetime(2020, 9, 2, 14, 33), datetime.datetime(2020, 9, 2, 14, 43), datetime.datetime(2020, 9, 2, 14, 53), datetime.datetime(2020, 9, 3, 0, 3), datetime.datetime(2020, 9, 4, 0, 3), datetime.datetime(2020, 9, 4, 0, 13)]
out = {datetime.date(2020, 9, 2): [26.0, 24.6, 23.9, 23.7, 23.6], datetime.date(2020, 9, 3): [21.8], datetime.date(2020, 9, 4): [21.6, 21.6]}

'''I found a thread a couple of days ago, where these 2 lines were the fix. honestly don't remember what the problem was, except it was related to datetime and plt'''
plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%d-%m-%Y %H:%M'))
plt.gca().xaxis.set_major_locator(mdates.DayLocator())

ax1 = plt.subplot(2, 1, 1)
plt.plot(x, y)
plt.xlabel('time')
plt.ylabel('temp')
plt.title('logs')
plt.grid()
ax1.xaxis.set_major_formatter(mdates.DateFormatter('%d-%m-%Y %H:%M'))

'''and also found how to subplot a boxplot from dict, from another thread'''
ax2 = plt.subplot(2, 1, 2)
labels, data = [*zip(*out.items())]  # 'transpose' items to parallel key, value lists
plt.boxplot(data)
plt.xticks(range(1, len(labels) + 1), labels)
plt.xlabel('date')
plt.ylabel('temp')

'''for rotating the xticklabels, and as far as I've been able to read, the most likely culprit'''
plt.gcf().autofmt_xdate()

plt.draw() # non-blocking call

plt.show() # keep last in script to keep windows open after execution

这是结果

它可能只是plt.gcf().autofmt_xdate()如果是,有没有办法显示两个子图的 xticklabels,并且仍然让它们旋转?

这是使用 Matplotilb 的面向对象界面的解决方案,可让您对齐轴并旋转轴上的标签。 在子图中共享 xaxis 使得缩放适用于两个子图。

上部子图上的刻度是通过使用打开的

up.tick_params(labelbottom=True)

boxplots 使用 matplotlib 的日期值定位,对应于使用的日期时间

mdates.date2num(d)
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import datetime as dt
import numpy as np
import datetime


y = [26.0, 24.6, 23.9, 23.7, 23.6, 21.8, 22.0, 23.6]
x = [datetime.datetime(2020, 9, 2, 14, 13), datetime.datetime(2020, 9, 2, 14, 23), datetime.datetime(2020, 9, 2, 14, 33), datetime.datetime(2020, 9, 2, 14, 43), datetime.datetime(2020, 9, 2, 14, 53), datetime.datetime(2020, 9, 3, 0, 3), datetime.datetime(2020, 9, 4, 0, 3), datetime.datetime(2020, 9, 4, 0, 13)]
out = {datetime.date(2020, 9, 2): [26.0, 24.6, 23.9, 23.7, 23.6], datetime.date(2020, 9, 3): [21.8], datetime.date(2020, 9, 4): [21.6, 21.6]}


f, (up, down) = plt.subplots(2, 1, sharex=True)

up.plot(x, y)
up.set_xlabel('time')
up.set_ylabel('temp')
up.set_title('logs')
up.grid()

down.boxplot(
    out.values(),
    positions=[mdates.date2num(d) for d in out.keys()]
)

down.get_xaxis().set_major_formatter(mdates.DateFormatter('%d-%m-%Y %H:%M'))
down.get_xaxis().set_major_locator(mdates.DayLocator())

up.tick_params(labelbottom=True)

plt.setp( up.xaxis.get_majorticklabels(), rotation=30 )
plt.setp( down.xaxis.get_majorticklabels(), rotation=30 )

f.tight_layout()
plt.draw()

请注意, autofmt_xdate明确关闭了除底部(s?)之外的所有子图的刻度标签。

日期刻度标签经常重叠,因此旋转它们并右对齐它们很有用。 此外,一个常见的用例是一些共享 x 轴的子图,其中 x 轴是日期数据。 刻度标签通常很长,它有助于在底部子图中旋转它们并在其他子图中关闭它们,以及关闭 xlabels

这个答案类似于@Zephyr 的答案,但我还是发布了它,因为它正确地对齐了图之间的数据。 您可以通过在下方的绘图上设置一天中的不同时间或更改框的宽度来更改对齐方式。

结果

正如 JohanC 已经指出的那样,您应该使用matplotlib 的面向对象接口

您可以创建您需要的两个子图,然后根据您的需要自定义轴:

import matplotlib.pyplot as plt
import datetime as datetime
import matplotlib.dates as md


y = [26.0, 24.6, 23.9, 23.7, 23.6, 21.8, 22.0, 23.6]
x = [datetime.datetime(2020, 9, 2, 14, 13), datetime.datetime(2020, 9, 2, 14, 23), datetime.datetime(2020, 9, 2, 14, 33), datetime.datetime(2020, 9, 2, 14, 43), datetime.datetime(2020, 9, 2, 14, 53), datetime.datetime(2020, 9, 3, 0, 3), datetime.datetime(2020, 9, 4, 0, 3), datetime.datetime(2020, 9, 4, 0, 13)]
out = {datetime.date(2020, 9, 2): [26.0, 24.6, 23.9, 23.7, 23.6], datetime.date(2020, 9, 3): [21.8], datetime.date(2020, 9, 4): [21.6, 21.6]}

fig, ax = plt.subplots(2, 1)

ax[0].plot(x, y)
ax[0].set_xlabel('time')
ax[0].set_ylabel('temp')
ax[0].set_title('logs')
ax[0].grid()

labels, data = [*zip(*out.items())]
ax[1].boxplot(data)
ax[1].set_xticklabels([label.strftime('%Y-%m-%d') for label in labels])
ax[1].set_xlabel('date')
ax[1].set_ylabel('temp')

ax[0].xaxis.tick_top()
ax[0].xaxis.set_major_formatter(md.DateFormatter('%Y-%m-%d'))
ax[0].xaxis.set_major_locator(md.DayLocator())
plt.setp(ax[0].xaxis.get_majorticklabels(), rotation = 45)
ax[0].set_xlim(labels[0], labels[-1])

plt.setp(ax[1].xaxis.get_majorticklabels(), rotation = 45)

plt.show()

在此处输入图片说明

旁注:下标签和上标签没有完全对齐,因为您正在尝试比较两种不同类型的轴:顶部是连续的(在一个刻度和下一个刻度之间有许多其他可能的小时、分钟、秒值)而较低的一个是分类的(您只绘制几天的值,并且在一个厚的和下一个之间没有其他的)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM