Matplotlib自定義座標軸刻度的實現示例
雖然 Matplotlib 預設的座標軸定位器(locator)
與格式生成器(formatter)
可以滿足大部分需求,但是並非對每一幅圖都合適。此次我將通過一些示例演示如何將座標軸刻度調整為你需要的位置與格式。
在介紹示例之前,我們最好先對 Matplotlib 圖形的物件層級有更深入的理解。Matplotlib 的目標是用 Python 物件表現任意圖形元素。例如,想想前面介紹的 figure 物件
,它其實就是一個盛放圖形元素的包圍盒(bounding box)
。可以將每個 Matplotlib 物件都看成是子物件(sub-object)
的容器,例如每個 figure 都會包含一個或多個 axes 物件
座標軸刻度線也不例外。每個 axes 都有 xaxis 和 yaxis 屬性,每個屬性同樣包含構成座標軸的線條、刻度和標籤的全部屬性。
1 主要刻度與次要刻度
每一個座標軸都有主要
刻度線與次要
刻度線。顧名思義,主要刻度往往更大或更顯著,而次要刻度往往更小。雖然一般情況下 Matplotlib 不會使用次要刻度,但是你會在對數圖中看到它們
import matplotlib.pyplot as plt plt.style.use('seaborn-whitegrid') import numpy as np ax = plt.axes(xscale='log',yscale='log') plt.show()
我們發現每個主要刻度都顯示為一個較大的刻度線和標籤,而次要刻度都顯示為一個較小的刻度線,且不顯示標籤。
可以通過設定每個座標軸的 formatter 與 locator 物件,自定義這些刻度屬性(包括刻度線的位置和標籤)。來檢查一下圖形 x 軸的屬性:
In[1]: print(ax.xaxis.get_major_locator()) print(ax.xaxis.get_minor_locator())
<matplotlib.ticker.LogLocator object at 0x107530cc0> <matplotlib.ticker.LogLocator object at 0x107530198>
In[2]: print(ax.xaxis.get_major_formatter()) print(ax.xaxis.get_minor_formatter())
<matplotlib.ticker.LogFormatterMathtext object at 0x107512780> <matplotlib.ticker.NullFormatter object at 0x10752dc18>
我們會發現,主要刻度標籤和次要刻度標籤的位置都是通過一個 LogLocator 物件
(在對數圖中可以看到)設定的。然而,次要刻度有一個 NullFormatter 物件
處理標籤,這樣標籤就不會在圖上顯示了。
下面來演示一些示例,看看不同圖形的定位器與格式生成器是如何設定的。
2 隱藏刻度與標籤
隱藏圖形的 x 軸標籤與 y 軸刻度
最常用的刻度 / 標籤格式化操作可能就是隱藏刻度與標籤了,可以通過 plt.NullLocator()
與 plt.NullFormatter()
實現,如下所示
ax = plt.axes() ax.plot(np.random.rand(50)) ax.yaxis.set_major_locator(plt.NullLocator()) ax.xaxis.set_major_formatter(plt.NullFormatter())
import matplotlib.pyplot as plt plt.style.use('seaborn-whitegrid') import numpy as np ax = plt.axes() ax.plot(np.random.rand(50)) ax.yaxis.set_major_locator(plt.NullLocator()) ax.xaxis.set_major_formatter(plt.NullFormatter()) plt.show()
需要注意的是,我們移除了 x 軸的標籤(但是保留了刻度線 / 網格線),以及 y 軸的刻度(標籤也一併被移除)。
隱藏人臉圖形的座標軸
在許多場景中都不需要刻度線,比如當你想要顯示一組圖形時。舉個例子,不同人臉的照片,就是經常用於研究有監督機器學習問題的示例:
fig,ax = plt.subplots(5,5,figsize=(5,5)) fig.subplots_adjust(hspace=0,wspace=0) # 從scikit-learn獲取一些人臉照片資料 from sklearn.datasets import fetch_olivetti_faces faces = fetch_olivetti_faces().images for i in range(5): for j in range(5): ax[i,j].xaxis.set_major_locator(plt.NullLocator()) ax[i,j].yaxis.set_major_locator(plt.NullLocator()) ax[i,j].imshow(faces[10 * i + j],cmap="bone")
import matplotlib.pyplot as plt plt.style.use('seaborn-whitegrid') import numpy as np fig,wspace=0) # 從scikit-learn獲取一些人臉照片資料 from sklearn.datasets import fetch_olivetti_faces faces = fetch_olivetti_faces().images for i in range(5): for j in range(5): ax[i,j].xaxis.set_major_locator(plt.NullLocator()) ax[i,j].yaxis.set_major_locator(plt.NullLocator()) ax[i,cmap="bone") plt.show()
需要注意的是,由於每幅人臉圖形預設都有各自的座標軸,然而在這個特殊的視覺化場景中,刻度值(本例中是畫素值)的存在並不能傳達任何有用的資訊,因此需要將定位器設定為空。
3 增減刻度數量
刻度擁擠的圖形
預設刻度標籤有一個問題,就是顯示較小圖形時,通常刻度顯得十分擁擠。我們可以在下圖的網格中看到類似的問題:
fig,ax = plt.subplots(4,4,sharex=True,sharey=True)
自定義刻度數量
尤其是 x 軸,數字幾乎都重疊在一起,辨識起來非常困難。我們可以用 plt.MaxNLocator()
來解決這個問題,通過它可以設定最多需要顯示多少刻度。根據設定的最多刻度數量,Matplotlib 會自動為刻度安排恰當的位置:
# 為每個座標軸設定主要刻度定位器 for axi in ax.flat: axi.xaxis.set_major_locator(plt.MaxNLocator(3)) axi.yaxis.set_major_locator(plt.MaxNLocator(3)) fig
import matplotlib.pyplot as plt plt.style.use('seaborn-whitegrid') import numpy as np fig,sharey=True) # 為每個座標軸設定主要刻度定位器 for axi in ax.flat: axi.xaxis.set_major_locator(plt.MaxNLocator(3)) axi.yaxis.set_major_locator(plt.MaxNLocator(3)) fig plt.show()
這樣圖形就顯得更簡潔了。如果你還想要獲得更多的配置功能,那麼可以試試 plt.MultipleLocator
,我們將在接下來的內容中介紹它。
4 花哨的刻度格式
預設帶整數刻度的圖
Matplotlib 預設的刻度格式可以滿足大部分的需求。雖然預設配置已經很不錯了,但是有時候你可能需要更多的功能,例如下圖中的正弦曲線和餘弦曲線:
# 畫正弦曲線和餘弦曲線 fig,ax = plt.subplots() x = np.linspace(0,3 * np.pi,1000) ax.plot(x,np.sin(x),lw=3,label='Sine') ax.plot(x,np.cos(x),label='Cosine') # 設定網格、圖例和座標軸上下限 ax.grid(True) ax.legend(frameon=False) ax.axis('equal') ax.set_xlim(0,3 * np.pi);
import matplotlib.pyplot as plt plt.style.use('seaborn-whitegrid') import numpy as np # 畫正弦曲線和餘弦曲線 fig,3 * np.pi); plt.show()
在 π / 2 的倍數上顯示刻度
我們可能想稍稍改變一下這幅圖。首先,如果將刻度與網格線畫在 π 的倍數上,圖形會更加自然。可以通過設定一個 MultipleLocator
來實現,它可以將刻度放在你提供的數值的倍數上。為了更好地測量,在 π /4
的倍數上新增主要刻度和次要刻度
ax.xaxis.set_major_locator(plt.MultipleLocator(np.pi / 2)) ax.xaxis.set_minor_locator(plt.MultipleLocator(np.pi / 4)) fig
import matplotlib.pyplot as plt plt.style.use('seaborn-whitegrid') import numpy as np # 畫正弦曲線和餘弦曲線 fig,label='Cosine') # 設定網格、圖例和座標軸上下限 ax.grid(True) ax.legend(frameon=False) ax.axis('equal') ax.xaxis.set_major_locator(plt.MultipleLocator(np.pi / 2)) ax.xaxis.set_minor_locator(plt.MultipleLocator(np.pi / 4)) fig plt.show()
然而,這些刻度標籤看起來有點奇怪:雖然我們知道它們是 π 的倍數,但是用小數表示圓周率不太直觀。因此,我們可以用刻度格式生成器來修改。
自定義刻度標籤
由於沒有內建的格式生成器可以直接解決問題,因此需要用plt.FuncFormatter
來實現,用一個自定義的函式設定不同刻度標籤的顯示
def format_func(value,tick_number): # 找到 π /2的倍數刻度 N = int(np.round(2 * value / np.pi)) if N == 0: return "0" elif N == 1: return r"$\pi/2$" elif N == 2: return r"$\pi$" elif N % 2 > 0: return r"${0}\pi/2$".format(N) else: return r"${0}\pi$".format(N // 2) ax.xaxis.set_major_formatter(plt.FuncFormatter(format_func)) fig
import matplotlib.pyplot as plt plt.style.use('seaborn-whitegrid') import numpy as np # 畫正弦曲線和餘弦曲線 fig,label='Cosine') # 設定網格、圖例和座標軸上下限 ax.grid(True) ax.legend(frameon=False) ax.axis('equal') def format_func(value,tick_number): # 找到 π /2的倍數刻度 N = int(np.round(2 * value / np.pi)) if N == 0: return "0" elif N == 1: return r"$\pi/2$" elif N == 2: return r"$\pi$" elif N % 2 > 0: return r"${0}\pi/2$".format(N) else: return r"${0}\pi$".format(N // 2) ax.xaxis.set_major_formatter(plt.FuncFormatter(format_func)) fig plt.show()
這樣就好看多啦!其實我們已經用了 Matplotlib 支援 LaTeX 的功能,在數學表示式兩側加上美元符號( $
),這樣可以非常方便地顯示數學符號和數學公式。在這個示例中, " $ \pi $
"就表示圓周率符合 π
。
當你準備展示或列印圖形時, plt.FuncFormatter() 不僅可以為自定義圖形刻度提供十分靈活的功能,而且用法非常簡單。
5 格式生成器與定位器小結
前面已經介紹了一些格式生成器與定位器,下面用表格簡單地總結一下內建的格式生成器與定位器選項。關於兩者更詳細的資訊,請參考各自的程式文件或者 Matplotlib 的線上文件。以下的所有類都在 plt 名稱空間內。
定位器類 | 描述 |
---|---|
NullLocator | 無刻度 |
FixedLocator | 刻度位置固定 |
IndexLocator | 用索引作為定位器(如 x = range(len(y))) |
LinearLocator | 從 min 到 max 均勻分佈刻度 |
LogLocator | 從 min 到 max 按對數分佈刻度 |
MultipleLocator | 刻度和範圍都是基數(base)的倍數 |
MaxNLocator | 為最大刻度找到最優位置 |
AutoLocator | (預設)以 MaxNLocator 進行簡單配置 |
AutoMinorLocator | 次要刻度的定位器 |
格式生成器類 | 描述 |
---|---|
NullFormatter | 刻度上無標籤 |
IndexFormatter | 將一組標籤設定為字串 |
FixedFormatter | 手動為刻度設定標籤 |
FuncFormatter | 用自定義函式設定標籤 |
FormatStrFormatter | 為每個刻度值設定字串格式 |
ScalarFormatter | (預設)為標量值設定標籤 |
LogFormatter | 對數座標軸的預設格式生成器 |
到此這篇關於Matplotlib自定義座標軸刻度的實現示例的文章就介紹到這了,更多相關Matplotlib自定義座標軸刻度內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!