數(shù)據(jù)科學(xué) IPython 筆記本 8.13 自定義刻度

8.13 自定義刻度

原文:Customizing Ticks

譯者:飛龍

協(xié)議:CC BY-NC-SA 4.0

本節(jié)是《Python 數(shù)據(jù)科學(xué)手冊》(Python Data Science Handbook)的摘錄。

Matplotlib 的默認(rèn)刻度定位器和格式化程序,在許多常見情況下通常都足夠了,但對于每個繪圖都不是最佳選擇。本節(jié)將提供幾個刻度位置和格式的示例,它們調(diào)整你感興趣的特定繪圖類型。

在我們進(jìn)入示例之前,我們最好進(jìn)一步了解 Matplotlib 繪圖的對象層次結(jié)構(gòu)。Matplotlib 旨在用 Python 對象表示繪圖中出現(xiàn)的所有內(nèi)容:例如,回想一下figure是繪圖元素所在的邊框。每個 Matplotlib 對象也可以充當(dāng)子對象的容器:例如,每個figure可以包含一個或多個axes對象,它們的每個又包含表示繪圖內(nèi)容的其他對象。

刻度線也不例外。 每個axes都有屬性xaxisyaxis,它們又具有一些屬性,包括構(gòu)成軸域的直線,刻度和標(biāo)簽。

主要和次要刻度

在每個軸內(nèi),有主要刻度標(biāo)記和次要刻度標(biāo)記的概念。 正如名稱所暗示的那樣,主要刻度通常更大或更明顯,而次要刻度通常更小。 默認(rèn)情況下,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();
png

我們在這里看到每個主刻度線顯示為一個大刻度線和一個標(biāo)簽,而每個次刻度線顯示為一個沒有標(biāo)簽的較小刻度線。

這些刻度屬性 - 位置和標(biāo)簽 - 也就是說,可以通過設(shè)置每個軸的formatterlocator對象來定制。 讓我們檢查剛剛展示的繪圖的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>
'''

我們看到主要和次要刻度標(biāo)簽的位置都由LogLocator指定(這對于對數(shù)圖是有意義的)。 但是,次要刻度的標(biāo)簽格式為NullFormatter:這表示不會顯示任何標(biāo)簽。我們現(xiàn)在將展示一些為各種圖設(shè)置這些定位器和格式化器的示例。

隱藏刻度或標(biāo)簽

也許最常見的刻度/標(biāo)簽格式化操作是隱藏刻度或標(biāo)簽。這可以使用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())
png

請注意,我們已經(jīng)從x軸移除了標(biāo)簽(但保留了刻度線/網(wǎng)格線),并從y軸中刪除了刻度線(以及標(biāo)簽)。
在許多情況下,不顯示刻度可能很有用 - 例如,當(dāng)你想要顯示圖像網(wǎng)格的時候。
例如,考慮下圖,它包含不同的面部圖像,這是監(jiān)督機(jī)器學(xué)習(xí)問題中常用的一個例子(例如,參見“深入:支持向量機(jī)”):

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")
png

請注意,每個圖像都有自己的軸域,我們將定位器設(shè)置為null,因?yàn)榭潭戎担ㄔ谶@種情況下為像素數(shù))不會傳達(dá)這個特定可視化的相關(guān)信息。

減少或增加刻度數(shù)量

默認(rèn)設(shè)置的一個常見問題是,較小的子圖最終會擁有密集的標(biāo)簽。我們可以在這里顯示的繪圖網(wǎng)格中看到它:

fig, ax = plt.subplots(4, 4, sharex=True, sharey=True)
png

特別是對于x刻度,數(shù)字幾乎重疊并使它們很難看清。我們可以用plt.MaxNLocator()解決這個問題,它允許我們指定要顯示的最大刻度數(shù)。給定此最大數(shù)量,Matplotlib 將使用內(nèi)部邏輯來選擇特定的刻度位置:

# 對于每個軸,設(shè)置 x 和 y 主要定位器
for axi in ax.flat:
    axi.xaxis.set_major_locator(plt.MaxNLocator(3))
    axi.yaxis.set_major_locator(plt.MaxNLocator(3))
fig
png

這使事情變得更加干凈。 如果你想要更多地控制等間隔的刻度位置,你也可以使用plt.MultipleLocator,我們將在下一節(jié)討論。

花式刻度格式

Matplotlib 的默認(rèn)刻度格式可能會有很多不足之處:它可以作為一個泛用的默認(rèn)值,但有時你還想做更多的事情??紤]一下正弦和余弦的繪圖:

# 繪制正弦和余弦曲線
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);
png

我們可能想做一些改變。 首先,以 π 的倍數(shù)的刻度線和網(wǎng)格線來區(qū)分這些數(shù)據(jù)更加自然。 我們可以通過設(shè)置MultipleLocator來實(shí)現(xiàn),它可以在你提供的數(shù)字的倍數(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
png

但現(xiàn)在這些刻度標(biāo)簽看起來有點(diǎn)傻:我們可以看到它們是 π 的倍數(shù),但十進(jìn)制表示并沒有立即傳達(dá)這一點(diǎn)。要解決這個問題,我們可以更改刻度格式化器。對于我們想要做的事情,沒有內(nèi)置格式化器,所以我們改為使用plt.FuncFormatter,它接受用戶定義的函數(shù),對刻度輸出進(jìn)行細(xì)粒度控制:

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
png

這要好得多! 請注意,我們已經(jīng)使用了 Matplotlib 的 LaTeX 支持,通過將字符串括在美元符號中來指定。 這對于顯示數(shù)學(xué)符號和公式非常方便:在這種情況下,$\pi$顯示為希臘字符π。

plt.FuncFormatter()提供繪圖刻度外觀的極細(xì)粒度控制,并且在準(zhǔn)備繪圖用于演示或發(fā)布時非常方便。

格式化器和定位器的總結(jié)

我們已經(jīng)提到了一些可用的格式化器和定位器。我們將簡要列出所有內(nèi)置定位器和格式化器的選項(xiàng)來結(jié)束本節(jié)。 對于其中任何內(nèi)容的更多信息,請參閱文檔字符串或 Matplotlib 在線文檔。plt命名空間中提供以下東西:

定位器類 描述
NullLocator 沒有刻度
FixedLocator 刻度定位器是固定的
IndexLocator 索引繪圖的定位器(也就是,其中x = range(len(y))
LinearLocator 等間隔的刻度,從最小值到最大值
LogLocator 對數(shù)刻度,從最小值到最大值
MultipleLocator 刻度和范圍是基數(shù)的倍數(shù)
MaxNLocator 在不錯的位置尋找小于等于最大值的刻度數(shù)
AutoLocator (默認(rèn))帶有簡單默認(rèn)值的MaxNLocator
AutoMinorLocator 用于次要刻度的定位器
格式化器類 描述
NullFormatter 刻度上沒有標(biāo)簽
IndexFormatter 從一列標(biāo)簽中設(shè)置字符串
FixedFormatter 手動為標(biāo)簽設(shè)置字符串
FuncFormatter 使用用戶定義的函數(shù)設(shè)置標(biāo)簽
FormatStrFormatter 對每個值使用格式化字符串
ScalarFormatter (默認(rèn))用于標(biāo)量值的格式化器
LogFormatter 對數(shù)軸域的默認(rèn)格式化器

我們將在本書的其余部分看到更多這些例子。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容