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

1zmg4dgp  于 2023-10-24  发布在  其他
关注(0)|答案(2)|浏览(147)

我觉得我已经尝试了我能在这里找到的所有东西,谷歌,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(),如果是的话,有没有一种方法可以显示两个子图的xticklabel,并且仍然旋转它们?

raogr8fs

raogr8fs1#

这里有一个使用Matplotilb的面向对象界面的解决方案,它可以让你对齐轴并旋转轴上的标签。在子图中共享x轴可以使缩放对两个子图都有效。
使用以下命令打开上部子图上的刻度

up.tick_params(labelbottom=True)

箱线图是使用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?)以外的所有子图的ticklabels。
日期刻度标签经常重叠,所以旋转它们并右对齐它们是很有用的。此外,一个常见的用例是多个共享x轴的子图,其中x轴是日期数据。刻度标签通常很长,它有助于在底部子图上旋转它们,并在其他子图上关闭它们,以及关闭xlabels**。
这个答案与@Zephyr的答案类似,但我还是贴了出来,因为它正确地对齐了图之间的数据。你可以通过在下面的图上设置一天中的不同时间或通过改变框的宽度来改变对齐。

9o685dep

9o685dep2#

正如JohanC已经指出的,你应该使用matplotlib's object-oriented interface
您可以创建所需的两个子图,然后根据需要自定义轴:

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()

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

相关问题