8.13 自定義刻度
譯者:飛龍
協(xié)議:CC BY-NC-SA 4.0
本節(jié)是《Python 數(shù)據(jù)科學手冊》(Python Data Science Handbook)的摘錄妨退。
Matplotlib 的默認刻度定位器和格式化程序拦坠,在許多常見情況下通常都足夠了,但對于每個繪圖都不是最佳選擇隔心。本節(jié)將提供幾個刻度位置和格式的示例坎缭,它們調(diào)整你感興趣的特定繪圖類型竟痰。
在我們進入示例之前,我們最好進一步了解 Matplotlib 繪圖的對象層次結(jié)構(gòu)掏呼。Matplotlib 旨在用 Python 對象表示繪圖中出現(xiàn)的所有內(nèi)容:例如坏快,回想一下figure
是繪圖元素所在的邊框。每個 Matplotlib 對象也可以充當子對象的容器:例如憎夷,每個figure
可以包含一個或多個axes
對象莽鸿,它們的每個又包含表示繪圖內(nèi)容的其他對象。
刻度線也不例外拾给。 每個axes
都有屬性xaxis
和yaxis
祥得,它們又具有一些屬性,包括構(gòu)成軸域的直線蒋得,刻度和標簽级及。
主要和次要刻度
在每個軸內(nèi),有主要刻度標記和次要刻度標記的概念额衙。 正如名稱所暗示的那樣饮焦,主要刻度通常更大或更明顯怕吴,而次要刻度通常更小。 默認情況下县踢,Matplotlib 很少使用次要刻度转绷,但是你可以在對數(shù)繪圖中看到它們:
import matplotlib.pyplot as plt
plt.style.use('classic')
%matplotlib inline
import numpy as np
ax = plt.axes(xscale='log', yscale='log')
ax.grid();
我們在這里看到每個主刻度線顯示為一個大刻度線和一個標簽,而每個次刻度線顯示為一個沒有標簽的較小刻度線硼啤。
這些刻度屬性 - 位置和標簽 - 也就是說议经,可以通過設置每個軸的formatter
和locator
對象來定制。 讓我們檢查剛剛展示的繪圖的x
軸:
print(ax.xaxis.get_major_locator())
print(ax.xaxis.get_minor_locator())
'''
<matplotlib.ticker.LogLocator object at 0x10dbaf630>
<matplotlib.ticker.LogLocator object at 0x10dba6e80>
'''
print(ax.xaxis.get_major_formatter())
print(ax.xaxis.get_minor_formatter())
'''
<matplotlib.ticker.LogFormatterMathtext object at 0x10db8dbe0>
<matplotlib.ticker.NullFormatter object at 0x10db9af60>
'''
我們看到主要和次要刻度標簽的位置都由LogLocator
指定(這對于對數(shù)圖是有意義的)丙曙。 但是爸业,次要刻度的標簽格式為NullFormatter
:這表示不會顯示任何標簽。我們現(xiàn)在將展示一些為各種圖設置這些定位器和格式化器的示例亏镰。
隱藏刻度或標簽
也許最常見的刻度/標簽格式化操作是隱藏刻度或標簽。這可以使用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())
請注意索抓,我們已經(jīng)從x
軸移除了標簽(但保留了刻度線/網(wǎng)格線),并從y
軸中刪除了刻度線(以及標簽)毯炮。
在許多情況下逼肯,不顯示刻度可能很有用 - 例如,當你想要顯示圖像網(wǎng)格的時候桃煎。
例如篮幢,考慮下圖,它包含不同的面部圖像为迈,這是監(jiān)督機器學習問題中常用的一個例子(例如三椿,參見“深入:支持向量機”):
fig, ax = plt.subplots(5, 5, figsize=(5, 5))
fig.subplots_adjust(hspace=0, wspace=0)
# 從 sklearn 獲取一些人臉數(shù)據(jù)
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")
請注意,每個圖像都有自己的軸域葫辐,我們將定位器設置為null
搜锰,因為刻度值(在這種情況下為像素數(shù))不會傳達這個特定可視化的相關(guān)信息。
減少或增加刻度數(shù)量
默認設置的一個常見問題是耿战,較小的子圖最終會擁有密集的標簽蛋叼。我們可以在這里顯示的繪圖網(wǎng)格中看到它:
fig, ax = plt.subplots(4, 4, sharex=True, sharey=True)
特別是對于x
刻度,數(shù)字幾乎重疊并使它們很難看清剂陡。我們可以用plt.MaxNLocator()
解決這個問題狈涮,它允許我們指定要顯示的最大刻度數(shù)。給定此最大數(shù)量鸭栖,Matplotlib 將使用內(nèi)部邏輯來選擇特定的刻度位置:
# 對于每個軸歌馍,設置 x 和 y 主要定位器
for axi in ax.flat:
axi.xaxis.set_major_locator(plt.MaxNLocator(3))
axi.yaxis.set_major_locator(plt.MaxNLocator(3))
fig
這使事情變得更加干凈。 如果你想要更多地控制等間隔的刻度位置纤泵,你也可以使用plt.MultipleLocator
骆姐,我們將在下一節(jié)討論镜粤。
花式刻度格式
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), lw=3, label='Cosine')
# 配置網(wǎng)格,圖例和限制
ax.grid(True)
ax.legend(frameon=False)
ax.axis('equal')
ax.set_xlim(0, 3 * np.pi);
我們可能想做一些改變带射。 首先同规,以 π 的倍數(shù)的刻度線和網(wǎng)格線來區(qū)分這些數(shù)據(jù)更加自然。 我們可以通過設置MultipleLocator
來實現(xiàn)窟社,它可以在你提供的數(shù)字的倍數(shù)處券勺,設置刻度線。 為了更好地衡量灿里,我們將以π/4
的倍數(shù)添加主要和次要刻度:
ax.xaxis.set_major_locator(plt.MultipleLocator(np.pi / 2))
ax.xaxis.set_minor_locator(plt.MultipleLocator(np.pi / 4))
fig
但現(xiàn)在這些刻度標簽看起來有點傻:我們可以看到它們是 π 的倍數(shù)关炼,但十進制表示并沒有立即傳達這一點。要解決這個問題匣吊,我們可以更改刻度格式化器儒拂。對于我們想要做的事情,沒有內(nèi)置格式化器色鸳,所以我們改為使用plt.FuncFormatter
社痛,它接受用戶定義的函數(shù),對刻度輸出進行細粒度控制:
def format_func(value, tick_number):
# 尋找 pi/2 倍數(shù)的數(shù)字
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
這要好得多命雀! 請注意蒜哀,我們已經(jīng)使用了 Matplotlib 的 LaTeX 支持,通過將字符串括在美元符號中來指定吏砂。 這對于顯示數(shù)學符號和公式非常方便:在這種情況下撵儿,$\pi$
顯示為希臘字符π
。
plt.FuncFormatter()
提供繪圖刻度外觀的極細粒度控制赊抖,并且在準備繪圖用于演示或發(fā)布時非常方便统倒。
格式化器和定位器的總結(jié)
我們已經(jīng)提到了一些可用的格式化器和定位器。我們將簡要列出所有內(nèi)置定位器和格式化器的選項來結(jié)束本節(jié)氛雪。 對于其中任何內(nèi)容的更多信息房匆,請參閱文檔字符串或 Matplotlib 在線文檔。plt
命名空間中提供以下東西:
定位器類 | 描述 |
---|---|
NullLocator |
沒有刻度 |
FixedLocator |
刻度定位器是固定的 |
IndexLocator |
索引繪圖的定位器(也就是报亩,其中x = range(len(y)) ) |
LinearLocator |
等間隔的刻度浴鸿,從最小值到最大值 |
LogLocator |
對數(shù)刻度,從最小值到最大值 |
MultipleLocator |
刻度和范圍是基數(shù)的倍數(shù) |
MaxNLocator |
在不錯的位置尋找小于等于最大值的刻度數(shù) |
AutoLocator |
(默認)帶有簡單默認值的MaxNLocator
|
AutoMinorLocator |
用于次要刻度的定位器 |
格式化器類 | 描述 |
---|---|
NullFormatter |
刻度上沒有標簽 |
IndexFormatter |
從一列標簽中設置字符串 |
FixedFormatter |
手動為標簽設置字符串 |
FuncFormatter |
使用用戶定義的函數(shù)設置標簽 |
FormatStrFormatter |
對每個值使用格式化字符串 |
ScalarFormatter |
(默認)用于標量值的格式化器 |
LogFormatter |
對數(shù)軸域的默認格式化器 |
我們將在本書的其余部分看到更多這些例子弦追。