在平時(shí)使用matploglib的時(shí)候式塌,將問題解決方法书在、使用心得甘穿、基本概念等等腮恩,都零零散散做了一些總結(jié),但是一直沒有系統(tǒng)的進(jìn)行過整理扒磁。為了能夠更好的鞏固matplotlib的使用庆揪,將之前的總結(jié)進(jìn)行一次系統(tǒng)化的梳理。
為什么需要數(shù)據(jù)可視化妨托?
無論是工作缸榛,學(xué)習(xí),生活中都會(huì)遇到各種數(shù)據(jù):年度預(yù)算數(shù)據(jù)兰伤,項(xiàng)目人力成本數(shù)據(jù)内颗,實(shí)驗(yàn)記錄數(shù)據(jù),投資收益等等敦腔。當(dāng)直接面對(duì)各種數(shù)據(jù)的時(shí)候均澳,無法直觀的反映出各種數(shù)據(jù)間的關(guān)系,因此就需要借助各種圖表來對(duì)數(shù)據(jù)進(jìn)行可視化的展示。選擇合理的數(shù)據(jù)圖表找前,比用數(shù)據(jù)和文字描述更明了糟袁、更容易理解,將數(shù)據(jù)轉(zhuǎn)換成圖表的形式呈現(xiàn)躺盛,可以幫助我們更好地了解數(shù)據(jù)之間的關(guān)聯(lián)關(guān)系及變化趨勢(shì)项戴,對(duì)問題的研究可以做出合理的推斷和預(yù)測(cè)。
使用不同的圖表從不同的方面來闡述問題槽惫,從不同的角度表現(xiàn)相對(duì)的關(guān)系周叮、數(shù)據(jù)與數(shù)據(jù)之間的聯(lián)系,從而尋找問題更好的解決方法界斜。
如下圖左表格中x,y的數(shù)據(jù)仿耽,單純從數(shù)據(jù)中看無法直觀的看出x,y之間的關(guān)系各薇。但是從右圖可以很直觀的看出x项贺,y之間為正相關(guān)。
matplotlib簡(jiǎn)介
matplotlib使用numpy進(jìn)行數(shù)組運(yùn)算得糜,并調(diào)用一系列其他的Python庫來實(shí)現(xiàn)硬件交互敬扛。matplotlib的核心是一套由對(duì)象構(gòu)成的繪圖API。它利用通用的圖形用戶界面工具包朝抖,如Tkinter, wxPython, Qt或GTK+,向應(yīng)用程序嵌入式繪圖提供了應(yīng)用程序接口(API)谍珊。matplotlib是基于Python語言的開源項(xiàng)目治宣,旨在為Python提供一個(gè)數(shù)據(jù)繪圖包。matplotlib的對(duì)象體系嚴(yán)謹(jǐn)而豐富砌滞,為使用者提供了巨大的發(fā)揮空間侮邀。在熟悉了核心對(duì)象之后,可以輕易的定制圖像贝润。matplotlib的對(duì)象體系也是計(jì)算機(jī)圖形學(xué)的一個(gè)優(yōu)秀范例绊茧。
matplotlib最初由John D. Hunter撰寫,它擁有一個(gè)活躍的開發(fā)社區(qū)打掘,并且根據(jù)BSD樣式許可證分發(fā)华畏。 在John D. Hunter2012年去世前不久,Michael Droettboom被提名為matplotlib的主要開發(fā)者尊蚁。
可以通過官網(wǎng)和源碼可以更加深入的了解matplotlib亡笑。
官網(wǎng):https://matplotlib.org
源碼:https://github.com/matplotlib/matplotlib
matplotlib 可視化的結(jié)構(gòu)
使用matplotlib繪圖,主要掌握figure(畫布)横朋、axes(坐標(biāo)系)仑乌、axis(坐標(biāo)軸)之間的關(guān)系。在matplotlib中,整個(gè)圖像為一個(gè)Figure對(duì)象晰甚。在Figure對(duì)象中可以包含一個(gè)衙传,或者多個(gè)axes對(duì)象。每個(gè)Axes對(duì)象都是一個(gè)擁有自己坐標(biāo)系統(tǒng)的繪圖區(qū)域厕九。
如下圖所示粪牲,在同一個(gè)figure畫布中,存在四個(gè)坐標(biāo)系止剖,對(duì)應(yīng)的每個(gè)坐標(biāo)系都有各自的坐標(biāo)軸腺阳。
舉個(gè)比較形象的例子,一個(gè)畫家需要?jiǎng)?chuàng)作一幅油畫穿香。首先需要在畫框上固定一張畫布上亭引,有了畫布就可以創(chuàng)作任意的作品了,這個(gè)過程就是matplotlib中初始化畫布(figure)皮获;其次焙蚓,需要規(guī)劃在這個(gè)畫布上的布局,是一整幅還是多個(gè)子圖構(gòu)成洒宝?如果是多了子圖就需要為不同的的板塊分配區(qū)域了购公,這個(gè)區(qū)域就對(duì)應(yīng)了matplotlib中為不同的子圖指定的坐標(biāo)系(axes)。對(duì)應(yīng)的畫布中可能會(huì)存在1個(gè)或者多個(gè)坐標(biāo)系雁歌;然后宏浩,在不同的子圖創(chuàng)作完成之后,需要對(duì)邊界進(jìn)行勾勒靠瞎,這個(gè)邊界就對(duì)應(yīng)了matplotlib中的坐標(biāo)軸(axis).
matplotlib的構(gòu)成
matplotlib官網(wǎng)上提供描述其結(jié)構(gòu)的一張圖比庄,為了更方便的了解其內(nèi)容將其中涉及到的內(nèi)容增加了中文的說明。通過這張可以大致了解到通過繪制一張圖所涵蓋的部分乏盐。通過運(yùn)行后面的
相關(guān)代碼
- matplotlib圖的構(gòu)成(圖AnatomyOfMatplotlib):
由于matplotlib對(duì)于中文顯示的支持不太好佳窑,會(huì)導(dǎo)致中文顯示為亂碼。對(duì)于中文字符顯示的解決方案會(huì)在后面進(jìn)行說明
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.ticker import AutoMinorLocator, MultipleLocator, FuncFormatter
#支持中文
matplotlib.rcParams['font.family'] = ['Heiti TC']
np.random.seed(19680801)
X = np.linspace(0.5, 3.5, 100)
Y1 = 3+np.cos(X)
Y2 = 1+np.cos(1+X/0.75)/2
Y3 = np.random.uniform(Y1, Y2, len(X))
fig = plt.figure(figsize=(8, 8))
ax = fig.add_subplot(1, 1, 1, aspect=1)
def minor_tick(x, pos):
if not x % 1.0:
return ""
return "%.2f" % x
#設(shè)置x軸主刻度的位置父能,主刻度標(biāo)簽設(shè)置為1的倍數(shù)
ax.xaxis.set_major_locator(MultipleLocator(1.000))
#設(shè)置x軸次刻度的位置神凑,將每一個(gè)主刻度的區(qū)間等分為4格,如對(duì)應(yīng)圖中第一個(gè)主刻度區(qū)間中0.25何吝,0.50溉委,0.75
ax.xaxis.set_minor_locator(AutoMinorLocator(4))
#設(shè)置y軸主刻度的位置,主刻度標(biāo)簽設(shè)置為1的倍數(shù)
ax.yaxis.set_major_locator(MultipleLocator(1.000))
#設(shè)置y軸次刻度的位置岔霸,將每一個(gè)主刻度的區(qū)間等分為4格
ax.yaxis.set_minor_locator(AutoMinorLocator(4))
#設(shè)置x軸副刻度的文本顯示格式
ax.xaxis.set_minor_formatter(FuncFormatter(minor_tick))
#設(shè)置x軸和y軸的顯示區(qū)間
ax.set_xlim(0, 4)
ax.set_ylim(0, 4)
#設(shè)置主刻度中刻度的長(zhǎng)寬屬性
ax.tick_params(which='major', width=1.0)
ax.tick_params(which='major', length=10)
#設(shè)置次刻度的文本大小薛躬,顏色
ax.tick_params(which='minor', width=1.0, labelsize=10)
ax.tick_params(which='minor', length=5, labelsize=10, labelcolor='0.25')
#顯示網(wǎng)格設(shè)置
ax.grid(linestyle="--", linewidth=0.5, color='.25', zorder=-10)
#按照y1,y2,y3來繪制
ax.plot(X, Y1, c=(0.25, 0.25, 1.00), lw=2, label="Blue signal", zorder=10)
ax.plot(X, Y2, c=(1.00, 0.25, 0.25), lw=2, label="Red signal")
ax.plot(X, Y3, linewidth=0,
marker='o', markerfacecolor='w', markeredgecolor='k')
#設(shè)置圖的標(biāo)題
ax.set_title("Anatomy of a figure", fontsize=20, verticalalignment='bottom')
#設(shè)置x軸lable
ax.set_xlabel("X axis label")
#設(shè)置y軸lable
ax.set_ylabel("Y axis label")
#設(shè)置圖例
ax.legend()
#通過patches和patheffects中的函數(shù)來繪制對(duì)應(yīng)圖中圓圈標(biāo)注的地方
def circle(x, y, radius=0.15):
from matplotlib.patches import Circle
from matplotlib.patheffects import withStroke
circle = Circle((x, y), radius, clip_on=False, zorder=10, linewidth=1,
edgecolor='black', facecolor=(0, 0, 0, .0125),
path_effects=[withStroke(linewidth=5, foreground='w')])
ax.add_artist(circle)
#設(shè)置文本顯示的屬性
def text(x, y, text):
ax.text(x, y, text, backgroundcolor="white",
ha='center', va='top', weight='bold', color='blue')
#對(duì)各個(gè)標(biāo)注點(diǎn)的顯示
# Minor tick
circle(0.50, -0.10)
text(0.50, -0.32, "次刻度標(biāo)簽(Minor tick label)")
# Major tick
circle(-0.03, 4.00)
text(0.03, 3.80, "主刻度(Major tick)")
# Minor tick
circle(0.00, 3.50)
text(0.00, 3.30, "次刻度(Minor tick)")
# Major tick label
circle(-0.15, 3.00)
text(-0.15, 2.80, "主刻度標(biāo)簽(Major tick label)")
# X Label
circle(1.80, -0.27)
text(1.80, -0.45, "x軸標(biāo)簽(X axis label)")
# Y Label
circle(-0.27, 1.80)
text(-0.27, 1.6, "y軸標(biāo)簽(Y axis label)")
# Title
circle(1.60, 4.13)
text(1.60, 3.93, "名稱(Title)")
# Blue plot
circle(1.75, 2.80)
text(1.75, 2.60, "線條(Line)\n(line plot)")
# Red plot
circle(1.20, 0.60)
text(1.20, 0.40, "線條(Line)\n(line plot)")
# Scatter plot
circle(3.20, 1.75)
text(3.20, 1.55, "節(jié)點(diǎn)樣式(Markers)\n(scatter plot)")
# Grid
circle(3.00, 3.00)
text(3.00, 2.80, "網(wǎng)格(Grid)")
# Legend
circle(3.70, 3.80)
text(3.70, 3.60, "圖例(Legend)")
# Axes
circle(0.5, 0.5)
text(0.5, 0.3, "坐標(biāo)系(Axes)")
# Figure
circle(-0.3, 0.65)
text(-0.3, 0.45, "畫布(Figure)")
color = 'blue'
#注解的顯示,圖中右下角spines
ax.annotate('坐標(biāo)軸(Spines)', xy=(4.0, 0.35), xytext=(3.3, 0.5),
weight='bold', color=color,
arrowprops=dict(arrowstyle='->',
connectionstyle="arc3",
color=color))
ax.annotate('', xy=(3.15, 0.0), xytext=(3.45, 0.45),
weight='bold', color=color,
arrowprops=dict(arrowstyle='->',
connectionstyle="arc3",
color=color))
#文本的顯示
ax.text(4.0, -0.4, "參考自官網(wǎng)的簡(jiǎn)介(\nMade with http://matplotlib.org)",
fontsize=10, ha="right", color='.5')
#fig.savefig('./img/AnatomyOfMatplotlib.png')
plt.show()
- 多子圖顯示(圖AxesAxisFig):
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0.0,6.0)
figure,ax=plt.subplots(2,2,figsize=(16,9))
ax[0][0].plot(x,np.sin(np.pi*x));
ax[0][0].set_title("正弦")
ax[0][0].set_xlabel("時(shí)間")
ax[0][0].set_ylabel("幅度")
ax[0][0].set_ylabel("幅度")
ax[0][1].plot(x,np.cos(np.pi*x));
ax[0][1].set_title("余弦")
ax[0][1].set_xlabel("時(shí)間")
ax[0][1].set_ylabel("幅度")
ax[1][0].plot(x,np.log((x+1)*10));
ax[1][0].set_title("指數(shù)")
ax[1][0].set_xlabel("時(shí)間")
ax[1][0].set_ylabel("距離")
ax[1][1].plot(x,x*4);
ax[1][1].set_title("投資")
ax[1][1].set_xlabel("資金")
ax[1][1].set_ylabel("收益")
figure.tight_layout(pad=1.5)
#figure.savefig('./img/Subplots.png')