使用 matplotlib 在上部子图上显示 xtick 标签
Show xtick labels on upper subplot with matplotlib
我觉得我已经尝试了在这里找到的所有内容,google、matplotlib 文档和其他几个论坛。我无法让 xticks 显示在上部 subplot/graph 和下部。我在一个与 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,并且仍然旋转它们?
正如 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()
旁注:下标签和上标签没有完全对齐,因为您正在尝试比较两种不同类型的轴:从上到上是连续的(在一个刻度和下一个刻度之间还有许多其他可能的小时值,分、秒)
而较低的是分类的(您只绘制了几天的值,并且在一个厚和下一个之间没有其他值)。
这是一个使用 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 明确关闭除底部之外的所有子图的刻度标签。
Date ticklabels often overlap, so it is useful to rotate them and right align them. Also, a common use case is a number of subplots with shared x-axis where the x-axis is date data. The ticklabels are often long, and it helps to rotate them on the bottom subplot and turn them off on other subplots, as well as turn off xlabels.
这个答案类似于@Zephyr 的答案,但我还是发布了它,因为它正确地对齐了绘图之间的数据。您可以通过在下图设置一天中的不同时间或更改框的宽度来更改对齐方式。
我觉得我已经尝试了在这里找到的所有内容,google、matplotlib 文档和其他几个论坛。我无法让 xticks 显示在上部 subplot/graph 和下部。我在一个与 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,并且仍然旋转它们?
正如 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()
旁注:下标签和上标签没有完全对齐,因为您正在尝试比较两种不同类型的轴:从上到上是连续的(在一个刻度和下一个刻度之间还有许多其他可能的小时值,分、秒) 而较低的是分类的(您只绘制了几天的值,并且在一个厚和下一个之间没有其他值)。
这是一个使用 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 明确关闭除底部之外的所有子图的刻度标签。
Date ticklabels often overlap, so it is useful to rotate them and right align them. Also, a common use case is a number of subplots with shared x-axis where the x-axis is date data. The ticklabels are often long, and it helps to rotate them on the bottom subplot and turn them off on other subplots, as well as turn off xlabels.
这个答案类似于@Zephyr 的答案,但我还是发布了它,因为它正确地对齐了绘图之间的数据。您可以通过在下图设置一天中的不同时间或更改框的宽度来更改对齐方式。