Python繪圖—Matplotlib教程(詳細版)前半部分
一直將matplotlib當做一個工具來用,因為沒有了解到它的特性,所以一直學得不繫統,導致用到的時候經常要查官方文件。這裡翻譯一個官方推薦的matplotlib的介紹文件。
猛戳進入原文連結
文件中包含的內容:
- 簡介
- 簡單的例子
- matplotlib元件(Figures, Subplots, Axes and Ticks)
- 動畫
- 其他的繪圖型別
- 補充
該部落格只翻譯123小節,下一篇部落格介紹下面的
你可以點選圖片上面的原始碼超連結獲取當前圖形的程式碼。這些連結也是原英文文件的作者提供的。
簡介
matplotlib可能是最常用的2D繪圖Python包了。它可以對Python中的資料進行快速的視覺化,並以多種格式輸出。接下來,我們將以互動的方式介紹matplotlib中的大多數情況
pyplot
在matplotlib面向物件的繪相簿中,pyplot是一個方便的介面。
簡單的例子
在這一章,我們想在一個圖中畫一個cosine函式和一個sine函式。對於畫圖時的細節,我們先讓它預設,然後再一步一步按自己的要求豐富figure,讓它變得更visible。
首先,由sine函式和cosine函式獲取資料:
import numpy as np
X = np.linspace(-np.pi, np.pi, 256, endpoint=True)
C, S = np.cos(X), np.sin(X)
其中,np.linspace(...)
的意思是從-到+均勻的取256個點(包括最後一個點-)。至此,C就是一個由256個點組成的cosine函式,而S是一個由256個點組成的sine函式。
使用預設值
為了方便起見,matplotlib給出了很多預設設定。 你幾乎可以控制所有matplotlib中提供的屬性值:figure大小和畫素,line的寬度、顏色和樣式,axes,axis和grid屬性,文字和字型屬性等等。儘管大多數情況下,matplotlib的預設值都足夠好了,但在某些情況下,你可能還是想用自己的方式修飾這些屬性。
原始碼和結果如下所示:
import numpy as np
import matplotlib.pyplot as plt
X = np.linspace(-np.pi, np.pi, 256, endpoint=True)
C,S = np.cos(X), np.sin(X)
plt.plot(X,C)
plt.plot(X,S)
plt.show()
初始化預設值
在下面的指令碼中,我們初始化一些引數。下面修改的引數實際上與預設值是一樣的,但你可以通過修改這些引數,觀察結果圖形的變化。
原始碼和結果如下所示:
# 模組匯入
import numpy as np
import matplotlib.pyplot as plt
# 建立一個8x6大小的figure,並設定每英寸80個畫素點
plt.figure(figsize=(8, 6), dpi=80)
# 建立在1x1的位置建立一個subplot
plt.subplot(111)
X = np.linspace(-np.pi, np.pi, 256, endpoint=True)
C, S = np.cos(X), np.sin(X)
# 繪製cosine函式,顏色是藍色,line寬為1.0,line型別是實線
plt.plot(X, C, color='blue', linewidth=1.0, linestyle='-')
# 繪製sine函式,顏色是綠色,line寬為1.0,line型別是實線
plt.plot(X, S, color='green', linewidth=1.0, linestyle='-')
# 設定x軸和y軸範圍
plt.xlim(-4.0, 4.0)
plt.ylim(-1.0, 1.0)
# 設定x軸下標和y軸下標
plt.xticks(np.linspace(-4, 4, 9, endpoint=True))
plt.yticks(np.linspace(-1, 1, 5, endpoint=True))
# 儲存圖片,每英寸72個點
# 如果此處報錯,在當前路徑下建立figures資料夾
# savefig("../figures/exercice_2.png", dpi=72)
# 在螢幕上顯示結果
plt.show()
修改顏色和line寬度
將cosine函式改成藍色,sine函式改成紅色,將它們的line加寬為2.5,同時也修改了figure的大小,使圖形的比例看起來更好。
原始碼和結果如下所示:
plt.figure(figsize=(10, 6), dpi=80)
plt.plot(X, C, color='blue', linewidth=2.5, linestype='-')
plt.plot(X, S, color="red", linewidth=2.5, linestyle="-")
設定座標軸範圍
改變了x軸和y軸的範圍,讓圖形看起來既完整又緊緻。
原始碼:和結果如下所示
plt.xlim(X.min() * 1.1, X.max() * 1.1)
plt.ylim(C.min() * 1.1, C.max() * 1.1)
設定座標軸下標
當前的座標軸下標並不理想,因為它們沒有標出我們感興趣的點-和+。
原始碼和結果如下所示:
plt.xticks( [-np.pi, -np.pi/2, 0, np.pi/2, np.pi])
plt.yticks([-1, 0, +1])
設定座標軸下標名
座標軸的下標的位置現在很理想,但是它的名字(也就是表現形式)不應該是3.142,最好是。注意matplotlib的座標軸的下標包括位置(location)和名字(label)兩部分。現在,我們利用latex來命名下標。
原始碼和結果如下所示:
# r''是為了轉義裡面的轉義字元\
plt.xticks([-np.pi, -np.pi/2, 0, np.pi/2, np.pi], [r'$-\pi$', r'$-\pi/2$', r'$0$', r'$+\pi/2$', r'$+\pi$'])
plt.yticks([-1, 0, +1], [r'$-1$', r'$0$', r'$+1$'])
移動 spines
spines包括圖片上下左右4條邊界和它們的下標,就是正方形的4條邊。它們可以被挪到任意的位置,現在,它們還在邊界上。我們要把它們移到中間。首先,將上邊界和右邊界的顏色設定為none,就隱藏了。然後我們將下邊界和左邊界移動到資料空間的0處。
原始碼和結果如下所示:
# plt.gca()獲取當前ax
ax = plt.gca()
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.xaxis.set_ticks_position('bottom')
# set_position中的引數元組的第二個值可取-1,0,1分別代表相對‘data’的不同的位置
ax.spines['bottom'].set_position(('data', 0))
ax.yaxis.set_ticks_position('left')
ax.spines['left'].set_position(('data', 0))
新增legend
legend就是如下圖所示的東西。這個需要調整兩點:一個是引數label,一個是plot命令plt.legend()
。
原始碼和結果如下所示:
plt.plot(X, C, color="blue", linewidth=2.5, linestyle="-", label="cosine")
plt.plot(X, S, color="red", linewidth=2.5, linestyle="-", label="sine")
# frameon=True的話,右上角的宣告會在一個框內
plt.legend(loc='upper left', frameon=False)
標記一些點
讓我們來用plt.annotate()
命令來標記一些感興趣的點。我們選了點來標記它在sine和cosine函式上的值。首先,繪製一個點和虛線。然後我們用annotate命令新增文字和箭頭上去。
原始碼和結果如下所示:
t = 2*np.pi/3
plt.plot([t,t],[0,np.cos(t)], color ='blue', linewidth=1.5, linestyle="--")
plt.scatter([t,],[np.cos(t),], 50, color ='blue')
# 第一個引數s為要標記上去的文字
# 第二個引數xy為標記的位置,必須是可迭代物件(如tuple,list)
# 第三個物件xycoords表示xy的參考系
# 第四個物件xytext為標記文字相對標記位置的位置,必須是可迭代物件iterabl
# 第五個物件textcoords表示xytext的參考系
# 第六個物件fontsize為字型大小
# 第七個物件arrowprops為箭頭樣式
plt.annotate(r'$\sin(\frac{2\pi}{3})=\frac{\sqrt{3}}{2}$', xy=(t, np.sin(t)), xycoords='data', xytext=(+10, +30), textcoords='offset points', fontsize=16, arrowprops=dict(arrowstyle="->", connectionstyle="arc3,rad=.2"))
plt.plot([t,t],[0,np.sin(t)], color ='red', linewidth=1.5, linestyle="--")
plt.scatter([t,],[np.sin(t),], 50, color ='red')
plt.annotate(r'$\cos(\frac{2\pi}{3})=-\frac{1}{2}$', xy=(t, np.cos(t)), xycoords='data', xytext=(-90, -50), textcoords='offset points', fontsize=16, arrowprops=dict(arrowstyle="->", connectionstyle="arc3,rad=.2"))
細節決定成敗
labels現在被紅線和藍線擋住了。我們可以把label的字條調大,讓紅藍線變成半透明的。
原始碼和結果如下所示:
for label in ax.get_xticklabels() + ax.get_yticklabels():
label.set_fontsize(16)
label.set_bbox(dict(facecolor='white', edgecolor='None', alpha=0.65))
matplotlib元件
到目前為止,我們使用的都是直接了當的單一figure和axes。這可以幫我們方便快速的繪圖。此外,我們還可以使用figure,subplot和axes創造更多的佈局。figure是matplotlib中面向使用者的最大的介面,figure裡面是subplots。subplot指定plots在figure中的位置,axes就是被指定位置後的的plots,這些都可以按照你的意願來佈局。我們之前的程式碼都沒有宣告它們。如果我們要呼叫plot,gca()
獲取當前axes,gcf()
獲取當前figure。如果沒有當前figure,就建立一個並返回。
Figures
一個figure就是一個在GUI中名為“Figure#”的一個視窗,它的計數是從1開始的,跟普通的Python計數方式不同,而是MATLAB的計數風格。下面是幾個定義figure外形的引數。
引數 | 預設值 | 描述 |
---|---|---|
num | 1 | figure編號 |
figsize | figure.figsize | figure長和寬 |
dpi | figure.dpi | 畫素 |
facecolor | figure.facecolor | 背景顏色 |
edgecolor | figure.edgecolor | 邊緣顏色 |
frameon | True | 邊框有無 |
大多數情況下,figure都是使用預設值,只有num引數才會經常改動。
如果你是以GUI的形式工作,可以點選右上角的x關閉figure,也可以通過呼叫函式關閉figure,如plt.close()
。無引數表示關閉當前figure,有引數int表示關閉特定figure,還可以通過修改引數關閉所有figure。
figure物件和其他物件一樣,可以通過set_
型別的函式修改引數。
Subplots
subplot是用來佈局plots的,需要指定(行、列、序號)。
點選獲取原始碼,效果圖如下:
點選獲取原始碼,效果圖如下:
點選獲取原始碼,效果圖如下:
點選獲取原始碼,效果圖如下:
Axes
Axes和subplots很像,但它可以佈局在figure的任意位置。所以如果我們想把一個小plot放在一個大plot裡面,應該採用Axes。
點選獲取原始碼,效果圖如下:
點選獲取原始碼,效果圖如下:
Ticks
合適的ticks對於圖片的繪製非常重要。matplotlib提供了一個完整的ticks配置系統,tick locators表明ticks應該處於什麼位置;tick formatters可以提供要展示的tick名字。major ticks和minor ticks是相互獨立的。因為沒有位置資訊,每一個預設的minor ticks是不顯示的,它們只是一個空列表。
Tick Locators
下面是不同的位置資訊:
Class | Description |
---|---|
NullLocator | 沒有ticks 圖一 |
IndexLocator | 對每一個重要繪圖點都設定一個tick 圖二 |
FixedLocator | 靈活的ticks 圖三 |
LinearLocator | 線性ticks 圖四 |
MultipleLocator | 對每一個繪圖點都設定一個tick 圖五 |
AutoLocator | 選擇不多於n個比較好的ticks 圖六 |
LogLocator | log型別的ticks 圖七 |
1.
2.
3.
4.
5.
6.
7.
所有這些定位器都從基類matplotlib.ticker.Locator派生。 你可以製作自己的定位器。 處理日期作為ticks可能是特別棘手的。 因此,matplotlib在matplotlib.dates中提供了特殊的定位器。