Matplotlib 提供了豐富的 API,讓開發者可以高度客製化圖表的樣式,其中 Tick 標籤的格式化與樣式設定是圖表呈現的關鍵環節。本文將深入探討如何使用 Matplotlib 的 annotate 函式新增標註,以及如何客製化 Tick 標籤的位置、格式和樣式,包含隱藏軸標籤、顯示圖片網格、調整刻度數量等技巧。同時,我們將介紹 Locator 和 Formatter 的使用,以及如何利用它們來精確控制 Tick 標籤的呈現方式,讓圖表更具可讀性和美觀性。此外,文章也涵蓋了 Matplotlib 的組態檔案和樣式表的使用,讓讀者可以更有效率地管理圖表風格,並快速切換不同的視覺化風格。

基本使用

以下是使用annotate函式新增標註的基本示例:

import matplotlib.pyplot as plt
import numpy as np

fig, ax = plt.subplots()
x = np.linspace(0, 20, 1000)
ax.axis('equal')
ax.annotate('local maximum', xy=(6.28, 1), xytext=(10, 4),
            arrowprops=dict(facecolor='black', shrink=0.05))
ax.annotate('local minimum', xy=(5 * np.pi, -1), xytext=(2, -6),
            arrowprops=dict(arrowstyle="->",
                            connectionstyle="angle3,angleA=0,angleB=-90"))

在這個示例中,我們使用annotate函式新增兩個標註:一個是「local maximum」,另一個是「local minimum」。我們使用xy引數指定標註的位置,使用xytext引數指定箭頭的起點。同時,我們使用arrowprops引數自定義箭頭的樣式。

進階使用

以下是使用annotate函式新增更多複雜標註的示例:

import matplotlib.pyplot as plt
import numpy as np

fig, ax = plt.subplots(figsize=(12, 4))
births_by_date.plot(ax=ax)

# Add labels to the plot
ax.annotate("New Year's Day", xy=('2012-1-1', 4100), xycoords='data',
            xytext=(50, -30), textcoords='offset points',
            arrowprops=dict(arrowstyle="->",
                            connectionstyle="arc3,rad=-0.2"))
ax.annotate("Independence Day", xy=('2012-7-4', 4250),
            xycoords='data',
            bbox=dict(boxstyle="round", fc="none", ec="gray"),
            xytext=(10, -40), textcoords='offset points', ha='center',
            arrowprops=dict(arrowstyle="->"))
ax.annotate('Labor Day Weekend', xy=('2012-9-4', 4850),
            xycoords='data',
            ha='center', xytext=(0, -20), textcoords='offset points')
ax.annotate('', xy=('2012-9-1', 4850), xytext=('2012-9-7', 4850),
            xycoords='data', textcoords='data',
            arrowprops={'arrowstyle': '|-|,widthA=0.2,widthB=0.2', })
ax.annotate('Halloween', xy=('2012-10-31', 4600), xycoords='data',
            xytext=(-80, -40), textcoords='offset points',
            arrowprops=dict(arrowstyle="fancy",
                            fc="0.6", ec="none",
                            connectionstyle="angle3,angleA=0,angleB=-90"))

在這個示例中,我們使用annotate函式新增多個標註,每個標註都有不同的樣式和連線方式。同時,我們使用bbox引數新增背景框,使用ha引數指定水平對齊方式。

內容解密:

在上面的示例中,我們使用annotate函式新增標註和箭頭。這個函式提供了許多選項,讓您可以自定義箭頭的樣式、顏色和連線方式。同時,我們使用xy引數指定標註的位置,使用xytext引數指定箭頭的起點。透過這些選項,您可以建立出各種不同的標註和箭頭樣式。

圖表翻譯:

以下是上述程式碼生成的圖表: 在這個圖表中,我們使用Plantuml語法建立了一個簡單的流程圖,展示了不同日期之間的關係。同時,我們使用arrowstyle引數自定義箭頭的樣式,使用connectionstyle引數指定連線方式。

個人化 Tick 樣式

Matplotlib 的預設 Tick 位置和格式通常能滿足大多數情況下的需求,但在某些情況下,可能需要根據特定的繪圖型別進行調整。這一章將提供多個調整 Tick 位置和格式的例子。

Tick 的物件階層

在 Matplotlib 中,每個元素都有一個對應的 Python 物件。例如,Figure 是繪圖的邊界框,Axes 是繪圖區域的容器,包含了繪圖的內容。每個 Axes 物件都有 xaxis 和 yaxis 屬性,這些屬性包含了 Tick 的所有屬性,包括線條、Tick 標籤和軸標籤。

主要和次要 Tick

在每個 Axes 中,有主要 Tick 和次要 Tick 的概念。主要 Tick 通常更大或更明顯,而次要 Tick 則通常更小。Matplotlib 很少使用次要 Tick,但在對數繪圖中可以看到它們(見圖 33-1)。

import matplotlib.pyplot as plt
import numpy as np

# 設定繪圖樣式
plt.style.use('classic')

# 建立一個對數繪圖
ax = plt.axes(xscale='log', yscale='log')
ax.set(xlim=(1, 1E3), ylim=(1, 1E3))
ax.grid(True)

個人化 Tick 樣式

Tick 的位置和標籤可以透過設定 Locator 和 Formatter 來個人化。Locator 用於設定 Tick 的位置,Formatter 用於設定 Tick 標籤的格式。

# 取得主要 Tick 的 Locator 和 Formatter
print(ax.xaxis.get_major_locator())
print(ax.xaxis.get_major_formatter())

# 取得次要 Tick 的 Locator 和 Formatter
print(ax.xaxis.get_minor_locator())
print(ax.xaxis.get_minor_formatter())

隱藏 Tick 或標籤

可以使用 plt.NullLocatorplt.NullFormatter 來隱藏 Tick 或標籤。

# 建立一個新的 Axes
ax = plt.axes()

# 隱藏 x 軸的 Tick 和標籤
ax.xaxis.set_major_locator(plt.NullLocator())
ax.xaxis.set_major_formatter(plt.NullFormatter())

圖表翻譯:

此圖示為隱藏 x 軸的 Tick 和標籤的效果。透過設定 NullLocatorNullFormatter,可以隱藏 x 軸的 Tick 和標籤。

內容解密:

上述程式碼示範瞭如何隱藏 x 軸的 Tick 和標籤。透過設定 NullLocatorNullFormatter,可以實作隱藏 x 軸的 Tick 和標籤的效果。此外,還可以透過設定其他 Locator 和 Formatter 來個人化 Tick 樣式。

隱藏軸標籤和刻度

在某些情況下,隱藏軸標籤和刻度可以使圖表更清晰、更容易閱讀。例如,當您想要顯示一組圖片時,隱藏刻度和標籤可以使圖表看起來更整潔。

import matplotlib.pyplot as plt
import numpy as np

# 建立一個隨機資料的圖表
rng = np.random.default_rng()
fig, ax = plt.subplots()
ax.plot(rng.random(50))

# 顯示網格
ax.grid()

# 隱藏y軸的刻度
ax.yaxis.set_major_locator(plt.NullLocator())

# 隱藏x軸的標籤
ax.xaxis.set_major_formatter(plt.NullFormatter())

plt.show()

顯示圖片網格

當您想要顯示一組圖片時,隱藏刻度和標籤可以使圖表看起來更整潔。以下是使用Scikit-Learn的 Olivetti Faces資料集建立一個圖片網格的例子。

import matplotlib.pyplot as plt
from sklearn.datasets import fetch_olivetti_faces

# 載入 Olivetti Faces 資料集
faces = fetch_olivetti_faces().images

# 建立一個 5x5 的子圖表
fig, ax = plt.subplots(5, 5, figsize=(5, 5))

# 調整子圖表的間距
fig.subplots_adjust(hspace=0, wspace=0)

# 對於每個子圖表,隱藏刻度和標籤,然後顯示圖片
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='binary_r')

plt.show()

調整刻度數量

在某些情況下,預設的刻度數量可能會導致標籤過於擁擠。以下是使用 plt.MaxNLocator 調整刻度數量的例子。

import matplotlib.pyplot as plt

# 建立一個 4x4 的子圖表
fig, ax = plt.subplots(4, 4, sharex=True, sharey=True)

# 對於每個子圖表,設定 x 和 y 軸的最大刻度數量為 3
for axi in ax.flat:
    axi.xaxis.set_major_locator(plt.MaxNLocator(3))
    axi.yaxis.set_major_locator(plt.MaxNLocator(3))

plt.show()

內容解密:

  • ax.plot(rng.random(50)) 建立了一個隨機資料的圖表。
  • ax.grid() 顯示了網格。
  • ax.yaxis.set_major_locator(plt.NullLocator()) 隱藏了 y 軸的刻度。
  • ax.xaxis.set_major_formatter(plt.NullFormatter()) 隱藏了 x 軸的標籤。
  • fig, ax = plt.subplots(5, 5, figsize=(5, 5)) 建立了一個 5x5 的子圖表。
  • fig.subplots_adjust(hspace=0, wspace=0) 調整了子圖表的間距。
  • 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='binary_r') 顯示了圖片。
  • axi.xaxis.set_major_locator(plt.MaxNLocator(3))axi.yaxis.set_major_locator(plt.MaxNLocator(3)) 設定了 x 和 y 軸的最大刻度數量為 3。

圖表翻譯:

此圖表展示了一個 4x4 的子圖表,每個子圖表都有調整過的刻度數量。透過使用 plt.MaxNLocator,我們可以設定最大刻度數量,以避免標籤過於擁擠。這使得圖表更容易閱讀和理解。

自訂刻度標籤格式

Matplotlib 的預設刻度標籤格式可能不夠理想:它作為一個廣泛的預設設定,工作得很好,但有時您可能想要做一些不同的事情。讓我們考慮一下對於正弦和餘弦曲線的繪製(見圖 33-6)。

import matplotlib.pyplot as plt
import numpy as np

# 繪製正弦和餘弦曲線
fig, ax = plt.subplots()
x = np.linspace(0, 3 * np.pi, 1000)
ax.plot(x, np.sin(x), lw=3, label='正弦')
ax.plot(x, np.cos(x), lw=3, label='餘弦')

# 設定網格、圖例和限制
ax.grid(True)
ax.legend(frameon=False)
ax.axis('equal')
ax.set_xlim(0, 3 * np.pi)

圖 33-6 顯示了預設的刻度標籤格式。現在,我們想要對這個圖表進行一些修改。首先,對於這些資料來說,更自然的做法是以 π 的倍數來間隔刻度和網格線。我們可以使用 plt.MultipleLocator 來實作這一點,它可以在指定的倍數位置放置刻度。為了更好的效果,我們將在 π/2 和 π/4 的倍數位置新增主要和次要刻度(見圖 33-7)。

# 設定主要和次要刻度位置
ax.xaxis.set_major_locator(plt.MultipleLocator(np.pi / 2))
ax.xaxis.set_minor_locator(plt.MultipleLocator(np.pi / 4))

但是現在,這些刻度標籤看起來有一點愚蠢:我們可以看到它們是 π 的倍數,但十進製表示法並不能立即傳達這一點。為瞭解決這個問題,我們可以更改刻度格式器。沒有內建的格式器可以做到我們想要的,所以我們將使用 plt.FuncFormatter,它接受一個使用者定義的函式,提供對刻度輸出的細粒度控制(見圖 33-8)。

# 定義一個使用者定義的函式來格式化刻度標籤
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 fr"${N//2}\pi$"
    else:
        return fr"${N//2}\pi/2$"

# 將使用者定義的函式應用於 x 軸的刻度標籤
ax.xaxis.set_major_formatter(plt.FuncFormatter(format_func))

內容解密:

上述程式碼首先匯入必要的函式庫,然後建立了一個繪圖區域和一組子圖。接下來,它使用 np.linspace 生成 x 值,並使用 ax.plot 繪製正弦和餘弦曲線。然後,它設定網格、圖例和限制。為了自訂刻度標籤格式,它使用 plt.MultipleLocator 設定主要和次要刻度位置,然後定義了一個使用者定義的函式 format_func 來格式化刻度標籤。最後,它將這個使用者定義的函式應用於 x 軸的刻度標籤。

圖表翻譯:

此圖表顯示了使用 plt.MultipleLocatorplt.FuncFormatter 自訂刻度標籤格式的效果。x 軸的刻度標籤現在以 π 的倍數表示,且格式化為更易於理解的形式。這種自訂格式化可以使圖表更具可讀性和美觀性。

自訂Tick標籤格式

在Matplotlib中,使用FuncFormatter可以自訂Tick標籤的格式。例如,下面的程式碼使用LaTeX支援來顯示π符號:

import matplotlib.pyplot as plt
import numpy as np

# 定義一個函式來格式化Tick標籤
def format_func(x, pos):
    N = int(np.round(x / np.pi))
    if N == 0:
        return r"$0$"
    elif N == 1:
        return r"$\pi/2$"
    elif N == 2:
        return r"$\pi$"
    elif N % 2 > 0:
        return rf"${N}\pi/2$"
    else:
        return rf"${N // 2}\pi$"

# 建立一個圖表
fig, ax = plt.subplots()

# 設定x軸的Tick標籤格式
ax.xaxis.set_major_formatter(plt.FuncFormatter(format_func))

# 顯示圖表
plt.show()

這個程式碼會產生一個圖表,x軸的Tick標籤使用LaTeX支援來顯示π符號。

Matplotlib的Locator和Formatter選項

Matplotlib提供了多種Locator和Formatter選項,可以用來自訂Tick標籤的位置和格式。下面是部分可用的Locator和Formatter選項:

Locator選項

Locator類別描述
NullLocator沒有Tick標籤
FixedLocatorTick標籤位置固定
IndexLocator用於索引圖表(例如,x = range(len(y)))
LinearLocator線性Tick標籤

Formatter選項

Formatter類別描述
NullFormatter沒有Tick標籤
ScalarFormatter標量格式器
LogFormatter對數格式器
FuncFormatter自訂函式格式器

更多關於這些選項的資訊,可以參考Matplotlib的檔案或是使用help函式來檢視相關的幫助資訊。

自動化 ticks 和格式化工具

在資料視覺化中,適當的 ticks 和格式化設定能夠大大提高圖表的可讀性和美觀度。Matplotlib 提供了多種 ticks 位置和格式化的工具,讓使用者能夠輕鬆地控制圖表的呈現方式。

Ticks 位置設定

Matplotlib 提供了多種 ticks 位置設定工具,包括:

  • LinearLocator:均勻分佈的 ticks,從最小值到最大值。
  • LogLocator:對數均勻分佈的 ticks,從最小值到最大值。
  • MultipleLocator:ticks 和範圍是基數的倍數。
  • MaxNLocator:找到最多數量的 ticks 在良好的位置。
  • AutoLocator (Default):MaxNLocator 的簡單預設設定。

此外,Matplotlib 還提供了 AutoMinorLocator,用於設定次要 ticks 的位置。

格式化工具

除了 ticks 位置設定,Matplotlib 還提供了多種格式化工具,包括:

  • NullFormatter:不顯示 ticks 標籤。
  • IndexFormatter:從標籤列表設定字串。
  • FixedFormatter:使用固定字串格式化 ticks 標籤。

以下是使用 Matplotlib 的 formatter 的一個例子:

import matplotlib.pyplot as plt
import matplotlib.ticker as ticker

# 建立一個 figure 和 axis
fig, ax = plt.subplots()

# 設定 x 軸的 ticks 位置
ax.xaxis.set_major_locator(ticker.MultipleLocator(10))

# 設定 x 軸的 ticks 格式化
ax.xaxis.set_major_formatter(ticker.IndexFormatter(['A', 'B', 'C', 'D']))

# 顯示圖表
plt.show()

在這個例子中,我們使用 MultipleLocator 設定 x 軸的 ticks 位置為 10 的倍數,並使用 IndexFormatter 設定 x 軸的 ticks 格式化為 [‘A’, ‘B’, ‘C’, ‘D’]。

內容解密:

上述程式碼中,我們首先匯入必要的模組,包括 matplotlib.pyplotmatplotlib.ticker。然後,我們建立一個 figure 和 axis,並設定 x 軸的 ticks 位置和格式化。最後,我們顯示圖表。

這個例子展示瞭如何使用 Matplotlib 的 ticks 位置設定和格式化工具來控制圖表的呈現方式。透過這些工具,使用者可以輕鬆地建立出美觀且富有意義的圖表。

圖表翻譯:

這個圖表展示了 Matplotlib 的 ticks 位置設定和格式化工具之間的關係。使用者可以根據自己的需求選擇合適的工具來控制圖表的呈現方式。

個人化matplotlib風格

在前面的章節中,我們已經學習瞭如何調整matplotlib的各個元素來建立一個漂亮的圖表。然而,matplotlib還提供了一種更高階的方式來控制圖表的風格,即透過組態檔案和樣式表。

組態檔案

matplotlib的組態檔案是一種簡單的文字檔案,包含了圖表的各個引數設定。透過修改這個檔案,可以全域性地改變matplotlib的行為和外觀。例如,可以設定預設的字型、顏色、線寬等。

樣式表

樣式表是matplotlib提供的一種預先定義的風格集合。透過選擇不同的樣式表,可以快速地改變圖表的外觀。matplotlib提供了多種內建樣式表,包括「classic」、「seaborn」、「ggplot」等。

自定義樣式

除了使用內建樣式表外,還可以自定義自己的樣式。這可以透過建立一個新的樣式表檔案來實作。樣式表檔案是一種簡單的文字檔案,包含了圖表的各個引數設定。

示例

下面是一個示例,展示瞭如何使用matplotlib的樣式表來改變圖表的外觀:

import matplotlib.pyplot as plt
import numpy as np

# 使用「classic」樣式表
plt.style.use('classic')

# 生成一些隨機資料
x = np.random.randn(1000)

# 繪製一個直方圖
plt.hist(x)

這將生成一個預設風格的直方圖。現在,讓我們改變一下樣式表,看看效果:

# 使用「seaborn」樣式表
plt.style.use('seaborn')

# 繪製另一個直方圖
plt.hist(x)

這將生成一個具有不同風格的直方圖。

內容解密:

  • plt.style.use('classic'):設定matplotlib的樣式表為「classic」。
  • plt.hist(x):繪製一個直方圖。
  • np.random.randn(1000):生成1000個隨機資料。

圖表翻譯:

下面是使用Plantuml語法繪製的流程圖,展示了matplotlib的樣式表如何影響圖表的外觀:

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

title Matplotlib圖表Tick標籤格式與樣式進階技巧

package "資料視覺化流程" {
    package "資料準備" {
        component [資料載入] as load
        component [資料清洗] as clean
        component [資料轉換] as transform
    }

    package "圖表類型" {
        component [折線圖 Line] as line
        component [長條圖 Bar] as bar
        component [散佈圖 Scatter] as scatter
        component [熱力圖 Heatmap] as heatmap
    }

    package "美化輸出" {
        component [樣式設定] as style
        component [標籤註解] as label
        component [匯出儲存] as export
    }
}

load --> clean --> transform
transform --> line
transform --> bar
transform --> scatter
transform --> heatmap
line --> style --> export
bar --> label --> export

note right of scatter
  探索變數關係
  發現異常值
end note

@enduml

這個流程圖展示了matplotlib的樣式表如何影響圖表的外觀,並提供了選擇不同樣式表的選項。

深入剖析 Matplotlib 的客製化圖表元素

從底層架構到高階應用的全面檢視顯示,Matplotlib 提供了豐富的 API,允許開發者對圖表元素進行精細的客製化,從簡單的標註到複雜的 Tick 格式,幾乎涵蓋了所有圖表元件。本文深入探討了 Matplotlib 的 annotate 函式、Tick 物件階層、Locator 和 Formatter 的使用,以及如何客製化 Tick 標籤、隱藏軸元素、顯示圖片網格和調整刻度數量。多維比較分析顯示,相較於其他 Python 視覺化函式庫,Matplotlib 在靈活性方面更勝一籌,尤其在處理複雜的科學視覺化需求時,其高度客製化的能力更顯重要。

然而,Matplotlib 的靈活性也帶來了更高的學習成本。對於初學者而言,掌握眾多的 API 和引數設定可能具有一定挑戰性。此外,在處理大量資料時,Matplotlib 的效能表現可能不如一些專注於高效能繪圖的函式庫。技術限制深析指出,Matplotlib 的繪圖流程主要根據 CPU 計算,這在處理大規模資料集或需要即時互動的場景下可能成為瓶頸。

展望未來,Matplotlib 將持續發展,並與其他 Python 資料科學工具鏈更緊密地整合。預計未來版本將更注重效能最佳化,並可能引入 GPU 加速等技術,以提升大規模資料處理能力。同時,隨著互動式資料視覺化需求的增長,Matplotlib 也將在互動式繪圖和動畫方面持續改進。玄貓認為,Matplotlib 作為 Python 生態系統中不可或缺的視覺化工具,其高度客製化的能力和不斷演進的特性,使其在未來仍將保持強勁的競爭力,並在科學研究、資料分析和機器學習等領域持續發揮重要作用。對於追求圖表精細控制和高度客製化的開發者而言,深入學習和掌握 Matplotlib 的 API 至關重要。