轉載於https://blog.csdn.net/qq_31347869/article/details/104794515
畫了這么久的圖,腦子里還是亂的,每次想實現個效果都能查到不同的實現方法,什么 plt.plot
啦,ax.plot
啦,看起來好像都能達到目的?特別是到了精調繪圖細節,比如坐標軸范圍、數字方向、標題等東西,更是頭大,每次都要試來試去。決定好好理一下 matplotlib 到底怎么用🤦♀️🤦♀️🤦♀️
首先搞清楚了一直以來的疑惑(借用官方文檔的一幅圖說明):Figure,Axes,Axis 這三個是什么關系。
(圖片來自: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)
- 1
- 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()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
不過更好用的方法是 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)
- 1
- 2
- 3
- 4
參數說明:
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()
- 1
- 2
- 3
- 4
這樣就創建了一個為 panel
,大小為 3*2 英寸
,背景板顏色 灰色
的圖形對象。
2. plt.subplot()
有了一個空白“畫板”后,我們再用 subplot
在這個畫板上分出多個子區域用來繪畫。將畫板整個區域分為 nrows
行,ncols
列,subplot
的 index
參數將指示當前繪制在第幾個區域。區域編號的順序從上之下,從左至右。
調用方法:
plt.subplot(nrows, ncols, index, **kwargs)
- 1
參考文檔: 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()
- 1
- 2
- 3
- 4
- 5
- 6
有時我們需要的子圖大小是不一樣的,此時的解決辦法是划分多次,每一次划分將目標子圖安置在合適的位置就可以啦。
應用實例 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()
- 1
- 2
- 3
- 4
- 5
- 6
其實把每一次 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 = A2
C = A3
# 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)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
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()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
設置每一個 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之前
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
用 subplots
創建一個畫板,同時也創建了一個繪圖子區域 axes
。畫板賦值給了 fig
,繪畫子區域賦值給了 ax
。這樣一來,所有 fig.***
都是對整個畫板進行操作,所有 ax.***
都是對這個 Aexs 子區域進行操作。
(圖片來自:Usage Guide)
參考資料:
matplotlib 官方參考文檔
https://zhuanlan.zhihu.com/p/93423829
Python matplotlib高級繪圖詳解