Matplotlib是 Python 最著名的2D繪圖庫与倡,提供了豐富的數據繪圖工具,主要用于繪制一些統計圖形昆稿。Matplotlib可用于Python腳本纺座,Python和IPython shell,Jupyter筆記本溉潭,Web應用程序服務器和四個圖形用戶界面工具包净响。
相信初接觸matplotlib肯定會有些困惑,同樣一個目標有多個解決方案喳瓣,有人用plt.xx
馋贤,有人用ax.xx
,對小白及其不友好畏陕,照葫蘆畫瓢搞出來了配乓,但不明白為什么,寫出來的代碼很混亂惠毁。下次遇到問題依然一頭霧水犹芹。我也是這樣,所以鞠绰,花時間讀了很多文章腰埂,整理了一下知識點,入門夠用了蜈膨。另盐固,涉及到的文章都貼出了鏈接,可以一并閱讀丈挟,加深理解。
matplotlib架構
matplotlib的架構分為以下三層
- Scripting (腳本)層
- Artist (表現)層志电。擁有許多可視化元素曙咽,如figure、axes挑辆、axis等元素例朱。
- Backend (后端)層孝情。包含 pyplot 和 pylab 模塊(已棄用,不推薦)
它們之間的訪問關系是:
Scripting 訪問 Artist洒嗤, Artist 訪問 Backend
理論上各層都可以畫出相同的圖形箫荡,但越底層的操作越細節(jié)越困難,越高層越易于人機交互渔隶,越容易羔挡。也就是說上層是下層的封裝,把一些不需要打交道的事情封裝好间唉,實際畫圖只關心效果即可绞灼。
matplotlib兩種繪圖API
在Matplotlib庫中提供了兩種風格的API供開發(fā)者使用。這也就是為什么有人用plt.xx
呈野,有人用ax.xx
的原因低矮。好的代碼應該堅持使用一種風格,否則會顯得混亂被冒,閱讀起來困難军掂,不利于維護。
- Pyplot編程接口(state-based)
不推薦
- 面向對象的編程接口(object-based)
推薦
之前有三種api昨悼,還有一種pylab api蝗锥,模仿matlab的工作方式,但大量導入全局命名方式導致意外行為幔戏,被認為是糟糕的風格玛追,matplotlib最新版中已棄用此方式。理解matplotlib闲延、pylab與pyplot之間的關系
另外痊剖,pandas自帶的df.plot()方法也可以繪制簡單的圖形,它是使用matplotlib庫的plot()方法的簡單包裝實現的垒玲。最好不要用陆馁,pandas作為數據分析來用,繪圖就交給matplotlib等專業(yè)的繪圖庫來做合愈。下文也介紹一下叮贩,下次看到這種解決方案可以心中有數,不迷惑佛析。
matplotlib:先搞明白plt. /ax./ fig再畫
matplotlib圖像的結構
在matplotlib中,整個圖像為一個Figure對象寸莫,相當于畫板捺萌。在Figure對象中可以包含一個或者多個Axes對象(畫紙)。每個Axes(ax)對象都是一個擁有自己坐標系統axis的繪圖區(qū)域膘茎。
以兩個例子來介紹兩種方法的使用桃纯。下面兩幅圖分別用pyplot編程接口和面向對象編程接口實現酷誓。單子圖、多子圖都涉及到了态坦,用法在代碼里表達的很清楚了盐数。
單子圖柱狀圖
多子圖柱狀圖
一些其他圖形如折線圖、散點圖伞梯、餅圖等跟示例的柱狀圖大同小異玫氢,各種參數自行學習。不容錯過的Matplotlib常見用法小結 非常全面的Matplotlib畫圖方法壮锻、Matplotlib 1.4W+字教程的圖形繪制部分
- plot 折線圖
- bar 柱狀圖
- barh 條形圖
- hist 直方圖
- pie 餅圖
- boxplot 箱形圖
- scatter 散點圖
- polar 極坐標圖
Pyplot編程接口(state-based)不推薦
Pyplot封裝了底層的繪圖函數提供了一種繪圖環(huán)境琐旁,當使用plt.xx繪制圖形的時候,默認的Figure以及Axes等對象會自動創(chuàng)建以支持圖形的繪制猜绣。此方式屏蔽了一些底層通用的繪圖對象的創(chuàng)建細節(jié)灰殴,書寫簡潔。另外掰邢,pyplot是有狀態(tài)的牺陶,亦即它會保存當前圖片和作圖區(qū)域的狀態(tài),新的作圖函數會作用在當前圖片的狀態(tài)基礎之上辣之,代碼的位置要注意掰伸。遇到一些比較復雜的圖時不方便。官方推薦使用面向對象方式繪圖怀估。
import numpy as np
import matplotlib.pyplot as plt
# 準備數據
dog = (20, 28, 22, 30)
cat = (25, 32, 20, 27)
ind = np.arange(len(dog)) # 生成0-3的數組狮鸭,用于x軸刻度值
quarter = ['一季度','二季度','三季度','四季度']
width = 0.35 # 圖形柱的寬度
#################################################
# 一個子圖
# 繪圖
# x的位置調節(jié)好,不然兩個柱會重疊
plt.bar(ind - width/2, dog, width, label='Dog')
plt.bar(ind + width/2, cat, width, label='Cat')
# 調節(jié)組件
plt.ylabel('銷售額(萬)')
plt.title('各季度貓狗產業(yè)銷售額')
plt.xticks(ind,quarter)
plt.legend(loc=2)
# 保存圖形
plt.savefig('matplotlib_pyplot方式單子圖.png')
#################################################
#################################################
# 多個子圖多搀。有狀態(tài)歧蕉,細節(jié)調整需在各個subplot內調節(jié)
# 繪圖 第一個子圖
plt.subplot(121) #1行2列,占用第一個
plt.bar(ind, dog, width, color='dodgerblue', label='Dog')
# 調節(jié)組件
plt.ylabel('銷售額(萬)')
plt.title('各季度狗產業(yè)銷售額')
plt.xticks(ind,quarter)
# 繪圖 第二個子圖
plt.subplot(122) #1行2列康铭,占用第二個
plt.bar(ind, cat, width, color='darkorange', label='Cat')
# 調節(jié)組件
plt.ylabel('銷售額(萬)')
plt.title('各季度貓產業(yè)銷售額')
plt.xticks(ind,quarter)
# 保存圖形
plt.savefig('matplotlib_pyplot方式多子圖.png')
#################################################
# 交互展示
plt.show()
面向對象的編程接口(object-based)推薦
面向對象的繪圖方式主要使用matplotlib的兩個子類:matplotlib.figure.Figure和matplotlib.axes.Axes惯退。我們需要自己創(chuàng)建figure(畫板),axes(畫紙)从藤。畫板(figure)為matplotlib.figure.Figure的一個實例催跪,每個子圖(畫紙,axes)為matplotlib.axes.Axes的一個實例夷野,分別可以繼承父類的所有方法懊蒸,也就是說你繪圖時,你想設置的元素(網格線啊悯搔,坐標刻度啊等)都可以在二者的屬性中找出來使用榛鼎。使用面向對象編程接口有利于我們對于圖形繪制的完整控制,處理復雜圖形更有優(yōu)勢。但是相對于Pyplot接口可能需要書寫更多的代碼者娱。
import numpy as np
import matplotlib.pyplot as plt
# 準備數據
dog = (20, 28, 22, 30)
cat = (25, 32, 20, 27)
ind = np.arange(len(dog)) # 生成0-3的數組,用于x軸刻度值
quarter = ['一季度','二季度','三季度','四季度']
width = 0.35 # 圖形柱的寬度
#################################################
# 一個子圖
# 繪圖
fig, ax = plt.subplots() # 實例畫板fig畫紙ax
# x的位置調節(jié)好苏揣,不然兩個柱會重疊
ax.bar(ind - width/2, dog, width, label='Dog')
ax.bar(ind + width/2, cat, width, label='Cat')
# 調節(jié)組件
ax.set_ylabel('銷售額(萬)')
ax.set_title('各季度貓狗產業(yè)銷售額')
ax.set_xticks(ind)
ax.set_xticklabels(quarter)
ax.legend(loc=2)
# 保存圖形
fig.savefig('matplotlib_兩種繪圖api比較示例_單子圖.png')
#################################################
#################################################
# 多個子圖黄鳍。無狀態(tài),ax[0]平匈,ax[1]代表各子圖
# 繪圖
fig, ax = plt.subplots(1,2) #(1,2)代表1行2列兩個區(qū)域
# 設置圖形對象 :窗口
# ax[0]代表第一個子圖框沟,ax[1]代表第二個子圖
ax[0].bar(ind, dog, width, color='dodgerblue', label='Dog')
ax[1].bar(ind, cat, width, color='darkorange', label='Cat')
# 調節(jié)組件
ax[0].set_ylabel('銷售額(萬)')
ax[0].set_title('各季度狗產業(yè)銷售額')
ax[0].set_xticks(ind)
ax[0].set_xticklabels(quarter)
ax[1].set_ylabel('銷售額(萬)')
ax[1].set_title('各季度貓產業(yè)銷售額')
ax[1].set_xticks(ind)
ax[1].set_xticklabels(quarter)
# 保存圖形
fig.savefig('matplotlib_兩種繪圖api比較示例_多子圖.png')
#################################################
# 交互展示
plt.show() # 面向對象接口不能使用交互式的show()方法對圖像直接進行顯示。如果想交互顯示增炭,需要用pyplot方式
pandas自帶df.plot()方法 不要用
pandas自帶的df.plot()方法也可以繪制簡單的圖形忍燥,它是使用matplotlib庫的plot()方法的簡單包裝實現的。最好不要用隙姿,pandas作為數據分析來用梅垄,繪圖就交給matplotlib等專業(yè)的繪圖庫來做。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
# 準備數據
dog = (20, 28, 22, 30)
cat = (25, 32, 20, 27)
data = {
'Dog': dog,
'Cat': cat}
ind = np.arange(len(dog)) # 生成0-3的數組输玷,用于x軸刻度值
quarter = ['一季度','二季度','三季度','四季度']
width = 0.35 # 圖形柱的寬度
# 生成DataFrame
df = pd.DataFrame(data,index=ind)
# df.plot()方法繪圖队丝。kind代表繪圖類型
ax = df.plot(kind='bar')
# 調節(jié)組件
ax.set_ylabel('銷售額(萬)')
ax.set_title('各季度貓狗產業(yè)銷售額')
ax.set_xticks(ind)
ax.set_xticklabels(quarter)
ax.legend(loc=2)
# 交互展示
plt.show()
matplotlib組件詳解
在matplotlib中,整個圖像為一個Figure對象欲鹏。在Figure對象中可以包含一個或者多個Axes對象机久。每個Axes(ax)對象都是一個擁有自己坐標系統的繪圖區(qū)域。
matplotlib的圖的構成元素
- 坐標軸(axis)
- 坐標軸名稱(axis label)
- 坐標軸刻度(tick)
- 坐標軸刻度標簽(tick label)
- 坐標軸邊界(lim)
- 網格線(grid)
- 圖例(legend)
- 標題(title)
- 邊框(spine)
中文亂碼膘盖、負號顯示
設置標題 ax.set_title()
單子圖用
ax.
,多子圖用ax[].
ax.set_title('標題',fontdict={'size':16},loc = 'left') #設置16px的字體大小袄膏,將標題顯示在左側
設置邊框(spine) ax.spines
默認圖表中會顯示上下左右四條spine践图,可根據需要設置為不顯示
ax.spines['right'].set_visible(False) #去除右邊的spines
ax.spines['bottom'].set_color('r') #設置底部的spines為紅色
設置坐標軸相關
設置坐標軸名稱
ax.set_xlabel('季度',fontsize=16)
ax.set_xlabel('銷售額',fontsize=16)
設置坐標軸刻度標簽
# 更改刻度標簽。此例將0沉馆,1码党,2,3更改為一季度斥黑,二季度揖盘,三季度,四季度
ax.set_xticks(ind)
ax.set_xticklabels(quarter)
# 設置刻度標簽屬性
# axis : 可選{‘x’, ‘y’, ‘both’} 锌奴,選擇對哪個軸操作兽狭,默認是’both’
# labelsize設置刻度標簽的大小
# direction{‘in’, ‘out’, ‘inout’}刻度線的方向
# color : 刻度線的顏色
# labelcolor : 刻度值顏色
ax.tick_params(axis = 'y', labelsize=14,direction='in',labelcolor='r')
設置刻度間隔
#從pyplot導入MultipleLocator類,這個類用于設置刻度間隔
from matplotlib.pyplot import MultipleLocator
#把x軸的刻度間隔設置為1,并存在變量里
x_major_locator=MultipleLocator(1)
#把y軸的刻度間隔設置為10箕慧,并存在變量里
y_major_locator=MultipleLocator(10)
#把x軸的主刻度設置為1的倍數
ax.xaxis.set_major_locator(x_major_locator)
#把y軸的主刻度設置為10的倍數
ax.yaxis.set_major_locator(y_major_locator)
設置坐標軸邊界
ax.set_xlim([0,12]) # x軸邊界
ax.set_ylim([0,50]) # y軸邊界
設置圖例 ax.legend()
圖例是對圖形所展示的內容的解釋服球,比如在一張圖中畫了三條線,那么這三條線都代表了什么呢颠焦?這時就需要做點注釋斩熊。
兩種方式設置圖例
# 第一種
# 繪圖的時候加上label,之后調用ax.legend()
ax.bar(ind - width/2, dog, width, label='Dog')
ax.bar(ind + width/2, cat, width, label='Cat')
ax.legend()
# 第二種
# 使用ax.legend()按順序設置好圖例
ax.bar(ind - width/2, dog, width)
ax.bar(ind + width/2, cat, width)
ax.legend(['Dog','Cat'])
圖例位置
loc參數用來規(guī)定圖例的位置
如:將圖例放在左上角:ax.legend(loc=2)
圖例各位置如下
- 0: ‘best'
- 1: ‘upper right'
- 2: ‘upper left'
- 3: ‘lower left'
- 4: ‘lower right'
- 5: ‘right'
- 6: ‘center left'
- 7: ‘center right'
- 8: ‘lower center'
- 9: ‘upper center'
- 10: ‘center'
設置網格線 ax.grid()
網格線多用于輔助查看具體的數值大小,橫縱坐標都可以設置相應的網格線伐庭,視具體情況而論粉渠。
# b參數設置是否顯示網格
# linestyle:線型
# color:顏色
# linewidth:寬度
# axis:x,y圾另,both霸株,顯示x/y/兩者的格網。默認both
ax.grid(b = True, linestyle = "--",color = "gray", linewidth = "0.5",axis = 'y')
設置背景顏色
設置整個圖像背景顏色
fig.set_facecolor('white')
設置某個子圖背景顏色
ax.set_facecolor('white')
保存圖像 fig.savefig
保存圖像的時候可以設置分辨率
fig.savefig('xxx.png',dpi=300)
交互展示 ax.show()
顯示最終繪制的圖像
ax.show()