全文共3576
字,預(yù)計(jì)學(xué)習(xí)時(shí)長(zhǎng)10
分鐘或更長(zhǎng)
圖片來(lái)源:Pexels
Seaborn和Matplotlib是Python最強(qiáng)大的兩個(gè)可視化庫(kù)。Seaborn其默認(rèn)主題讓人驚訝,而Matplotlib可以通過(guò)其多個(gè)分類為用戶打造專屬功能。
Python提供了各種用于繪制數(shù)據(jù)的包。本教程將使用以下兩種包來(lái)演示Python的繪圖功能:
· Matplotlib
· Seaborn
Matplotlib
importmatplotlib.pyplot as plt
%matplotlib inline
import numpy as np
在上面的代碼塊中,將Pyplot模塊調(diào)整為plt格式并導(dǎo)入Matplotliib庫(kù)。這樣做可以簡(jiǎn)化執(zhí)行命令的過(guò)程,具體內(nèi)容會(huì)在本篇教程中看到。PyPlot包含創(chuàng)建和編輯繪圖所需的一系列命令。操作時(shí)同時(shí)運(yùn)行%matplotlibinline,那么繪圖下方就能自動(dòng)顯示代碼塊,否則用戶每次繪圖時(shí)都需要輸入plt.show()來(lái)創(chuàng)建新圖。此功能是Jupyter Notebook / IPython獨(dú)有的。Matplotlib擁有定制的代碼塊結(jié)構(gòu),這使得它比其他繪圖庫(kù)更先進(jìn)。接下來(lái)看看如何使用matploblib生成散點(diǎn)圖。
提示:當(dāng)使用matplotlib時(shí),文本輸出無(wú)法帶來(lái)視覺(jué)上的吸引力。為了解決這個(gè)問(wèn)題,我們?cè)趫?zhí)行代碼塊生成圖片時(shí)會(huì)在每一行代碼末端添加分號(hào)“;”。
我們使用的數(shù)據(jù)庫(kù)是UCI機(jī)器學(xué)習(xí)庫(kù)中的共享單車數(shù)據(jù)集。
Matplotlib: 散點(diǎn)圖
散點(diǎn)圖是各種示意圖中影響力最廣、信息量最大、功能最多的一類圖。它可以直接向用戶傳遞信息,無(wú)需太多額外工作(如下圖所示)。
· plt.scatter()將輸入的散點(diǎn)圖上的數(shù)據(jù)作為初始參數(shù),其中temp指x軸,cnt指y軸。
· c指的是不同數(shù)據(jù)點(diǎn)的顏色。輸入一個(gè)字符串“季節(jié)”,它也表示數(shù)據(jù)幀中的一列,不同顏色對(duì)應(yīng)不同季節(jié)。該方法用可視化方法對(duì)數(shù)據(jù)分組,十分簡(jiǎn)單便捷。
plt.scatter('temp','cnt', data=day, c='season')
plt.xlabel('NormalizedTemperature', fontsize='large')
plt.ylabel('Countof Total Bike Rentals', fontsize='large');
圖上信息顯示:
· 某些時(shí)間點(diǎn)的自行車租賃量超過(guò)8000輛。
· 標(biāo)準(zhǔn)溫度超過(guò)0.8。
· 自行車租賃量與溫度或季節(jié)無(wú)關(guān)。
· 自行車租賃量與標(biāo)準(zhǔn)溫度之間含有正線性關(guān)系。
這個(gè)圖的確含有大量信息,然而圖表并不能產(chǎn)生圖例,因此我們很難對(duì)各組季節(jié)數(shù)據(jù)進(jìn)行破譯。這是因?yàn)橛蒙Ⅻc(diǎn)圖繪圖時(shí),Matplotlib無(wú)法根據(jù)繪圖制作圖例。下一節(jié)中,我們將會(huì)看到該圖如何隱藏信息,甚至誤導(dǎo)讀者。
看看經(jīng)過(guò)徹底編輯后的繪圖。該圖旨在根據(jù)不同組別繪制圖例,并進(jìn)行破譯。
plt.rcParams['figure.figsize']= [15, 10]
fontdict={'fontsize':18,
'weight' : 'bold',
'horizontalalignment': 'center'}
fontdictx={'fontsize':18,
'weight' : 'bold',
'horizontalalignment': 'center'}
fontdicty={'fontsize':16,
'weight' : 'bold',
'verticalalignment': 'baseline',
'horizontalalignment': 'center'}
spring =plt.scatter('temp', 'cnt', data=day[day['season']==1], marker='o',color='green')
summer =plt.scatter('temp', 'cnt', data=day[day['season']==2], marker='o', color='orange')
autumn =plt.scatter('temp', 'cnt', data=day[day['season']==3], marker='o',color='brown')
winter =plt.scatter('temp', 'cnt', data=day[day['season']==4], marker='o',color='blue')
plt.legend(handles=(spring,summer,autumn,winter),
labels=('Spring', 'Summer','Fall/Autumn', 'Winter'),
title='Season',title_fontsize=16,
scatterpoints=1,
bbox_to_anchor=(1, 0.7), loc=2,borderaxespad=1.,
ncol=1,
fontsize=14)
plt.title('BikeRentals at Different Temperatures\nBy Season', fontdict=fontdict,color='black')
plt.xlabel('Normalizedtemperature', fontdict=fontdictx)
plt.ylabel('Countof Total Rental Bikes', fontdict=fontdicty);
· plt.rcParams['figure.figsize']= [15, 10]限定了整張圖的大小,這個(gè)代碼對(duì)應(yīng)的是一個(gè)長(zhǎng)15厘米*寬10厘米的圖。
· Fontdict是一個(gè)包含許多參數(shù)的字典,可以用于標(biāo)記不同的軸,其中標(biāo)題為fontdict,x軸為fontdictx,y軸為fontdicty。
· 如今有四個(gè)plt.scatter()函數(shù),對(duì)應(yīng)四個(gè)不同的季節(jié),這一點(diǎn)在數(shù)據(jù)參數(shù)中再次出現(xiàn),而這些數(shù)據(jù)參數(shù)已被子集化以對(duì)應(yīng)不同單一季節(jié)。“o”表示不同的標(biāo)記和顏色參數(shù),這可以直觀地顯示數(shù)據(jù)點(diǎn)的位置以及其顏色。
· 在plt.legend()中輸入?yún)?shù)形成圖例。前兩個(gè)參數(shù)是句柄:圖例和標(biāo)簽會(huì)展示真正的散點(diǎn)圖;而于各個(gè)圖對(duì)應(yīng)的名字也會(huì)在圖例中出現(xiàn)。圖上大小不一的標(biāo)記代表散點(diǎn),它們最終組合為一個(gè)散點(diǎn)圖。bbox_to_anchor=(1, 0.7), loc=2, borderaxespad=1。這三個(gè)參數(shù)串聯(lián)使用,來(lái)對(duì)照?qǐng)D例位置。點(diǎn)擊這句話開(kāi)頭的鏈接,可以發(fā)現(xiàn)這些參數(shù)的本質(zhì)。
現(xiàn)在可以通過(guò)區(qū)分不同季節(jié)來(lái)發(fā)現(xiàn)更多隱藏信息。但即使已經(jīng)添加了額外的圖層,散點(diǎn)圖依然可以隱藏信息并帶來(lái)誤解。
該散點(diǎn)圖:
· 數(shù)據(jù)中有重復(fù)部分。
· 分布混亂。
· 未顯示自行車租賃在不同季節(jié)之間的明顯差別。
· 隱藏信息,如:春夏氣溫上升時(shí)自行車出租量會(huì)增加。
· 表示自行車租賃量與氣溫呈正比關(guān)系。
· 并未清楚顯示最低溫出現(xiàn)在哪一季節(jié)。
子圖
創(chuàng)建子圖可能是業(yè)界最具吸引力也是最專業(yè)的圖表技術(shù)之一。當(dāng)單一的圖信息過(guò)多時(shí),人們難以評(píng)估,子圖就變得十分重要。
分面就是在同一個(gè)軸上繪制多個(gè)不同的圖。分面是數(shù)據(jù)可視化中功能最多的技術(shù)之一。分面可以從多個(gè)角度展示信息,也可以揭露隱藏內(nèi)容。
· 如前所述,plt.figure()將用于創(chuàng)建新的繪圖畫(huà)布。最終會(huì)保存為圖畫(huà)格式。
· 重復(fù)運(yùn)行fig.add_subplot()代碼4次,分別對(duì)應(yīng)四個(gè)季節(jié)的子圖。其參數(shù)則對(duì)應(yīng)nrows,ncols和index。比方說(shuō)axl對(duì)應(yīng)圖表上第一個(gè)繪圖(索引在左上角從1開(kāi)始,向右遞增)。
· 余下的函數(shù)調(diào)用可以自我解釋或被覆蓋。
fig = plt.figure()
plt.rcParams['figure.figsize']= [15,10]
plt.rcParams['font.weight']= 'bold'
fontdict={'fontsize':25,
'weight' : 'bold'}
fontdicty={'fontsize':18,
'weight' : 'bold',
'verticalalignment': 'baseline',
'horizontalalignment': 'center'}
fontdictx={'fontsize':18,
'weight' : 'bold',
'horizontalalignment': 'center'}
plt.subplots_adjust(wspace=0.2,hspace=0.2)
fig.suptitle('BikeRentals at Different Temperatures\nBy Season',fontsize=25,fontweight='bold', color='black',
position=(0.5,1.01))
ax1 =fig.add_subplot(221)
ax1.scatter('temp','cnt', data=day[day['season']==1], c='green')
ax1.set_title('Spring',fontdict=fontdict, color='green')
ax1.set_ylabel('Countof Total Rental Bikes', fontdict=fontdicty, position=(0,-0.1))
ax2 =fig.add_subplot(222)
ax2.scatter('temp','cnt', data=day[day['season']==2], c='orange')
ax2.set_title('Summer',fontdict=fontdict, color='orange')
ax3 =fig.add_subplot(223)
ax3.scatter('temp','cnt', data=day[day['season']==3], c='brown')
ax3.set_title('Fallor Autumn', fontdict=fontdict, color='brown')
ax4 =fig.add_subplot(224)
ax4.scatter('temp','cnt', data=day[day['season']==4], c='blue')
ax4.set_title('Winter',fontdict=fontdict, color='blue')
ax4.set_xlabel('Normalizedtemperature', fontdict=fontdictx, position=(-0.1,0));
現(xiàn)在分別分析各組,效果也會(huì)更加顯著。首先要注意到在不同季節(jié)里,自行車租賃量與氣溫的關(guān)系存在差異:
· 它們?cè)诖禾斐尸F(xiàn)正線性關(guān)系。
· 它們?cè)诙旌拖奶斐识畏蔷€性關(guān)系。
· 在秋天它們的正線性關(guān)系十分不明顯。
但是,這些圖依然有可能誤導(dǎo)讀者,原因也并不明顯。四張圖中,所有的軸都不一樣。如果人們沒(méi)有留意到這一點(diǎn),那么他們很有可能會(huì)誤解這些圖。請(qǐng)參閱下文,了解如何解決該問(wèn)題。
fig = plt.figure()
plt.rcParams['figure.figsize']= [12,12]
plt.rcParams['font.weight']= 'bold'
plt.subplots_adjust(hspace=0.60)
fontdicty={'fontsize':20,
'weight' : 'bold',
'verticalalignment': 'baseline',
'horizontalalignment': 'center'}
fontdictx={'fontsize':20,
'weight' : 'bold',
'horizontalalignment': 'center'}
fig.suptitle('BikeRentals at Different Temperatures\nBy Season',fontsize=25,fontweight='bold', color='black',
position=(0.5,1.0))
#ax2 is definedfirst because the other plots are sharing its x-axis
ax2 =fig.add_subplot(412, sharex=ax2)
ax2.scatter('temp','cnt', data=day.loc[day['season']==2], c='orange')
ax2.set_title('Summer',fontdict=fontdict, color='orange')
ax2.set_ylabel('Countof Total Rental Bikes', fontdict=fontdicty, position=(-0.3,-0.2))
ax1 =fig.add_subplot(411, sharex=ax2)
ax1.scatter('temp','cnt', data=day.loc[day['season']==1], c='green')
ax1.set_title('Spring',fontdict=fontdict, color='green')
ax3 =fig.add_subplot(413, sharex=ax2)
ax3.scatter('temp','cnt', data=day.loc[day['season']==3], c='brown')
ax3.set_title('Fallor Autumn', fontdict=fontdict, color='brown')
ax4 =fig.add_subplot(414, sharex=ax2)
ax4.scatter('temp','cnt', data=day.loc[day['season']==4], c='blue')
ax4.set_title('Winter',fontdict=fontdict, color='blue')
ax4.set_xlabel('Normalizedtemperature', fontdict=fontdictx);
如今繪圖網(wǎng)格重新調(diào)整,所有圖的x軸都與夏天圖的x軸一致(選擇夏天的x軸為標(biāo)準(zhǔn)是因?yàn)樗臏囟确秶鼜V)?,F(xiàn)在可以從數(shù)據(jù)中找到一些更有趣的發(fā)現(xiàn):
· 最低溫度出現(xiàn)在春天。
· 最高溫度出現(xiàn)在秋天。
· 在夏天和秋天,自行車租賃量和溫度似乎呈二次關(guān)系。
· 不考慮季節(jié)因素時(shí),溫度越低,自行車租賃量越少。
· 春天的自行車租賃量和溫度呈明顯的正線性關(guān)系。
· 秋天的自行車租賃量和溫度呈輕度的負(fù)線性關(guān)系。
fig = plt.figure()
plt.rcParams['figure.figsize']= [10,10]
plt.rcParams['font.weight']= 'bold'
plt.subplots_adjust(wspace=0.5)
fontdicty1={'fontsize':18,
'weight' : 'bold'}
fontdictx1={'fontsize':18,
'weight' : 'bold',
'horizontalalignment': 'center'}
fig.suptitle('BikeRentals at Different Temperatures\nBy Season',fontsize=25,fontweight='bold', color='black',
position=(0.5,1.0))
ax3 =fig.add_subplot(143, sharey=ax3)
ax3.scatter('temp','cnt', data=day.loc[day['season']==3], c='brown')
ax3.set_title('Fallor Autumn', fontdict=fontdict,color='brown')
ax1 =fig.add_subplot(141, sharey=ax3)
ax1.scatter('temp','cnt', data=day.loc[day['season']==1], c='green')
ax1.set_title('Spring',fontdict=fontdict, color='green')
ax1.set_ylabel('Countof Total Rental Bikes', fontdict=fontdicty1, position=(0.5,0.5))
ax2 =fig.add_subplot(142, sharey=ax3)
ax2.scatter('temp','cnt', data=day.loc[day['season']==2], c='orange')
ax2.set_title('Summer',fontdict=fontdict, color='orange')
ax4 =fig.add_subplot(144, sharey=ax3)
ax4.scatter('temp','cnt', data=day.loc[day['season']==4], c='blue')
ax4.set_title('Winter',fontdict=fontdict, color='blue')
ax4.set_xlabel('Normalizedtemperature', fontdict=fontdictx, position=(-1.5,0));
將所有繪圖并列放置又有新的發(fā)現(xiàn):
· 所有季節(jié)都有超過(guò)8000輛自行車出租的時(shí)間點(diǎn)。
· 大規(guī)模的自行車出租主要出現(xiàn)在春秋兩季。
· 冬夏兩季中自行車租賃量變動(dòng)較大。
但注意,不要從以上方面來(lái)解釋變量之間的關(guān)系。盡管春夏兩季中自行車租賃量與氣溫似乎存在負(fù)線性關(guān)系,但這一解釋實(shí)際是錯(cuò)誤的。從前文的分析中我們發(fā)現(xiàn)事實(shí)并非如此。
Seaborn
seaborn包是基于Matplotlib庫(kù)開(kāi)發(fā)的。它用于創(chuàng)建更具吸引力、信息量更大的統(tǒng)計(jì)圖形。雖然seaborn與Matplotlib不一樣,但它創(chuàng)建的圖像一樣具有吸引力。
盡管matplotlib表現(xiàn)不俗,但我們總希望做得更好。運(yùn)行下面的代碼塊以導(dǎo)入seaborn庫(kù),并創(chuàng)建先前的散點(diǎn)圖,來(lái)看看會(huì)出現(xiàn)什么。
首先輸入代碼import seaborn assns,將seaborn庫(kù)導(dǎo)入。下一行sns.set()將seaborn的默認(rèn)主題和調(diào)色板加載到會(huì)話中。運(yùn)行下面的代碼并觀察圖表中哪些區(qū)域或文字發(fā)生更改。
import seaborn assns
sns.set()
將seaborn加載到會(huì)話中后,當(dāng)使用Matplotlib生成圖像時(shí),這個(gè)庫(kù)會(huì)添加seaborn的默認(rèn)自定義項(xiàng),如圖所示。而最令用戶感到困擾的便是它們的標(biāo)題有可能會(huì)重復(fù)——Matplotlib的命名規(guī)則讓人困惑,這一點(diǎn)也讓人覺(jué)得厭煩。盡管如此,這些視覺(jué)效果依然很有吸引力,數(shù)據(jù)科學(xué)家的工作已引入這一技術(shù)。
為了使標(biāo)題更加與時(shí)俱進(jìn),提高其用戶友好度,需要使用如下代碼。但注意,以下代碼僅適用于散點(diǎn)圖中含有副標(biāo)題的情況。有的時(shí)候副標(biāo)題也十分重要,因此仍需更好地掌握這種結(jié)構(gòu)。
fig = plt.figure()
fig.suptitle('Seabornwith Python', fontsize='x-large', fontweight='bold')
fig.subplots_adjust(top=0.87)
#This is used forthe main title. 'figure()' is a class that provides all the plotting elementsof a diagram.
#This must be usedfirst or else the title will not show.fig.subplots_adjust(top=0.85) solves ouroverlapping title problem.
ax =fig.add_subplot(111)
fontdict={'fontsize':14,
'fontweight' : 'book',
'verticalalignment': 'baseline',
'horizontalalignment': 'center'}
ax.set_title('PlottingTutorial', fontdict=fontdict)
#This specifieswhich plot to add the customizations. fig.add_sublpot(111) corresponds to topleft plot no.1
#(there is only oneplot).
plt.plot(x, y,'go-', linewidth=1) #linewidth=1 to make it narrower
plt.xlabel('x-axis',fontsize=14)
plt.ylabel('yaxis',fontsize=14);
深入挖掘seaborn的功能后,我們可以用更少的代碼行與類似的語(yǔ)法對(duì)自行車租賃量數(shù)據(jù)集再次創(chuàng)建可視化圖。Seaborn仍然使用Matplotlib語(yǔ)法來(lái)生成圖像,盡管新圖與舊圖之間的語(yǔ)法差異很小,但依然十分明顯。
為了簡(jiǎn)化視覺(jué)效果,我們將對(duì)自行車租賃數(shù)據(jù)集的“季節(jié)”列重新命名,并重新標(biāo)記。
day.rename(columns={'season':'Season'},inplace=True)
day['Season']=day.Season.map({1:'Spring',2:'Summer', 3:'Fall/Autumn', 4:'Winter'})
如今我們已根據(jù)喜好重新編輯了“季節(jié)”一欄,接下來(lái)將用seaborn對(duì)先前的繪圖進(jìn)行可視化。
第一個(gè)明顯的區(qū)別在于——當(dāng)默認(rèn)樣式加入到會(huì)話后,seaborn顯示的默認(rèn)主題不一致。上面顯示的默認(rèn)主題是在調(diào)用sns.set()時(shí)在后臺(tái)應(yīng)用sns.set_style('whitegrid')的結(jié)果。我們也可以根據(jù)喜好用已有主題改變?cè)瓉?lái)的狀態(tài),如下圖所示。
· sns.set_style()標(biāo)記的是“white”、“dark”、“whitegrid”以及“darkgrid”中的一個(gè)。這一代碼控制著整個(gè)繪圖區(qū)域,比如顏色,網(wǎng)格以及標(biāo)記的狀態(tài)。
· sns.set_context()表示的是“paper”、“notebook”、“talk”和“poster”的內(nèi)容。這將根據(jù)讀取方式控制繪圖的布局。例如,如果內(nèi)容出現(xiàn)在“poster”上,我們將看到放大的圖像和文字。如果內(nèi)容出現(xiàn)在 “talk”中,其字體將會(huì)加粗。
plt.figure(figsize=(7,6))
fontdict={'fontsize':18,
'weight' : 'bold',
'horizontalalignment': 'center'}
sns.set_context('talk',font_scale=0.9)
sns.set_style('ticks')
sns.scatterplot(x='temp',y='cnt', hue='Season', data=day, style='Season',
palette=['green','orange','brown','blue'], legend='full')
plt.legend(scatterpoints=1,
bbox_to_anchor=(1, 0.7), loc=2,borderaxespad=1.,
ncol=1,
fontsize=14)
plt.xlabel('NormalizedTemperature', fontsize=16, fontweight='bold')
plt.ylabel('Countof Total Bike Rentals', fontsize=16, fontweight='bold')
plt.title('BikeRentals at Different Temperatures\nBy Season', fontdict=fontdict, color='black',
position=(0.5,1));
現(xiàn)在來(lái)看一個(gè)相同的散點(diǎn)圖,但其輸入代碼為sns.set_context('paper',font_scale=2)和sns.set_style('white')
plt.figure(figsize=(7,6))
fontdict={'fontsize':18,
'weight' : 'bold',
'horizontalalignment': 'center'}
sns.set_context('paper',font_scale=2) #this makes the font and scatterpoints much smaller, hence theneed for size adjustemnts
sns.set_style('white')
sns.scatterplot(x='temp',y='cnt', hue='Season', data=day, style='Season',
palette=['green','orange','brown','blue'],legend='full', size='Season', sizes=[100,100,100,100])
plt.legend(scatterpoints=1,
bbox_to_anchor=(1, 0.7), loc=2,borderaxespad=1.,
ncol=1,
fontsize=14)
plt.xlabel('NormalizedTemperature', fontsize=16, fontweight='bold')
plt.ylabel('Countof Total Bike Rentals', fontsize=16, fontweight='bold')
plt.title('BikeRentals at Different Temperatures\nBy Season', fontdict=fontdict,color='black',
position=(0.5,1));
現(xiàn)在終于用Seaborn重新創(chuàng)建了之前用Matplotlib生成的散點(diǎn)圖。更改后的圖使用的代碼行數(shù)更少,分辨率也更高。接下來(lái)繼續(xù)完成繪圖:
sns.set(rc={'figure.figsize':(20,20)})
sns.set_context('talk',font_scale=2)
sns.set_style('ticks')
g =sns.relplot(x='temp', y='cnt', hue='Season', data=day,palette=['green','orange','brown','blue'],
col='Season', col_wrap=4,legend=False
height=6, aspect=0.5,style='Season', sizes=(800,1000))
g.fig.suptitle('BikeRentals at Different Temperatures\nBy Season' ,position=(0.5,1.05),fontweight='bold', size=18)
g.set_xlabels('NormalizedTemperature',fontweight='bold', size=15)
g.set_ylabels('Countof Total Bike Rentals',fontweight='bold', size=20);
改變圖表形狀需要改變外觀參數(shù)。通過(guò)增大外觀的數(shù)值,圖表形狀會(huì)更呈方形。圖像高度也會(huì)隨著數(shù)值更改發(fā)生變化,因此這里需要同時(shí)對(duì)兩個(gè)參數(shù)進(jìn)行試驗(yàn)。
更改行數(shù)和列數(shù)需使用col_wrap參數(shù)執(zhí)行此操作。行數(shù)和列數(shù)會(huì)隨著col參數(shù)而變化。這種參數(shù)可以檢測(cè)類比數(shù)目,同時(shí)可以相應(yīng)地分配。
sns.set(rc={'figure.figsize':(20,20)})
sns.set_context('talk',font_scale=2)
sns.set_style('ticks')
g =sns.relplot(x='temp', y='cnt', hue='Season',data=day,palette=['green','orange','brown','blue'],
col='Season', col_wrap=2,legend=False
height=4, aspect=1.6,style='Season', sizes=(800,1000))
g.fig.suptitle('BikeRentals at Different Temperatures\nBy Season' ,position=(0.5,1.05),fontweight='bold', size=18)
g.set_xlabels('NormalizedTemperature',fontweight='bold', size=15)
g.set_ylabels('Countof\nTotal Bike Rentals',fontweight='bold', size=20);
聯(lián)系客服