Matplotlib可以說是Python最聲名遠揚的可視化庫了,也是Python數據分析庫的“三駕馬車”之一。Matplotlib是基礎而非常強大的可視化庫,Seaborn等好用的可視化庫是在前者的基礎上進行的封裝。Matplotlib擅長快速出簡單的圖、有豐富的接口進行精細化繪圖、和Numpy結合做科學可視化及三維圖配合默契、三維圖。但也有些缺點,如不容易基于實用目的繪制有一定難度的圖表(如小提琴圖等)、标簽等元素需指定坐标而不能自适應優化顯示、難以實現交互。
官網說:
Matplotlib tries to make easy things easy and hard things possible.
我越用越認可這句話,Matplotlib非常強大,Hard things是possible但并非easy and fast。
Matplotlib出圖示例
可視化基礎框架對于一個數據表df(通過pandas讀入為DataFrame)來說,用Matplotlib對其進行可視化的基礎框架為:
fig, ax = plt.subplots() ax.plot(df['x'],df['y'])
通過上面幾行代碼就可以畫出df表周一到周五y指标的變化折線。
折線圖繪制示例
Matplotlib其實為作圖提供了兩套可視化接口:
- plt.plot()系列
- fig, ax = plt.subplots() ax.plot() 系列
根據官網教程,分别對應MATLAB的陳述式語法和面向對象寫法,
個人理解,plt.plot()适合用于快速出圖,讀入一個數據表後想快速知道數據分布、指标關系等,通過plt.plot()系列語句直接出圖,而ax.plot()更方便用來精細繪圖,接口對各種圖表元素的編輯很友好。
在Matplotlib官網搜索,通常能看到兩套接口,如搜繪制餅圖的關鍵詞pie,結果中的axes.Axes.pie對應ax.pie()的用法,pyplot.pie對應plt.pie()的函數接口。
ax.×××()的寫法看起來要寫的語句多些,但這種面向對象(object-oriented)的寫法通過fig, ax = plt.subplots()建立畫布(figure)和定義軸域(axes),能更明确在哪作畫和映射規則,給用戶更大的自由度和更精細的調參能力。Axes包含了一套坐标軸(axis),确定了x/y坐标軸之後,數值再确定對應坐标,也就唯一确定了所在位置(這是二維情況下,更高維度就會對應着更多的axis),散點圖是去确定點在軸域下的位置,柱狀圖是确定每個柱柱所在的位置,因此一套Axes就确定了唯一的獨立的圖,一個畫布可以有多套Axes。簡單說就是ax.×××()更方便調細節,初學者盡量避免用plt.×××系列來畫圖。
基礎圖表繪制
數據可視化從目的來說,是為了更直觀展示數據或數據之間的對比、分布或關聯關系。散點圖、折線圖、柱狀圖、條形圖、餅圖、直方圖是非常常用而基礎的可視化圖。個人認為通過畫這幾種基礎圖并調細節是很好的學可視化實踐。
将數據映射為可視圖表
為了整體的美觀和一緻性,本文都用了一套自定義配色,通過mpl.rcParams["axes.prop_cycle"] = mpl.cycler('color', ['1EAFAE', 'A3FFFF', '69FFFF']) 語句實現簡單改配色,具體關于mpl.rcParams後面再展開。
畫散點圖可以用兩種主要的方法,scatter(x,y)和plot(x,y,'o') 。 通過ax.scatter(x,y)繪制以x為橫坐标,y為縱坐标的散點圖,scatter的重要參數如下:
- x,y:對應着x軸和y軸的數據,散點畫在坐标軸裡的[xi,yi]處。
- s,c,alpha: 對應散點大小(size)、顔色(color)、透明度,都可以傳一個和點數量相同長度的數組,如s=df['z']可以做氣泡圖,一般氣泡圖為了防止遮蓋問題,通常設置一定的透明度,alpha的範圍為0到1。c='#BA5C25'設置點顔色,c賦值為一個數組可以做出每個點一個顔色的效果。
- marker:設置點的形狀;
- cmap:顔色映射;
- norm:當顔色c為一組浮點數時,把值标準化到[0,1]做顔色映射,vmin和vamx參數是結合 norm 來用的;
散點圖參數示例
ax.plot(x,y,'o')也可以畫散點圖,ax.plot()核心是繪制坐标系下的點和點之間的連線的,當突出點的大小而省略線時,就是散點圖了,同樣突出線就變成了折線圖。通過fmt(也就是format_string)參數來控制這些,包括點的形狀、顔色、線的風格顔色等。折線圖基礎繪制效果可回看上一部分可視化基礎框架。
plot()的常用參數如下:
- x,y: x軸和y軸的數據,當plot()隻有一個輸入列表或數組時,參數被當做y軸,也就是value,x軸以索引自動生成,也就是ax.plot(y)相當于ax.plot(range(len(y)),y);
- fmt: 控制x,y繪制的折線的點形狀、顔色、線的風格、顔色;
- 其他的lines.Line2D支持的屬性, 如color控制線顔色,marker控制點形狀,linestyle控制線風格類型及linewidth控制線寬等,如果既設置了fmt又指定了color呢?可以實踐一下,線的顔色會根據color屬性最終顯示。
常用fmt字符意義整理(可收藏方便查閱)
plot()除了plot(x,y,[fmt])這種寫法之外,還可以傳多套x,y以繪制多條折線,寫法是plot(x,y,[fmt],x2,y2,[fmt2],…)。
另外plot()還支持plot('col1','col2',data=df)這種寫法,這是對二維表格數據更友好的接口。本文講到的其他圖形如bar、barh等基本也都是支持ax.×××(df['x'],df['y']) 和ax.×××(x,y,data)寫法的。
通過ax.bar(x,height)繪制柱狀圖,條形圖的繪制用ax.barh(y,width),因bar和barh的用法很類似,參數之間有對應關系,這裡結合着看。
x,height: x軸的值和各柱的高,相當于折線圖的x,y; width: 柱的寬度,默認是0.8,也可以傳入一個數組,畫不等寬的柱狀圖; bottom: 每個柱底部開始位置,默認是0,改bottom可以畫堆積柱狀圖、瀑布圖等; align: 柱狀的x是在柱底部中心還是邊緣,{'center', 'edge'},默認是center; data: 可以傳入一個DataFrame,用法和前面說到的ax.plot('col1','col2',data=df)一緻; 其他像color(柱顔色)、edgecolor(柱邊框色)、linewidth(邊框線寬)等圖元屬性用法都一緻,linewidth也是可以簡寫為lw的,顔色可以傳一個數組,可以畫出五彩斑斓的柱,也可借由這個參數美化瀑布圖; 條形圖barh的參數有barh(y,width,height,left,align),y是Y軸的值,每個柱的位置,因此barh的y對應bar的x,barh的width對應bar的height,barh的height對應bar的width。每個柱開始的位置是left,對應bar的bottom。align、data、color等一緻。 注意的是柱狀圖繪制語句ax.bar(x,height)的返回值是一個容器(BarContainer),包含了所有畫出來的柱。通過這個返回值可以對柱進行一些個性化的處理,另外的應用就是根據返回柱的屬性給每個柱标上文本标簽。
#給柱狀圖标上标簽 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 #每個柱的寬度 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參數傳一個數組,可以畫堆疊柱狀圖:堆疊柱除了等值堆疊之外,還可以等比堆疊,思路就是将每個x對應的柱都做一下數值變換,把柱的高度約束在[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) #标簽設置等代碼省略
堆疊柱狀圖繪制效果
調節width參數使得柱和柱之間的寬度為0,并對數據進行統計在畫圖,可以用ax.bar()繪制直方圖,但也不需要這麼複雜,Matplotlib提供了繪制直方圖的接口ax.hist(x,bins,normed),可以直接對某列數據繪制直方圖。x是需要統計分布的數據列,bins控制分箱的個數,默認是10。
箱線圖在數據分析中挺常用的,箱線圖對于數據分布有很好的展示作用,Matplotlib提供了boxplot(x)用于繪制箱線圖。
fig, ax= plt.subplots() ax.boxplot(df['y']) #箱線圖
餅圖是可視化中基礎而重要的圖形,是各種數據報告的常客,Matplotlib繪制餅圖時因為xy軸默認比例尺不同,為了得到不扁的餅,需設置xy軸1像素對應的值相等。
#繪制餅圖 fig,ax=plt.subplots(subplot_kw=dict(aspect="equal")) ax.pie(df['y']) #為了得到不扁的餅,設置xy軸比例尺相同 #--- #環狀圖 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)
本文近五千字,從基礎圖表入手拆解對應繪制函數的重點參數,共10張圖,基本都是個人繪制和排版的,個人認為較系統講了Matplotlib的用法和核心功能,下篇會實踐更有趣的内容。
畫心形線(下篇彩蛋)
,更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!