matplotlib繪圖:figure和axes有什麼區別?

畫了這麼久的圖,腦子裏還是亂的,每次想實現個效果都能查到不同的實現方法,什麼 plt.plot 啦,ax.plot 啦,看起來好像都能達到目的?特別是到了精調繪圖細節,比如座標軸範圍、數字方向、標題等東西,更是頭大,每次都要試來試去。決定好好理一下 matplotlib 到底怎麼用🤦‍♀️🤦‍♀️🤦‍♀️

首先搞清楚了一直以來的疑惑(借用官方文檔的一幅圖說明):FigureAxesAxis 這三個是什麼關係。
在這裏插入圖片描述
(圖片來自:Usage

- Figure: 紅色的外框,其實可以把它理解爲一個大畫板,我們所有的內容都會畫在這個“畫板”上
- Axes: 藍色的內框,有人這麼解釋:

Axis 指 x、y 座標軸等(如果有三維那就還有 z 軸),代表的是 “座標軸”。而 Axes 在英文裏是 Axis 的複數形式,也就是說 axes 代表的其實是 figure 當中的一套座標軸。之所以說一套而不是兩個座標軸,是因爲如果你畫三維的圖,axes 就代表 3 根座標軸了。所以,在一個 figure 當中,每添加一次 subplot ,其實就是添加了一套座標軸,也就是添加了一個 axes,放在二維座標裏就是你添加了兩根座標軸,分別是 x 軸和 y 軸。所以當你只畫一個圖的時候,plt.xxx 與 ax.xxx 其實都是作用在相同的圖上的。

說話的方式簡單點… 要不就把 Axes 理解爲子圖(畫布)吧,一張大畫板 figure 上可以有一個或多個子圖(畫布)Axes,當只有一個 axes 時,plt.plot()ax.plot() 自然就作用的是同一張圖了!

官方文檔也解釋的很清楚:

The whole figure (marked as the outer red box). The figure keeps track of all the child Axes, a smattering of ‘special’ artists (titles, figure legends, etc), and the canvas. (Don’t worry too much about the canvas, it is crucial as it is the object that actually does the drawing to get you your plot, but as the user it is more-or-less invisible to you). A figure can have any number of Axes, but to be useful should have at least one.

- Axis: 綠色的橫縱座標軸,這個纔是正兒八經的座標軸!

類似於下面這樣,定義 4 個 subplot,自然就有 4 個 Axes
在這裏插入圖片描述
總結一下: figure 是作圖時給你的一個大畫板,而 axes 是在這個畫板上的很多幅畫布(子圖),繪製的所有圖都在畫布(axes)上。比如上面的漫畫布局,就可以用:

plt.figure()
plt.gcf().subplots(2,2)

來完成。其中 .gcf() 的作用是獲取當前 figure,即 get current figure。另外對應的 .gca() 就是獲取當前 axes,即 get current axes。

很多教程說的 plt.plot()plt.scatter()plt.bar(),其實本質上還是在 axes 上畫圖,可以將他們理解爲:先在 figure(畫板)上獲取一個當前要操作的 axes(畫布),如果沒有 axes 就自動創建一個並將其設爲當前的 axes,然後在當前這個 axes 上執行各種繪圖功能。 plt.<xxx> 就相當於 plt.gca().<xxx>。


下來詳細解釋一下繪圖時常用的操作:

1. plt.figure()

通常我們創建圖形時,首先會用 fig = plt.figure() 創建一個 “畫板”,並定義畫板名稱爲 fig,此時畫板是空白的,後面我們可以在畫板上繪製一個或多個子圖像。

通過 ax = fig.add_subplot() 向畫板中添加新的畫布,併爲畫布指定名字爲 “ax”,然後就可以單獨給這個畫布設置各種屬性啦。

用栗子看一下:

# create data
A1 = np.arange(1, 6)  # x ∈ [1,5]
A2 = np.arange(1, 11) # x ∈ [1,10]
B = A1 ** 2
C = A1 ** 3
D = A2 ** 2

# create figure and axes
fig = plt.figure()
ax1 = fig.add_subplot(221)
ax2 = fig.add_subplot(222)
ax3 = fig.add_subplot(212)

# plot data
ax1.bar(A1, B)
ax2.scatter(A1, C)
ax3.plot(A2, D)

plt.show()

在這裏插入圖片描述
不過更好用的方法是 fig, axes = plt.subplots(),在創建畫板的同時也將畫布賦給了 axes,比上面的 add_subplot 要方便不少。

plt.figure 調用方法:

plt.figure(num=None, figsize=None, dpi=None, 
		   facecolor=None, edgecolor=None, frameon=True, 
		   FigureClass=<class 'matplotlib.figure.Figure'>, 
		   clear=False, **kwargs)

參考文檔matplotlib.pyplot.figure

參數說明

  • num 當給它一個數字時,就作爲畫板的編號,相當於 ID 號;當給它一個字符串時,就作爲畫板的名稱
  • figsize 畫板的寬、高,單位爲英寸 (2.5cm)
  • dpi 指定在該畫板上繪製的圖像的分辨率,即每英寸多少個像素
  • facecolor 畫板的背景顏色
  • edgecolor 畫板的邊框顏色
  • frameon 是否顯示邊框

應用實例:

import matplotlib.pyplot as plt
# 創建圖形對象
fig = plt.figure(num='panel', figsize=(3,2),facecolor='gray')
plt.show()

這樣就創建了一個爲 panel,大小爲 3*2 英寸,背景板顏色 灰色 的圖形對象。
在這裏插入圖片描述
2. plt.subplot()

有了一個空白“畫板”後,我們再用 subplot 在這個畫板上分出多個子區域用來繪畫。將畫板整個區域分爲 nrows 行,ncols 列,subplotindex 參數將指示當前繪製在第幾個區域。區域編號的順序從上之下,從左至右

調用方法:

plt.subplot(nrows, ncols, index, **kwargs)

參考文檔: matplotlib.pyplot.subplot

應用實例 1:

import matplotlib.pyplot as plt
fig = plt.figure(num='panel', figsize=(8,4),facecolor='gray')
# 劃分三個小區域,繪製出第一個和第三個區域
plt.subplot(1,3,1)  # 劃分1行3列,第1個子區域
plt.subplot(1,3,3)  # 劃分1行3列,第3個子區域
plt.show()

在這裏插入圖片描述
有時我們需要的子圖大小是不一樣的,此時的解決辦法是劃分多次,每一次劃分將目標子圖安置在合適的位置就可以啦。

應用實例 2:

import matplotlib.pyplot as plt
fig = plt.figure(num='panel', figsize=(8,4),facecolor='gray')
# 繪製兩個不同大小的區域
plt.subplot(1,3,1) # 劃分1行3列,第1個子區域
plt.subplot(1,2,2) # 劃分1行2列,第2個子區域
plt.show()

其實把每一次 subplot 動作看作是獨立的就行了,第一次將整個畫板劃分爲1行3列完全不影響第二次劃分爲1行2列,它們僅影響當前劃分後子圖的大小。
在這裏插入圖片描述
3. plt.subplots()

最常用的就是 subplots,便於繪圖時精調細節信息。如果用 subplots 創建了多個子圖,那麼 axes 就是一個 list,用索引列表元素的方法就能獲取到每一個 axes。

用例子看一下:

import matplotlib.pyplot as plt
import numpy as np

# create data
A = np.arange(1,5)
B = A**2
C = A**3

# create figure and axes
fig, axes = plt.subplots(1, 2, figsize=(6,3))

# plot data
axes[0].plot(A,B)
axes[1].scatter(A,C)

在這裏插入圖片描述
axes 能夠直接通過索引獲取,所以也能夠寫入循環中:

import matplotlib.pyplot as plt
import numpy as np

# data
A = np.arange(1, 5)
B = A ** 2
C = A ** 3

# create figure and axes
fig, axes = plt.subplots(1, 2, figsize=(6, 3))
colors = ['r', 'g']

# plot data
for ax, c in zip(axes.flatten(), colors):
	ax.plot(A, B, c=c)
plt.show()

在這裏插入圖片描述
設置每一個 axes 的座標軸信息:

# 設定標題
ax.set_title('Title',fontsize=18)
ax.set_xlabel('xlabel', fontsize=18,fontfamily = 'sans-serif',fontstyle='italic')
ax.set_ylabel('ylabel', fontsize='x-large',fontstyle='oblique')
ax.legend()

# 屬性設定
ax.set_aspect('equal') 
ax.minorticks_on() 
ax.set_xlim(0,16) 
ax.grid(which='minor', axis='both')

# 座標軸細節
ax.xaxis.set_tick_params(rotation=45,labelsize=18,colors='w') 
start, end = ax.get_xlim() 
ax.xaxis.set_ticks(np.arange(start, end,1)) 
ax.yaxis.tick_right()

# 關閉座標軸
plt.axis('off')  # 需要位於plt.imshow之後,plt.show之前

subplots 創建一個畫板,同時也創建了一個繪圖子區域 axes。畫板賦值給了 fig,繪畫子區域賦值給了 ax。這樣一來,所有 fig.*** 都是對整個畫板進行操作,所有 ax.*** 都是對這個 Aexs 子區域進行操作。
在這裏插入圖片描述
(圖片來自:Usage Guide


參考資料:
matplotlib 官方參考文檔
https://zhuanlan.zhihu.com/p/93423829
Python matplotlib高級繪圖詳解

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章