上篇文章色建,我們了解到 Matplotlib 是一個(gè)風(fēng)格類似 Matlab 的基于 Python 的繪圖庫(kù)誉碴。它提供了一整套和matlab相似的命令A(yù)PI宦棺,十分適合交互式地進(jìn)行制圖。而且我們也可以方便地將它作為繪圖控件黔帕,嵌入GUI應(yīng)用程序中代咸。本文主要走進(jìn) Matplotlib 的世界,初步學(xué)會(huì)繪制圖形蹬屹。
1 基礎(chǔ)知識(shí)
在學(xué)習(xí)繪制之前侣背,先來了解下 Matplotlib 基礎(chǔ)概念。
1.1 庫(kù)
我們繪制圖形主要用到兩個(gè)庫(kù)慨默,matplotlib.pyplot
和numpy
贩耐。在編碼過程中,這兩個(gè)庫(kù)的使用頻率較高厦取,而這兩個(gè)庫(kù)的名字較長(zhǎng)潮太。這難免會(huì)給我們帶來不便。所以我們一般給其設(shè)置別名, 大大減少重復(fù)性工作量铡买。具體如下代碼:
import matplotlib.pyplot as plt # 導(dǎo)入模塊 matplotlib.pyplot更鲁,并簡(jiǎn)寫成 plt
import numpy as np # 導(dǎo)入模塊 numpy,并簡(jiǎn)寫成 np
numpy 是 Python 用于數(shù)學(xué)運(yùn)算的庫(kù)奇钞,它是在安裝 matplotlib 時(shí)候順帶安裝的澡为。pyplot 是 matplotlib 一個(gè)子模塊,主要為底層的面向?qū)ο蟮睦L圖庫(kù)提供狀態(tài)機(jī)界面景埃。狀態(tài)機(jī)隱式地自動(dòng)創(chuàng)建數(shù)字和坐標(biāo)軸以實(shí)現(xiàn)所需的繪圖媒至。 matplotlib 中的所有內(nèi)容都按照層次結(jié)果進(jìn)行組織。頂層就是由 pyplot 提供的 matplotlib “狀態(tài)機(jī)環(huán)境”谷徙【軉基于這個(gè)狀態(tài)機(jī)環(huán)境,我們就可以創(chuàng)建圖形完慧。
1.2 圖形組成標(biāo)簽
我在 matplotlib 官網(wǎng)上找圖像組件說明圖并在上面增加中文翻譯谋旦。通過這張圖,我們對(duì) matplotlib 整體地認(rèn)識(shí)屈尼。
接下來册着,我主要講解 matplotlib 中幾個(gè)重要的標(biāo)簽。
- Figure
Figure 翻譯成中文是圖像窗口脾歧。Figure 是包裹 Axes指蚜、tiles、legends 等組件的最外層窗口涨椒。它其實(shí)是一個(gè) Windows 應(yīng)用窗口 。
Figure 中最主要的元素是 Axes(子圖)绽媒。一個(gè) Figure 中可以有多個(gè)子圖蚕冬,但至少要有一個(gè)能夠顯示內(nèi)容的子圖。
- Axes
Axes 翻譯成中文是軸域/子圖是辕。Axes 是帶有數(shù)據(jù)的圖像區(qū)域囤热。從上文可知,它是位于 Figure 里面获三。那它和 Figure 是什么關(guān)系旁蔼?這里可能文字難以表述清楚,我以圖說文疙教。用兩圖帶你徹底弄清它們的關(guān)系棺聊。
在看運(yùn)行結(jié)果之前,我先呈上代碼給各位看官品嘗贞谓。
fig = plt.figure() # 創(chuàng)建一個(gè)沒有 axes 的 figure
fig.suptitle('No axes on this figure') # 添加標(biāo)題以便我們辨別
fig, ax_lst = plt.subplots(2, 2) # 創(chuàng)建一個(gè)以 axes 為單位的 2x2 網(wǎng)格的 figure
plt.show()
根據(jù)運(yùn)行結(jié)果圖限佩,我們不難看出。左圖的 Figure1 中沒有 axes,右圖的 Figure2 中有 4 個(gè) axes祟同。因此作喘,我們可以將 Axes 理解為面板,而面板是覆在窗口(Figure) 上晕城。
- Axis
Axis 在中文的意思是軸泞坦。官網(wǎng)文檔對(duì) Axis 定義解釋不清楚,讓我們看得云里霧里的砖顷。如果你有留意前文的組成說明圖贰锁,可以看到 X Axis 和 Y Axis 的字樣。按照平常人的見識(shí)择吊, 觀察該圖就能明白 Axis 是軸的意思李根。此外,Axis 和 Axes 以及 Figure 這三者關(guān)系几睛,你看完下圖房轿,會(huì)恍然大悟。
2 繪制第一張圖
按照劇本發(fā)展所森,我接下來以繪制曲線并逐步美化它為例子片仿,一步步講解如何繪制圖形。在這過程中冯勉,我也會(huì)逐一說明各個(gè)函數(shù)的作用场梆。
初步繪制曲線
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(-2, 6, 50)
y1 = x + 3 # 曲線 y1
y2 = 3 - x # 曲線 y2
plt.figure() # 定義一個(gè)圖像窗口
plt.plot(x, y1) # 繪制曲線 y1
plt.plot(x, y2) # 繪制曲線 y2
plt.show()
調(diào)用np.linspace
是創(chuàng)建一個(gè) numpy 數(shù)組,并記作 x晴弃。x 包含了從 -2 到 6 之間等間隔的 50 個(gè)值掩幢。y1 和 y2 則分別是這 50 個(gè)值對(duì)應(yīng)曲線的函數(shù)值組成的 numpy 數(shù)組。前面的操作還處于設(shè)置屬性的階段上鞠,還沒有開始繪制圖形际邻。plt.figure()
函數(shù)才意味著開始執(zhí)行繪圖操作。最后別忘記調(diào)用show()
函數(shù)將圖形呈現(xiàn)出來芍阎。
簡(jiǎn)單修飾
我們已經(jīng)繪制出兩條直線世曾,但樣式比較簡(jiǎn)陋。所以我給兩條曲線設(shè)置鮮艷的顏色谴咸、線條類型轮听。同時(shí),還給縱軸和橫軸的設(shè)置上下限岭佳,增加可觀性血巍。
import matplotlib.pyplot as plt
import numpy as np
# 創(chuàng)建一個(gè)點(diǎn)數(shù)為 8 x 6 的窗口, 并設(shè)置分辨率為 80像素/每英寸
plt.figure(figsize=(8, 6), dpi=80)
# 再創(chuàng)建一個(gè)規(guī)格為 1 x 1 的子圖
plt.subplot(111)
x = np.linspace(-2, 6, 50)
y1 = x + 3 # 曲線 y1
y2 = 3 - x # 曲線 y2
# 繪制顏色為藍(lán)色、寬度為 1 像素的連續(xù)曲線 y1
plt.plot(x, y1, color="blue", linewidth=1.0, linestyle="-")
# 繪制顏色為紫色驼唱、寬度為 2 像素的不連續(xù)曲線 y2
plt.plot(x, y2, color="#800080", linewidth=2.0, linestyle="--")
# 設(shè)置橫軸的上下限
plt.xlim(-1, 6)
# 設(shè)置縱軸的上下限
plt.ylim(-2, 10)
plt.show()
設(shè)置縱橫軸標(biāo)簽
在圖像中藻茂,我們不能一味地認(rèn)為橫軸就是 X 軸,縱軸就是 Y 軸。圖形因內(nèi)容數(shù)據(jù)不同辨赐,縱橫軸標(biāo)簽往往也會(huì)不同优俘。這也體現(xiàn)了給縱橫軸設(shè)置標(biāo)簽說明的重要性。
...
# 設(shè)置橫軸標(biāo)簽
plt.xlabel("X")
# 設(shè)置縱軸標(biāo)簽
plt.ylabel("Y")
plt.show()
設(shè)置精準(zhǔn)刻度
matplotlib 畫圖設(shè)置的刻度是由曲線以及窗口的像素點(diǎn)等因素決定掀序。這些刻度精確度無法滿足需求帆焕,我們需要手動(dòng)添加刻度。上圖中不恭,縱軸只顯示 2 的倍數(shù)的刻度叶雹,橫軸只顯示 1 的倍數(shù)的刻度。我們?yōu)槠涮砑泳珳?zhǔn)刻度换吧,縱軸變成單位間隔為 1 的刻度折晦,橫軸變成單位間隔為 0.5 的刻度。
...
# 設(shè)置橫軸精準(zhǔn)刻度
plt.xticks([-1, -0.5, 0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5, 5.5])
# 設(shè)置縱軸精準(zhǔn)刻度
plt.yticks([-2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
plt.show()
xticks() 和 yticks() 需要傳入一個(gè)列表作為參數(shù)沾瓦。
該方法默認(rèn)是將列表的值來設(shè)置刻度標(biāo)簽满着,如果你想重新設(shè)置刻度標(biāo)簽,則需要傳入兩個(gè)列表參數(shù)給 xticks() 和 yticks() 贯莺。第一個(gè)列表的值代表刻度风喇,第二個(gè)列表的值代表刻度所顯示的標(biāo)簽。
...
# 設(shè)置橫軸精準(zhǔn)刻度
plt.xticks([-1, 0, 1, 2, 3, 4, 5, 6],
["-1m", "0m", "1m", "2m", "3m", "4m", "5m", "6m"])
# 設(shè)置縱軸精準(zhǔn)刻度
plt.yticks([-2, 0, 2, 4, 6, 8, 10],
["-2m", "0m", "2m", "4m", "6m", "8m", "10m"])
plt.show()
添加圖例
如果需要在圖的左上角添加一個(gè)圖例缕探。我們只需要在 plot() 函數(shù)里以「鍵 - 值」的形式增加一個(gè)參數(shù)魂莫。首先我們需要在繪制曲線的時(shí)候,增加一個(gè) label 參數(shù)爹耗,然后再調(diào)用 plt.legend() 繪制出一個(gè)圖例耙考。plt.legend() 需要傳入一個(gè)位置值。loc 的值可選如下:
值 | 說明 |
---|---|
best | 自動(dòng)選擇最佳位置潭兽,默認(rèn)是左上 |
upper right | 右上 |
upper left | 左上 |
lower right | 右下 |
lower left | 左下 |
right | 右邊琳骡,默認(rèn)是右上。如果因圖形擋住右上讼溺,會(huì)自動(dòng)往下選擇空白地方繪制 |
center right | 垂直居中且靠右 |
center left | 垂直居中且靠左 |
lower center | 垂直居中且靠底部 |
upper center | 垂直居中且靠頂部 |
center | 居中 |
...
# 繪制顏色為藍(lán)色、寬度為 1 像素的連續(xù)曲線 y1
plt.plot(x, y1, color="blue", linewidth=1.0, linestyle="-", label="y1")
# 繪制顏色為紫色最易、寬度為 2 像素的不連續(xù)曲線 y2
plt.plot(x, y2, color="#800080", linewidth=2.0, linestyle="--", label="y2")
plt.legend(loc="upper left")
...
注釋特殊點(diǎn)位
有時(shí)某些數(shù)據(jù)點(diǎn)非常關(guān)鍵怒坯,需要突顯出來。我們需要將改點(diǎn)繪制出來藻懒,即繪制散點(diǎn)圖剔猿,再對(duì)其做注釋。實(shí)現(xiàn)上述需求嬉荆,我們要用到scatter()
和annotate()
函數(shù)归敬。scatter()
是用于繪制散圖,這里我們只是用其來繪制單個(gè)點(diǎn)。scatter() 用法汪茧,后續(xù)文章會(huì)詳細(xì)對(duì)其用法做說明椅亚。annotate()
則是添加標(biāo)注 。
scatter()
函數(shù)必須傳入兩個(gè)參數(shù) x 和 y舱污。值得注意得是呀舔,它們的數(shù)據(jù)類型是列表。x 代表要標(biāo)注點(diǎn)的橫軸位置扩灯,y 代表要標(biāo)注點(diǎn)的橫軸位置媚赖。x 和 y 列表中下標(biāo)相同的數(shù)據(jù)是對(duì)應(yīng)的。例如 x 為 [3, 4]珠插,y 為 [6, 8]惧磺,這表示會(huì)繪制點(diǎn)(3,6)捻撑,(4磨隘, 8)。因此布讹,x 和 y 長(zhǎng)度要一樣琳拭。
annotate
函數(shù)同樣也有兩個(gè)必傳參數(shù),一個(gè)是標(biāo)注內(nèi)容描验,另一個(gè)是 xy白嘁。標(biāo)注內(nèi)容是一個(gè)字符串。xy 表示要在哪個(gè)位置(點(diǎn))顯示標(biāo)注內(nèi)容膘流。xy 位置地選定絮缅。一般是在scatter()
繪制點(diǎn)附近,但不建議重合呼股,這樣會(huì)影響美觀耕魄。
...
# 繪制顏色為藍(lán)色、寬度為 1 像素的連續(xù)曲線 y1
plt.plot(x, y1, color="blue", linewidth=1.0, linestyle="-", label="y1")
# 繪制散點(diǎn)(3, 6)
plt.scatter([3], [6], s=30, color="blue") # s 為點(diǎn)的 size
# 對(duì)(3, 6)做標(biāo)注
plt.annotate("(3, 6)",
xy=(3.3, 5.5), # 在(3.3, 5.5)上做標(biāo)注
fontsize=16, # 設(shè)置字體大小為 16
xycoords='data') # xycoords='data' 是說基于數(shù)據(jù)的值來選位置
# 繪制顏色為紫色彭谁、寬度為 2 像素的不連續(xù)曲線 y2
plt.plot(x, y2, color="#800080", linewidth=2.0, linestyle="--", label="y2")
# 繪制散點(diǎn)(3, 0)
plt.scatter([3], [0], s=50, color="#800080")
# 對(duì)(3, 0)做標(biāo)注
plt.annotate("(3, 0)",
xy=(3.3, 0), # 在(3.3, 0)上做標(biāo)注
fontsize=16, # 設(shè)置字體大小為 16
xycoords='data') # xycoords='data' 是說基于數(shù)據(jù)的值來選位置
點(diǎn)已經(jīng)被標(biāo)注出來了吸奴,如果你還想給點(diǎn)添加注釋。這需要使用text()
函數(shù)缠局。text(x则奥,y,s) 作用是在點(diǎn)(x狭园,y) 上添加文本 s读处。matplotlib 目前好像對(duì)中午支持不是很友好, 中文均顯示為亂碼唱矛。
···
# 繪制散點(diǎn)(3, 0)
plt.scatter([3], [0], s=50, color="#800080")
# 對(duì)(3, 0)做標(biāo)注
plt.annotate("(3, 0)", xy=(3.3, 0))
plt.text(4, -0.5, "this point very important",
fontdict={'size': 12, 'color': 'green'}) # fontdict設(shè)置文本字體
到此為止罚舱,我們基本上完成了繪制直線所有工作井辜。Matplotlib 能繪制種類繁多且繪圖功能強(qiáng)大,所以我接下來的文章將單獨(dú)對(duì)每種類型圖做分享講解管闷。
上篇閱讀:Python 繪圖粥脚,我只用 Matplotlib(一)
推薦閱讀:
爬蟲實(shí)戰(zhàn)二:爬取電影天堂的最新電影
深入理解HTTP