簡(jiǎn)介
Matplotlib可以說是Python最聲名遠(yuǎn)揚(yáng)的可視化庫了,也是Python數(shù)據(jù)分析庫的“三駕馬車”之一。Matplotlib是基礎(chǔ)而非常強(qiáng)大的可視化庫,Seaborn等好用的可視化庫是在前者的基礎(chǔ)上進(jìn)行的封裝。Matplotlib擅長快速出簡(jiǎn)單的圖、有豐富的接口進(jìn)行精細(xì)化繪圖、和Numpy結(jié)合做科學(xué)可視化及三維圖配合默契、三維圖。但也有些缺點(diǎn),如不容易基于實(shí)用目的繪制有一定難度的圖表(如小提琴圖等)、標(biāo)簽等元素需指定坐標(biāo)而不能自適應(yīng)優(yōu)化顯示、難以實(shí)現(xiàn)交互。
Matplotlib官網(wǎng)說:
Matplotlib tries to make easy things easy and hard things possible.
越用越認(rèn)可這句話,Matplotlib非常強(qiáng)大,Hard things是possible但并非easy and fast。
可視化基礎(chǔ)框架
對(duì)于一個(gè)數(shù)據(jù)表df(通過pandas讀入為DataFrame)來說,用Matplotlib對(duì)其進(jìn)行可視化的基礎(chǔ)框架為:
fig, ax = plt.subplots()
ax.plot(df['x'],df['y'])
通過上面幾行代碼就可以畫出df表周一到周五y指標(biāo)的變化折線。
Matplotlib其實(shí)為作圖提供了兩套可視化接口:
plt.plot()
系列fig, ax = plt.subplots() ax.plot()
系列
根據(jù)官網(wǎng)教程,分別對(duì)應(yīng)MATLAB的陳述式語法和面向?qū)ο髮懛ǎ唧w可參考tutorials:lifecycle.html ,
個(gè)人理解,plt.plot()適合用于快速出圖,讀入一個(gè)數(shù)據(jù)表后想快速知道數(shù)據(jù)分布、指標(biāo)關(guān)系等,通過plt.plot()系列語句直接出圖,而ax.plot()更方便用來精細(xì)繪圖,接口對(duì)各種圖表元素的編輯很友好。
在Matplotlib官網(wǎng)搜索,通常能看到兩套接口,如搜繪制餅圖的關(guān)鍵詞pie
,結(jié)果中的axes.Axes.pie對(duì)應(yīng)ax.pie()的用法,pyplot.pie對(duì)應(yīng)plt.pie()的函數(shù)接口。
ax.×××()的寫法看起來要寫的語句多些,但這種面向?qū)ο?object-oriented)的寫法通過fig, ax = plt.subplots()
建立畫布(figure)和定義軸域(axes),能更明確在哪作畫和映射規(guī)則,給用戶更大的自由度和更精細(xì)的調(diào)參能力。Axes包含了一套坐標(biāo)軸(axis),確定了x/y坐標(biāo)軸之后,數(shù)值再確定對(duì)應(yīng)坐標(biāo),也就唯一確定了所在位置(這是二維情況下,更高維度就會(huì)對(duì)應(yīng)著更多的axis),散點(diǎn)圖是去確定點(diǎn)在軸域下的位置,柱狀圖是確定每個(gè)柱柱所在的位置,因此一套Axes就確定了唯一的獨(dú)立的圖,一個(gè)畫布可以有多套Axes。更具體的辨析可讀姚太多啊的一篇文章,簡(jiǎn)單說就是ax.×××()更方便調(diào)細(xì)節(jié),初學(xué)者盡量避免用plt.×××系列來畫圖。
基礎(chǔ)圖表繪制
數(shù)據(jù)可視化從目的來說,是為了更直觀展示數(shù)據(jù)或數(shù)據(jù)之間的對(duì)比、分布或關(guān)聯(lián)關(guān)系。散點(diǎn)圖、折線圖、柱狀圖、條形圖、餅圖、直方圖是非常常用而基礎(chǔ)的可視化圖。個(gè)人認(rèn)為通過畫這幾種基礎(chǔ)圖并調(diào)細(xì)節(jié)是很好的學(xué)可視化實(shí)踐。
為了整體的美觀和一致性,本文都用了一套自定義配色,通過mpl.rcParams["axes.prop_cycle"] = mpl.cycler('color', ['1EAFAE', 'A3FFFF', '69FFFF'])
語句實(shí)現(xiàn)簡(jiǎn)單改配色,具體關(guān)于mpl.rcParams
后面再展開。
畫散點(diǎn)圖可以用兩種主要的方法,scatter(x,y)
和plot(x,y,'o')
。 通過ax.scatter(x,y)
繪制以x為橫坐標(biāo),y為縱坐標(biāo)的散點(diǎn)圖,scatter的重要參數(shù)如下:
x,y
:對(duì)應(yīng)著x軸和y軸的數(shù)據(jù),散點(diǎn)畫在坐標(biāo)軸里的[xi,yi]處。s,c,alpha
: 對(duì)應(yīng)散點(diǎn)大小(size)、顏色(color)、透明度,都可以傳一個(gè)和點(diǎn)數(shù)量相同長度的數(shù)組,如s=df['z']
可以做氣泡圖,一般氣泡圖為了防止遮蓋問題,通常設(shè)置一定的透明度,alpha的范圍為0到1。c='#BA5C25'
設(shè)置點(diǎn)顏色,c賦值為一個(gè)數(shù)組可以做出每個(gè)點(diǎn)一個(gè)顏色的效果。marker
:設(shè)置點(diǎn)的形狀;cmap
:顏色映射;norm
:當(dāng)顏色c為一組浮點(diǎn)數(shù)時(shí),把值標(biāo)準(zhǔn)化到[0,1]做顏色映射,vmin
和vamx
參數(shù)是結(jié)合norm
來用的;
ax.plot(x,y,'o')
也可以畫散點(diǎn)圖,ax.plot()核心是繪制坐標(biāo)系下的點(diǎn)和點(diǎn)之間的連線的,當(dāng)突出點(diǎn)的大小而省略線時(shí),就是散點(diǎn)圖了,同樣突出線就變成了折線圖。通過fmt(也就是format_string)參數(shù)來控制這些,包括點(diǎn)的形狀、顏色、線的風(fēng)格顏色等。折線圖基礎(chǔ)繪制效果可回看上一部分可視化基礎(chǔ)框架。
plot()的常用參數(shù)如下:
x,y
: x軸和y軸的數(shù)據(jù),當(dāng)plot()只有一個(gè)輸入列表或數(shù)組時(shí),參數(shù)被當(dāng)做y軸,也就是value,x軸以索引自動(dòng)生成,也就是ax.plot(y)
相當(dāng)于ax.plot(range(len(y)),y)
;fmt
: 控制x,y繪制的折線的點(diǎn)形狀、顏色、線的風(fēng)格、顏色;其他的lines.Line2D支持的屬性, 如
color
控制線顏色,marker
控制點(diǎn)形狀,linestyle
控制線風(fēng)格類型及linewidth
控制線寬等,如果既設(shè)置了fmt
又指定了color
呢?可以實(shí)踐一下,線的顏色會(huì)根據(jù)color屬性最終顯示。
plot()除了plot(x,y,[fmt])這種寫法之外,還可以傳多套x,y以繪制多條折線,寫法是plot(x,y,[fmt],x2,y2,[fmt2],…)
。
另外plot()還支持plot('col1','col2',data=df)
這種寫法,這是對(duì)二維表格數(shù)據(jù)更友好的接口。本文講到的其他圖形如bar、barh等基本也都是支持ax.×××(df['x'],df['y']) 和ax.×××(x,y,data)寫法的。
通過ax.bar(x,height)
繪制柱狀圖,條形圖的繪制用ax.barh(y,width)
,因bar和barh的用法很類似,參數(shù)之間有對(duì)應(yīng)關(guān)系,這里結(jié)合著看。
x,height
: x軸的值和各柱的高,相當(dāng)于折線圖的x,y;width
: 柱的寬度,默認(rèn)是0.8,也可以傳入一個(gè)數(shù)組,畫不等寬的柱狀圖;bottom
: 每個(gè)柱底部開始位置,默認(rèn)是0,改bottom可以畫堆積柱狀圖、瀑布圖等;align
: 柱狀的x是在柱底部中心還是邊緣,{'center', 'edge'},默認(rèn)是center;data
: 可以傳入一個(gè)DataFrame,用法和前面說到的ax.plot('col1','col2',data=df)
一致;其他像
color
(柱顏色)、edgecolor
(柱邊框色)、linewidth
(邊框線寬)等圖元屬性用法都一致,linewidth
也是可以簡(jiǎn)寫為lw
的,顏色可以傳一個(gè)數(shù)組,可以畫出五彩斑斕的柱,也可借由這個(gè)參數(shù)美化瀑布圖;條形圖barh的參數(shù)有
barh(y,width,height,left,align)
,y是Y軸的值,每個(gè)柱的位置,因此barh的y對(duì)應(yīng)bar的x,barh的width對(duì)應(yīng)bar的height,barh的height對(duì)應(yīng)bar的width。每個(gè)柱開始的位置是left,對(duì)應(yīng)bar的bottom。align、data、color等一致。
注意的是柱狀圖繪制語句ax.bar(x,height)
的返回值是一個(gè)容器(BarContainer),包含了所有畫出來的柱。通過這個(gè)返回值可以對(duì)柱進(jìn)行一些個(gè)性化的處理,另外的應(yīng)用就是根據(jù)返回柱的屬性給每個(gè)柱標(biāo)上文本標(biāo)簽。
#給柱狀圖標(biāo)上標(biāo)簽
fig,ax= plt.subplots()
rects=ax.bar(df['x'],df['y'])
ax.set_ylim(0,100)
for rect in rects:
height = rect.get_height()
ax.annotate('{}'.format(height),
xy=(rect.get_x() + rect.get_width() / 2, height),
xytext=(0,1), # 1 points vertical offset
textcoords="offset points",
ha='center', va='bottom')
通過給x以一定的偏移量,繪制簇狀柱形圖。代碼如下:
#簇狀柱 ClusterBar
x = list(range(1,len(df)+1))
width = 0.2 #每個(gè)柱的寬度
x1=[i-width for i in x]
x2=[i+width for i in x]
fig, ax = plt.subplots(figsize=(6,5))
rects1 = ax.bar(x1,df['y'], width*2, label='Men',color='#1EAFAE')
rects2 = ax.bar(x2,df['z'], width*2, label='Women',color='#69FFFF')
ax.set_xticks(x)
ax.set_xticklabels(df['x'])
ax.legend()
通過給bottom參數(shù)傳一個(gè)數(shù)組,可以畫堆疊柱狀圖:堆疊柱除了等值堆疊之外,還可以等比堆疊,思路就是將每個(gè)x對(duì)應(yīng)的柱都做一下數(shù)值變換,把柱的高度約束在[0,1],且堆疊之和為1,height=h[i]/sum(h)。
#堆疊柱狀圖
fig,ax= plt.subplots()
ax.bar(df['x'],df['y'],label='Men')
ax.bar(df['x'],df['z'],bottom=df['y'],label='Women')
ax.legend()
#等比例堆疊柱
fig,ax= plt.subplots()
df['y1']=df.apply(lambda x:(x['y'])*100/(x['y']+x['z']),axis=1)
df['z1']=df.apply(lambda x:(x['z'])*100/(x['y']+x['z']),axis=1)
ax.bar(df['x'],df['y1'])
ax.bar(df['x'],df['z1'],bottom=df['y1'])
ax.set_ylim(0,100) #標(biāo)簽設(shè)置等代碼省略
調(diào)節(jié)width
參數(shù)使得柱和柱之間的寬度為0,并對(duì)數(shù)據(jù)進(jìn)行統(tǒng)計(jì)在畫圖,可以用ax.bar()繪制直方圖,但也不需要這么復(fù)雜,Matplotlib提供了繪制直方圖的接口ax.hist(x,bins,normed)
,可以直接對(duì)某列數(shù)據(jù)繪制直方圖。x是需要統(tǒng)計(jì)分布的數(shù)據(jù)列,bins控制分箱的個(gè)數(shù),默認(rèn)是10。
箱線圖在數(shù)據(jù)分析中挺常用的,箱線圖對(duì)于數(shù)據(jù)分布有很好的展示作用,Matplotlib提供了boxplot(x)
用于繪制箱線圖。
fig, ax= plt.subplots()
ax.boxplot(df['y']) #箱線圖
餅圖是可視化中基礎(chǔ)而重要的圖形,是各種數(shù)據(jù)報(bào)告的常客,Matplotlib繪制餅圖時(shí)因?yàn)閤y軸默認(rèn)比例尺不同,為了得到不扁的餅,需設(shè)置xy軸1像素對(duì)應(yīng)的值相等。
#繪制餅圖
fig,ax=plt.subplots(subplot_kw=dict(aspect="equal"))
ax.pie(df['y']) #為了得到不扁的餅,設(shè)置xy軸比例尺相同
#---
#環(huán)狀圖
fig, ax = plt.subplots(subplot_kw=dict(aspect="equal"))
wps=dict(width=0.3, edgecolor='w')
ax.pie(df['y'], radius=1,startangle=90,counterclock=False,wedgeprops=wps)
ax.pie(df['z'], radius=1-0.3,startangle=90,counterclock=False,wedgeprops=wps)
圖表元素調(diào)校
一張可視化圖上除了主要的點(diǎn)、線、面之外,文本標(biāo)簽、坐標(biāo)軸標(biāo)簽等也是很重要的可視媒介,特別是對(duì)于信息圖表而言。 下面這張圖基本囊括了用到的圖形元素
加文本可以通過 ax.text(x,y, "Text")
。添加標(biāo)題通常寫ax.set_title()
,另外也可以用ax.title.set_text('title')
或ax.set(title='ttl')
設(shè)置標(biāo)題, 整理如下:
ax.text(x,y, "Text")
:在坐標(biāo)[x,y]處添加文本Text,文本支持latex公式,如ax.text(2,6, r'$E=mc^2$', fontsize=15)
;ax.set_title()
:添加標(biāo)題;ax.set_ylim(0,4)
設(shè)置y軸值的范圍(類似于函數(shù)的值域),例如對(duì)于y=[],直接ax.plot(y)畫出來的折線圖y軸范圍是 ,通過ax.set_ylim(0,4)
可以顯示0~100范圍的效果。同理通過ax.set_ylim(0,4)
設(shè)置x軸范圍(定義域);ax.set_ylabel("Y axis label")
:給y軸加上坐標(biāo)軸標(biāo)題;ax.tick_params(which='major', width=1.0)
:細(xì)調(diào)坐標(biāo)軸刻度;ax.legend()
: 設(shè)置圖例 ;
圖形元素設(shè)置除了文本類型之外,也可以往里加形狀 。
加線:
import matplotlib.lines as lines;ax.add_artist(lines.Line2D([15,15], [0, 10],color='#1EAFAE'))
,其效果可參考矩陣圖繪制效果;加帶箭頭的線:
ax.arrow(0, 0, 0.5, 0.5, head_width=0.05, head_length=0.1, fc='k', ec='k')
;加一個(gè)垂直的平均線:
ax.axvline(x, ls='--', color='r')
,那水平平均線呢?axhline(y=0, xmin=0, xmax=1, **kwargs)
;加垂直或水平的強(qiáng)調(diào)矩形:
ax.axhspan(ymin, ymax, xmin=0, xmax=1, **kwargs)
和ax.axvspan(xmin, xmax, ymin=0, ymax=1, **kwargs)
;加矩形:
patches.append(mpatches.Rectangle([0.5, 0.5], 0.5,0.8))
,可用于繪制甘特圖;加圓形(及橢圓):
patches.append( mpatches.Ellipse((x,y), width, height))
;加帶箭頭的形狀:
ax.annotate('箭頭文本', xy=(4,5), xytext=(3,2),color, arrowprops=dict( arrowstyle='->', connectionstyle="arc3"))
,加圖標(biāo)型的箭頭:patches.append( mpatches.Arrow(x,y, dx,dy,width))
;加圖片:
mpimg.imread(ipath); ax.axis('off'); ax.imshow(img)
;
給散點(diǎn)圖加標(biāo)簽并加分隔線繪制矩陣圖以實(shí)踐一下以上方法:
import matplotlib.lines as lines
fig, ax= plt.subplots()
ax.plot(df['z'],df['y'],'o')
ax.add_artist(lines.Line2D([70,70], [30,100],color='#000000',lw=3)) #是[x1,x2],[y1,y2] 不是[x1,y1],[x2,y2]
ax.add_artist(lines.Line2D([30,100], [65,65],color='#000000',lw=3))
ax.set_xlim(30,100)
ax.set_ylim(30,100)
ax.set_xlabel("z")
ax.set_ylabel("y")
繪制瀑布圖綜合運(yùn)用ax.bar()的參數(shù)和文本標(biāo)簽,并封裝為一個(gè)函數(shù),以后使用只需要調(diào)用就好:
#瀑布圖
x=[17,-3,7,6] #原始數(shù)據(jù)
def waterfall_chart(x):
j=0 #sum(x) 最終柱的結(jié)果
k=0 #k=x[i-1]
x0=[]
for i in x:
if i<0:
x0.append(j+i)
else:
x0.append(j)
j+=i
x1=[abs(i) for i in x]
c1=['#1EAFAE' if i>0 else '#69FFFF' for i in x]
c1.append('#BA5C25')
x0[0]=0
x0.append(0)
x1.append(j)
x.append(j)
w=list(range(1,len(x)+1))
fig,ax= plt.subplots(figsize=(6,5))
ax.bar(w,x0,alpha=0) #都透明度為0了,顏色不重要
rects=ax.bar(w,x1,bottom=x0,color=c1) #顏色可傳一個(gè)數(shù)組的
ax.set_ylim(0, 30)
i=0
for rect in rects: #加上適當(dāng)?shù)奈谋緲?biāo)簽
height = rect.get_height()+x0[i]
ax.annotate('{}'.format(x[i]),
xy=(rect.get_x() + rect.get_width() / 2, height),
xytext=(0,1), # 1 points vertical offset
textcoords="offset points",
ha='center', va='bottom')
i+=1
ax.set_xticklabels(['','Q1','Q2','Q3','Q4','Ys'])
return ax
waterfall_chart(x)
組合圖
為了更好地展現(xiàn)數(shù)據(jù)間的聯(lián)系或變化,我們有時(shí)會(huì)需要將多種圖表類型用在同一張可視化圖里,一種是共用坐標(biāo)軸的組合圖,例如面積圖+柱狀圖的組合、散點(diǎn)+折線圖就是很基礎(chǔ)的組合圖。另一種是雙坐標(biāo)軸,很常見的圖是左邊的y軸是月活,畫柱狀圖,右邊的y軸是增長率,畫折線圖。
棒棒糖圖(Lollipop)是將條形圖的柱變得很細(xì)并突出末端的一類圖,形似棒棒糖,特別適合于展示分類標(biāo)簽很多的數(shù)據(jù)。可以通過將柱狀圖和散點(diǎn)圖結(jié)合的方法繪制,Matplotlib庫繪制起來并不復(fù)雜,代碼如下。但對(duì)于一些散點(diǎn)圖的y軸不支持分類標(biāo)簽的庫來說,要畫棒棒糖圖還是挺復(fù)雜的。
y = [5, 4, 11, 10, 15, 11, 13, 8,13,15,13,19]
x=['c'+str(i) for i in range(len(y))]
fig, ax= plt.subplots(figsize=(6,6))
ax.barh(x,y,height=0.08,zorder=1) #圖層順序的解決方案
ax.scatter(y,x,zorder=2,color='#ba5c25')
有時(shí)為了對(duì)比兩類數(shù)據(jù),除了用簇狀柱形圖或簇狀條形圖外,也可以試試啞鈴圖,理解了上面畫棒棒糖圖的方法之后,要組合出啞鈴圖并不難,對(duì)數(shù)據(jù)進(jìn)行一定運(yùn)算后用barh加兩個(gè)scatter就可以畫出來。
帕累托圖是雙坐標(biāo)軸的可視化典例。帕累托圖特別適合展示符合長尾效應(yīng)的數(shù)據(jù)。matplotlib給我們提供了ax.twinx()
用于生成共用x軸的另一個(gè)Axes,效果就是左邊的y軸比例尺和右邊比例尺不一定一樣,能更好地將兩類圖進(jìn)行效果組合。
y=[23,162,51,119,12,3,8] #模擬數(shù)據(jù)
x=[str(i) for i in range(2,len(y)+2)]
y=sorted(y,reverse=True)
ysum=sum(y)
y2=[]
cc=0
for i in y:
cc+=i
y2.append(cc/ysum*100)
fig = plt.figure()
ax1 = fig.add_subplot(111)
rects=ax1.bar(x,y,color='#1EAFAE')
ax1.set_ylabel('Month IC')
ax1.set_ylim(0, 180)
ax2 = ax1.twinx()
#https://matplotlib.org/api/_as_gen/matplotlib.axes.Axes.twinx.html#matplotlib.axes.Axes.twinx
ax2.set_ylim(0, 100)
ax2.plot(x, y2,'o',color='#FFA069',linewidth=2,ls='-')
ax2.set_ylabel('%')
for rect in rects:
height = rect.get_height()
ax1.annotate('{}'.format(height),
xy=(rect.get_x() + rect.get_width() / 2, height),
xytext=(0,1), # 1 points vertical offset
textcoords="offset points",
ha='center', va='bottom')
ax1.set_title("Pareto in Matplotlib")
子圖
除了組合圖外,有時(shí)候我們也需要將多個(gè)圖并排以展現(xiàn)某種數(shù)據(jù)關(guān)系。前面說過一個(gè)畫布下可以有多套Axes,正常情況下我們只需要一套Axes用來畫圖,但是也經(jīng)常需要在一個(gè)畫布中畫多張圖,形成分面或子母圖的效果,前面我們基本都是寫fig, ax= plt.subplots()
,實(shí)際上subplots()
可以設(shè)置nrows、ncols參數(shù)生成多套Axes。
plt.subplots()的常用寫法有:
plt.subplot(3,2,4)
:在全局繪圖區(qū)域中建立3行、2列的分區(qū)繪圖區(qū)域,并定位到第4個(gè)子圖區(qū)域,返回一個(gè)axes;plt.subplot(324)
: 效果和上面subplot(3,2,4)的寫法一致;plt.subplots()
: 默認(rèn)1行1列,生成的axes就是一個(gè);plt.subplots(3,2)
: 沒有指定繪圖編號(hào),返回值包括一個(gè)figure和多個(gè)axes,和ax[0, 0].×××(x, y)
搭配著用;fig = plt.figure(); ax= fig.add_subplot(221)
:先建立一個(gè)畫布,在畫布上添加2x2個(gè)子圖,并定位到順序第一個(gè)子圖;
圖中代碼在全局繪圖區(qū)域中建立n行、m列的分區(qū)繪圖區(qū)域,并定位到其中一個(gè)子圖區(qū)域。之后ax的用法和前面一致,不贅述。
生成的圖片在shell環(huán)境中彈出的界面有保存圖片的按鍵,在jupyter環(huán)境中可以點(diǎn)擊圖片然后右鍵保存。而如果要通過代碼保存圖片到本地,一般通過plt.savefig(fname,dpi=300)
保存圖片,參數(shù)有文件保存路徑(fname)、圖片每英寸像素(dpi)、邊緣顏色(edgecolor)等。在shell環(huán)境中一般通過plt.show()展示圖片,而jupyter notebook中通常寫%matplotlib inline
將圖片直接在Out[]里輸出展示。
Matplotlib的rcParams接口可以設(shè)置很多個(gè)性化內(nèi)容,包括剛提到的savefig的edgecolor默認(rèn)值,可以寫mpl.rcParams["savefig.edgecolor"]='blue'
改變?cè)瓉淼哪J(rèn)值white。直方圖的默認(rèn)分箱數(shù)可以通過rcParams["hist.bins"]=5
改變。
而為了在Matplotlib中支持中文,各教程的解決方案基本都有mpl.rcParams['font.family']='SimHei'
這句,就是將Matplotlib的字體替換為微軟雅黑。前面基礎(chǔ)圖表繪制部分通過更新mpl.rcParams["axes.prop_cycle"]改變了繪圖的主題色,Matplotlib本身是提供了備選的繪圖渲染的各種主題,可以通過style.use('ggplot')
調(diào)用ggplot主題(想換回默認(rèn)主題用style.use('default')
)。就像給輸入法換皮膚一樣,rcParams接口給了我們更多的自由度和個(gè)性化。
三維及科學(xué)可視化
三維可視化和科學(xué)可視化是Matplotlib特別擅長的領(lǐng)域,人類作為三維生物,對(duì)三維的圖像有一定的偏好,扁平化和三維各有優(yōu)勢(shì),各有不同的應(yīng)用場(chǎng)合,能畫好二維可視化圖也該會(huì)畫三維的圖表,且一些場(chǎng)景用好三維有奇效。Matplotlib的三維可視化封裝在mpl_toolkits工具套件的mplot3d
里,mplot3d下的API主要包括Axes3D(三維坐標(biāo)軸區(qū)域)、art3d.xx3D(三維圖元)和proj3d(三維坐標(biāo)變換)。
from mpl_toolkits.mplot3d import Axes3D # noqa: F401 unused import
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.bar(df['x'],df['y'], zs=0, zdir='y', alpha=0.8)
ax.bar(df['x'],df['z'], zs=1, zdir='y', alpha=0.8)
ax.bar(df['x'],df['y'], zs=2, zdir='y', alpha=0.8)
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
ax.set_yticks([0,1,2])
三維可視化和科學(xué)可視化聯(lián)系很緊密,科研作圖中應(yīng)用廣泛,各種漂亮的參數(shù)曲面在官網(wǎng)示例里有很多,這里略過、當(dāng)然二維下也能畫出很優(yōu)美的函數(shù)圖像,結(jié)合numpy生成[0,2]之間的正弦函數(shù)曲線只需要4行代碼:
t = np.arange(0.0, 2.0, 0.01)
s = 1 + np.sin(2 * np.pi * t)
fig, ax = plt.subplots()
ax.plot(t, s)
繪制指數(shù)函數(shù)、分形的雪花曲線也是類似的過程,在官網(wǎng)案例集有類似的例子,具體這里不展開。
總結(jié)下本文從Matplotlib的可視化基礎(chǔ)框架一步步畫散點(diǎn)、折線、柱狀、箱線等圖,通過理解參數(shù)拓展畫了瀑布圖、矩陣圖、棒棒糖圖等,并且微調(diào)坐標(biāo)軸文本、標(biāo)題等圖形元素,讓可視化更完備,通過雙y軸繪制帕累托圖等組合圖,也繪制了包含多張子圖的圖和三維圖。
通過以上實(shí)踐可以看到的Matplotlib可視化語法的特點(diǎn)是繪圖對(duì)象和標(biāo)簽標(biāo)題等元素有一定獨(dú)立性,且有不同層級(jí)的接口可以用來微調(diào)元素,例如設(shè)置標(biāo)題就有多種寫法 ,Matplotlib不同于ggplot2的管道寫法、也不同于Altair等庫將數(shù)據(jù)傳到chart對(duì)象再調(diào)用mark_bar()等確定繪制什么圖。可視化是要好看,也不能忘了所展現(xiàn)的數(shù)據(jù)與數(shù)據(jù)間的關(guān)系是重點(diǎn)。
文中代碼更新于QLWeilcf/VisualizedLyn。本文七千多字,從基礎(chǔ)圖表入手拆解對(duì)應(yīng)繪制函數(shù)的重點(diǎn)參數(shù),一共22張圖,基本都是個(gè)人繪制和排版的,個(gè)人認(rèn)為較系統(tǒng)講了Matplotlib的用法和核心功能,下篇會(huì)實(shí)踐更有趣的內(nèi)容。
有任何建議歡迎留言交流。
最后用極坐標(biāo)繪心形線結(jié)束本文。
#極坐標(biāo)繪心形線
import numpy as np
theta= np.arange(0, 2*np.pi, 0.05)
r=5*(1-np.sin(theta)) #a取5
ax = plt.subplot(111, projection='polar')
ax.plot(theta, r,lw=3)
ax.grid(True)
ax.text(1.56,6,'r=a(1-sinθ)',ha='center',
fontsize=18,color='#1EAFAE')