繪圖的生命週期#

本教學旨在展示使用 Matplotlib 進行單一視覺化的開始、中間和結束。我們將從一些原始資料開始,並以儲存客製化視覺化的圖形結束。在此過程中,我們嘗試強調一些使用 Matplotlib 的整潔功能和最佳實踐。

注意

本教學改編自 Chris Moffitt 的這篇出色的部落格文章。由 Chris Holdgraf 轉化為本教學。

關於顯式與隱式介面的說明#

Matplotlib 有兩個介面。關於顯式和隱式介面之間權衡的說明,請參閱Matplotlib 應用程式介面 (API)

在顯式物件導向 (OO) 介面中,我們直接使用 axes.Axes 的實例,在 figure.Figure 的實例中建立視覺化。在受 MATLAB 啟發和建模的隱式介面中,我們使用一個封裝在 pyplot 模組中的全域基於狀態的介面,來繪製到「當前 Axes」。有關 pyplot 介面的更深入介紹,請參閱pyplot 教學

大多數術語都很直觀,但要記住的主要事情是

  • Figure 是最終的影像,可能包含一個或多個 Axes

  • Axes 代表單獨的繪圖(不要與

    Axis 混淆,它指的是繪圖的 x 軸、y 軸或 z 軸)。

我們直接從 Axes 呼叫繪圖的方法,這讓我們在客製化繪圖方面擁有更大的彈性和能力。

注意

一般而言,繪圖時請使用顯式介面,而不是隱式 pyplot 介面。

我們的資料#

我們將使用本教學所改編的文章中的資料。它包含許多公司的銷售資訊。

import matplotlib.pyplot as plt
import numpy as np

data = {'Barton LLC': 109438.50,
        'Frami, Hills and Schmidt': 103569.59,
        'Fritsch, Russel and Anderson': 112214.71,
        'Jerde-Hilpert': 112591.43,
        'Keeling LLC': 100934.30,
        'Koepp Ltd': 103660.54,
        'Kulas Inc': 137351.96,
        'Trantow-Barrows': 123381.38,
        'White-Trantow': 135841.99,
        'Will LLC': 104437.60}
group_data = list(data.values())
group_names = list(data.keys())
group_mean = np.mean(group_data)

開始#

此資料自然地以長條圖形式視覺化,每個群組一個長條。要使用物件導向方法執行此操作,我們首先產生 figure.Figureaxes.Axes 的實例。Figure 就像畫布,而 Axes 是該畫布的一部分,我們將在其中進行特定的視覺化。

注意

圖形可以有多個 Axes。有關如何執行此操作的資訊,請參閱緊密佈局教學

lifecycle

現在我們有了 Axes 實例,就可以在其上繪圖了。

lifecycle

控制樣式#

Matplotlib 中有許多樣式可供選擇,以便您可以根據自己的需求調整視覺化效果。要查看樣式列表,我們可以使用 style

['Solarize_Light2', '_classic_test_patch', '_mpl-gallery', '_mpl-gallery-nogrid', 'bmh', 'classic', 'dark_background', 'fast', 'fivethirtyeight', 'ggplot', 'grayscale', 'petroff10', 'seaborn-v0_8', 'seaborn-v0_8-bright', 'seaborn-v0_8-colorblind', 'seaborn-v0_8-dark', 'seaborn-v0_8-dark-palette', 'seaborn-v0_8-darkgrid', 'seaborn-v0_8-deep', 'seaborn-v0_8-muted', 'seaborn-v0_8-notebook', 'seaborn-v0_8-paper', 'seaborn-v0_8-pastel', 'seaborn-v0_8-poster', 'seaborn-v0_8-talk', 'seaborn-v0_8-ticks', 'seaborn-v0_8-white', 'seaborn-v0_8-whitegrid', 'tableau-colorblind10']

您可以使用以下方式啟用樣式

plt.style.use('fivethirtyeight')

現在讓我們重新製作上面的繪圖,看看它的樣子

lifecycle

樣式控制許多內容,例如顏色、線寬、背景等。

自訂繪圖#

現在我們有了一個具有我們想要的一般外觀的繪圖,因此讓我們進行微調,使其可以列印。首先,讓我們旋轉 x 軸上的標籤,以便它們更清楚地顯示出來。我們可以使用 axes.Axes.get_xticklabels() 方法來存取這些標籤

lifecycle

如果我們想要一次設定多個項目的屬性,則使用 pyplot.setp() 函式會很有用。這將採用一個(或多個)Matplotlib 物件的清單,並嘗試設定每個物件的某些樣式元素。

fig, ax = plt.subplots()
ax.barh(group_names, group_data)
labels = ax.get_xticklabels()
plt.setp(labels, rotation=45, horizontalalignment='right')
lifecycle

看起來這剪切掉了底部的某些標籤。我們可以告訴 Matplotlib 自動為我們建立的圖形中的元素騰出空間。為此,我們設定 rcParams 的 autolayout 值。有關使用 rcParams 控制繪圖的樣式、佈局和其他功能的更多資訊,請參閱使用樣式表和 rcParams 自訂 Matplotlib

plt.rcParams.update({'figure.autolayout': True})

fig, ax = plt.subplots()
ax.barh(group_names, group_data)
labels = ax.get_xticklabels()
plt.setp(labels, rotation=45, horizontalalignment='right')
lifecycle

接下來,我們將標籤新增到繪圖。要使用 OO 介面執行此操作,我們可以使用 Artist.set() 方法來設定此 Axes 物件的屬性。

fig, ax = plt.subplots()
ax.barh(group_names, group_data)
labels = ax.get_xticklabels()
plt.setp(labels, rotation=45, horizontalalignment='right')
ax.set(xlim=[-10000, 140000], xlabel='Total Revenue', ylabel='Company',
       title='Company Revenue')
Company Revenue

我們也可以使用 pyplot.subplots() 函式調整此繪圖的大小。我們可以使用 figsize 關鍵字引數來執行此操作。

注意

雖然 NumPy 中的索引形式為 (列、欄),但 figsize 關鍵字引數的形式為 (寬度、高度)。這遵循視覺化的慣例,不幸的是,這些慣例與線性代數的慣例不同。

fig, ax = plt.subplots(figsize=(8, 4))
ax.barh(group_names, group_data)
labels = ax.get_xticklabels()
plt.setp(labels, rotation=45, horizontalalignment='right')
ax.set(xlim=[-10000, 140000], xlabel='Total Revenue', ylabel='Company',
       title='Company Revenue')
Company Revenue

對於標籤,我們可以使用函式的形式指定自訂格式設定準則。下面我們定義一個函式,該函式將整數作為輸入,並將字串作為輸出傳回。當與 Axis.set_major_formatterAxis.set_minor_formatter 一起使用時,它們將自動建立並使用 ticker.FuncFormatter 類別。

對於此函式,x 引數是原始刻度標籤,而 pos 是刻度位置。我們在此只會使用 x,但兩個引數都是必要的。

def currency(x, pos):
    """The two arguments are the value and tick position"""
    if x >= 1e6:
        s = f'${x*1e-6:1.1f}M'
    else:
        s = f'${x*1e-3:1.0f}K'
    return s

然後,我們可以將此函式套用至繪圖上的標籤。要執行此操作,我們可以使用 Axes 的 xaxis 屬性。這可讓您在繪圖上的特定軸上執行動作。

fig, ax = plt.subplots(figsize=(6, 8))
ax.barh(group_names, group_data)
labels = ax.get_xticklabels()
plt.setp(labels, rotation=45, horizontalalignment='right')

ax.set(xlim=[-10000, 140000], xlabel='Total Revenue', ylabel='Company',
       title='Company Revenue')
ax.xaxis.set_major_formatter(currency)
Company Revenue

合併多個視覺化#

可以在 axes.Axes 的同一個實例上繪製多個繪圖元素。要執行此操作,我們只需在該 Axes 物件上呼叫另一個繪圖方法即可。

fig, ax = plt.subplots(figsize=(8, 8))
ax.barh(group_names, group_data)
labels = ax.get_xticklabels()
plt.setp(labels, rotation=45, horizontalalignment='right')

# Add a vertical line, here we set the style in the function call
ax.axvline(group_mean, ls='--', color='r')

# Annotate new companies
for group in [3, 5, 8]:
    ax.text(145000, group, "New Company", fontsize=10,
            verticalalignment="center")

# Now we move our title up since it's getting a little cramped
ax.title.set(y=1.05)

ax.set(xlim=[-10000, 140000], xlabel='Total Revenue', ylabel='Company',
       title='Company Revenue')
ax.xaxis.set_major_formatter(currency)
ax.set_xticks([0, 25e3, 50e3, 75e3, 100e3, 125e3])
fig.subplots_adjust(right=.1)

plt.show()
Company Revenue

儲存繪圖#

現在我們對繪圖的結果感到滿意,我們想要將其儲存到磁碟。在 Matplotlib 中,我們可以儲存為許多檔案格式。要查看可用選項的清單,請使用

{'eps': 'Encapsulated Postscript', 'jpg': 'Joint Photographic Experts Group', 'jpeg': 'Joint Photographic Experts Group', 'pdf': 'Portable Document Format', 'pgf': 'PGF code for LaTeX', 'png': 'Portable Network Graphics', 'ps': 'Postscript', 'raw': 'Raw RGBA bitmap', 'rgba': 'Raw RGBA bitmap', 'svg': 'Scalable Vector Graphics', 'svgz': 'Scalable Vector Graphics', 'tif': 'Tagged Image File Format', 'tiff': 'Tagged Image File Format', 'webp': 'WebP Image Format'}

然後,我們可以使用 figure.Figure.savefig() 以將圖形儲存到磁碟。請注意,下面我們顯示了幾個有用的旗標

  • transparent=True 使儲存的圖形背景透明(如果格式支援)。

  • dpi=80 控制輸出解析度(每平方英寸點數)。

  • bbox_inches="tight" 將圖形的邊界擬合到我們的繪圖。

# Uncomment this line to save the figure.
# fig.savefig('sales.png', transparent=False, dpi=80, bbox_inches="tight")

腳本的總執行時間:(0 分 4.147 秒)

由 Sphinx-Gallery 產生的範例集