簡體   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