常見問題#

我看不到圖表視窗#

請參閱 除錯圖表視窗未顯示問題

為什麼我有這麼多刻度,和/或為什麼它們的順序錯亂?#

刻度行為異常的一個常見原因是傳遞字串列表而不是數字或日期時間物件。當讀入逗號分隔的文字檔案時,這種情況很容易在不知不覺中發生。Matplotlib 將字串列表視為類別變數 (繪製類別變數),並且預設情況下,每個類別放置一個刻度,並按照它們被提供的順序繪製它們。

import matplotlib.pyplot as plt
import numpy as np

fig, ax = plt.subplots(1, 2, layout='constrained', figsize=(6, 2))

ax[0].set_title('Ticks seem out of order / misplaced')
x = ['5', '20', '1', '9']  # strings
y = [5, 20, 1, 9]
ax[0].plot(x, y, 'd')
ax[0].tick_params(axis='x', labelcolor='red', labelsize=14)

ax[1].set_title('Many ticks')
x = [str(xx) for xx in np.arange(100)]  # strings
y = np.arange(100)
ax[1].plot(x, y)
ax[1].tick_params(axis='x', labelcolor='red', labelsize=14)

(原始碼, 2x.png, png)

解決方案是將字串列表轉換為數字或日期時間物件(通常是 np.asarray(numeric_strings, dtype='float')np.asarray(datetime_strings, dtype='datetime64[s]'))。

如需更多資訊,請參閱 修正過多的刻度

決定圖表中藝術家 (Artists) 的範圍#

有時我們想要知道藝術家 (Artist) 的範圍。Matplotlib Artist 物件有一個方法 Artist.get_window_extent,通常會傳回藝術家 (Artist) 的像素範圍。但是,某些藝術家 (Artist),特別是文字,必須至少渲染一次才能知道它們的範圍。Matplotlib 提供 Figure.draw_without_rendering,應該在呼叫 get_window_extent 之前呼叫。

檢查圖表是否為空#

空實際上可能意味著不同的事情。圖表是否包含任何藝術家 (Artist)?具有空 Axes 的圖表仍然算作空嗎?如果圖表被渲染為純白色(可能存在藝術家 (Artist),但它們可能在繪圖區域之外或透明),則圖表是否為空?

就此目的而言,我們將空定義為:「圖表不包含任何藝術家 (Artist),除了它的背景圖塊。」背景的例外是必要的,因為預設情況下,每個圖表都包含一個 Rectangle 作為其背景圖塊。這個定義可以透過以下方式檢查

def is_empty(figure):
    """
    Return whether the figure contains no Artists (other than the default
    background patch).
    """
    contained_artists = figure.get_children()
    return len(contained_artists) <= 1

我們已決定不將其包含為圖表方法,因為這只是定義空的一種方式,並且很少需要檢查以上內容。通常,使用者或處理圖表的程式知道他們是否已在圖表中新增了內容。

檢查圖表是否會渲染為空的唯一可靠方法是實際執行此類渲染並檢查結果。

尋找圖表中所有特定類型的物件#

每個 Matplotlib 藝術家 (Artist)(請參閱 藝術家 (Artist) 教學)都有一個名為 findobj() 的方法,可用於遞迴搜尋藝術家 (Artist) 中可能包含的任何符合某些條件的藝術家 (Artist)(例如,比對所有 Line2D 實例或比對某些任意篩選函式)。例如,以下程式碼片段會尋找圖表中每個具有 set_color 屬性的物件,並將物件設為藍色

def myfunc(x):
    return hasattr(x, 'set_color')

for o in fig.findobj(myfunc):
    o.set_color('blue')

您也可以根據類別實例進行篩選

import matplotlib.text as text
for o in fig.findobj(text.Text):
    o.set_fontstyle('italic')

防止刻度標籤具有偏移量#

預設格式器會使用偏移量來縮短刻度標籤的長度。若要關閉每個軸上的此功能

ax.xaxis.get_major_formatter().set_useOffset(False)

設定 rcParams["axes.formatter.useoffset"] (預設:True),或使用不同的格式器。請參閱 ticker 以取得詳細資訊。

儲存透明圖表#

savefig() 命令有一個關鍵字引數 transparent,如果為 'True',則會在儲存時使圖表和軸的背景透明,但不會影響螢幕上顯示的影像。

如果您需要更精細的控制,例如,您不想要完全透明,或者您也想要影響螢幕顯示的版本,您可以直接設定 alpha 屬性。圖表有一個名為 patchRectangle 實例,而軸有一個名為 patch 的 Rectangle 實例。您可以直接設定它們的任何屬性(facecoloredgecolorlinewidthlinestylealpha)。例如

fig = plt.figure()
fig.patch.set_alpha(0.5)
ax = fig.add_subplot(111)
ax.patch.set_alpha(0.5)

如果您需要所有圖表元素都透明,目前沒有全域 alpha 設定,但您可以在個別元素上設定 alpha 通道,例如

ax.plot(x, y, alpha=0.5)
ax.set_xlabel('volts', alpha=0.5)

將多個圖形儲存到一個 pdf 檔案#

許多影像檔案格式每個檔案只能有一個影像,但某些格式支援多頁檔案。目前,Matplotlib 僅透過 backend_pdf.PdfPagesbackend_pgf.PdfPages 類別,為 pdf 檔案提供多頁輸出,使用 pdf 或 pgf 後端。

為刻度標籤騰出空間#

預設情況下,Matplotlib 在子圖周圍使用固定的百分比邊距。這可能會導致標籤重疊或在圖表邊界被截斷。有多種方法可以解決此問題

對齊多個子圖的 y 軸標籤#

如果您有多個子圖重疊,且 y 軸數據具有不同的刻度,您可能會發現 y 軸標籤在多個子圖中無法垂直對齊,這可能不夠美觀。 預設情況下,Matplotlib 會定位 y 軸標籤的 x 座標,使其不會與任何 y 軸刻度重疊。 您可以透過指定標籤的座標來覆寫此預設行為。 如需了解如何操作,請參閱對齊 y 軸標籤

控制繪圖元素的繪製順序#

繪圖元素的繪製順序,以及哪些元素會顯示在最上方,是由 set_zorder 屬性決定。 如需詳細說明,請參閱 Zorder 示範

使繪圖的長寬比相等#

Axes 屬性 set_aspect() 控制軸的長寬比。您可以將其設定為 'auto'、'equal' 或某個比例,以控制長寬比。

ax = fig.add_subplot(111, aspect='equal')

如需完整的範例,請參閱相等軸長寬比

繪製多個 y 軸刻度#

一個常見的需求是為左右 y 軸設定兩個刻度,這可以使用 twinx() 實現(目前不支援超過兩個刻度,但已在願望清單上)。這種方式效果相當不錯,但在嘗試互動式平移和縮放時會有一些怪癖,因為兩個刻度並不會收到訊號。

這種方法使用 twinx() (及其姊妹函數 twiny())來使用兩個不同的軸,關閉第二個軸的矩形框架以避免遮蔽第一個軸,並根據需要手動設定刻度位置和標籤。 您可以根據需要使用單獨的 matplotlib.ticker 格式化器和定位器,因為兩個軸是獨立的。

(原始碼, 2x.png, png)

如需完整的範例,請參閱 具有不同刻度的繪圖

產生影像而不顯示視窗#

只需不呼叫 show,並直接將圖片儲存為所需的格式即可

import matplotlib.pyplot as plt
plt.plot([1, 2, 3])
plt.savefig('myfig.png')

另請參閱

嵌入於網頁應用程式伺服器 (Flask),以取得有關在網頁應用程式內執行 matplotlib 的資訊。

處理執行緒#

Matplotlib 不是執行緒安全的:實際上,已知某些繪圖物件會受到競爭條件的影響。因此,如果您使用執行緒,您有責任設定適當的鎖定,以序列化對 Matplotlib 繪圖物件的存取。

您或許可以從不同的執行緒處理不同的圖片。但是,在這種情況下,您必須使用非互動式後端(通常是 Agg),因為大多數 GUI 後端也需要從主執行緒執行。

取得協助#

有許多資源可以協助您使用 Matplotlib。 您的問題很有可能已經被問過了

如果您無法透過搜尋找到問題的答案,請在您寄給郵件列表的電子郵件中提供以下資訊

  • 您的作業系統(Linux/Unix 使用者:張貼 uname -a 的輸出)。

  • Matplotlib 版本

    python -c "import matplotlib; print(matplotlib.__version__)"
    
  • 您從哪裡取得 Matplotlib(例如,您的 Linux 發行版套件、GitHub、PyPI 或 Anaconda)。

  • 對您的 matplotlibrc 檔案所做的任何自訂(請參閱使用樣式表和 rcParams 自訂 Matplotlib)。

  • 如果問題可以重現,請嘗試提供一個最小、獨立的 Python 指令碼來示範該問題。這是關鍵的步驟。如果您無法張貼一段我們可以執行並重現錯誤的程式碼,那麼獲得協助的機會將會大幅減少。很多時候,單純嘗試將您的程式碼縮減到產生錯誤的最小程式碼,將有助於您在您的程式碼中找到導致問題的錯誤。

  • Matplotlib 通過 logging 函式庫和一個設定記錄層級的輔助函數來提供偵錯資訊:可以呼叫

    plt.set_loglevel("info")  # or "debug" for more info
    

    來取得此偵錯資訊。

    來自 logging 模組的標準函數也適用;例如,即使在匯入 Matplotlib 之前,也可以呼叫 logging.basicConfig(level="DEBUG") (這尤其對於取得 Matplotlib 匯入期間發出的記錄資訊是必要的),或將自訂處理器附加到「matplotlib」記錄器。如果您使用自訂記錄設定,這可能會很有用。

如果您是自行編譯 Matplotlib,請同時提供

  • 您的編譯器版本 -- 例如,gcc --version

  • 以下指令的輸出

    pip install --verbose
    

    建置輸出的開頭包含許多關於您平台的詳細資訊,這些資訊對於 Matplotlib 開發人員診斷您的問題很有幫助。

如果您使用 pre-Meson 建置系統編譯了舊版本的 Matplotlib,請改為提供

  • 您對 setup.py/setupext.py 所做的任何變更,

  • 以下指令的輸出

    rm -rf build
    python setup.py build
    

在您寄給郵件列表的第一封電子郵件中包含這些資訊將會節省很多時間。

與在錯誤追蹤器中提交錯誤相比,寫信給郵件列表可能會更快得到回覆。 大多數開發人員只會定期檢查錯誤追蹤器。 如果確定您的問題是錯誤且無法快速解決,則可能會要求您在追蹤器中提交錯誤,以防止問題遺失。