7天学会python_7天学会Python最佳可视化工具Seaborn(五):结构化展示多维数据
當(dāng)探索具有中等數(shù)量(不多不少的意思……)維度的數(shù)據(jù)集時(shí),一個(gè)很好的方式是基于不同的子數(shù)據(jù)集構(gòu)建不同的實(shí)例,并將它們以網(wǎng)格的方式組織在一張圖之中。這種技術(shù)有時(shí)被稱為“l(fā)attice”或“trellis”(大概是格子圖、網(wǎng)格圖),這跟“small multiples”的概念類似(多張更小的子圖)。它能幫助我們快速從復(fù)雜的數(shù)據(jù)中提取大量信息。matplotlib對于創(chuàng)建帶有多個(gè)坐標(biāo)軸(每個(gè)坐標(biāo)軸體系意味著一張子圖)的圖形有著良好的支持,seaborn基于這些來直接地將圖形的排布結(jié)構(gòu)與數(shù)據(jù)集的結(jié)構(gòu)聯(lián)結(jié)起來。
要利用這些特性,我們的數(shù)據(jù)集應(yīng)該保存在一個(gè)pandas DataFrame中,并且應(yīng)該是Hadley Whickam口中的“tidy data”格式。簡短來說,就是我們的dataframe對象中,每一行是一個(gè)觀測樣本,每一列是一個(gè)變量。
對于一些更高級的應(yīng)用來說,我們可以直接使用這篇教程中討論的一些對象來獲得最大的靈活性。一些seaborn函數(shù)(如lmplot()/catplot()/pairplot())也隱式地使用了這些對象。很多seaborn函數(shù)是坐標(biāo)軸級別的,它們僅僅針對某個(gè)特定的matplotlib Axes來繪圖,而不會(huì)修改圖形的屬性;而在這篇教程中即將討論到的這些方法是更高級別的函數(shù),在被調(diào)用時(shí),它們會(huì)創(chuàng)建一個(gè)新的圖形,而且一般情況下對于創(chuàng)建過程更加嚴(yán)格。在某些案例中,這些函數(shù)和他們依賴的類所需要輸入的參數(shù)依賴于不同的接口屬性,比如在lmplot()中我們通過設(shè)置高度和寬高比(height和aspect)來控制每個(gè)子圖(facet)的大小,而非直接指定整個(gè)圖形的大小。這些函數(shù)在調(diào)用后都會(huì)返回這個(gè)圖形對象,而且大多數(shù)對象都提供了非常方便的方法來改變繪圖的方式,這些方法往往更加抽象和簡單。
import seaborn as snsimport matplotlib.pyplot as pltsns.set(style='ticks')
一、條件式多圖
當(dāng)我們想要基于不同的數(shù)據(jù)子集來展示某個(gè)變量的分布或者多個(gè)變量之間的關(guān)系時(shí),FacetGrid類會(huì)提供很大的幫助。一個(gè)FacetGrid圖可以從三個(gè)維度來構(gòu)建:row、col和hue。前兩個(gè)與它返回的坐標(biāo)軸數(shù)組有著之間的關(guān)聯(lián);我們可以把hue變量理解為第三個(gè)維度,就像長、寬和高一樣,只不過在這里我們是用不同的顏色來體現(xiàn)它的。
在使用FacetGrid時(shí),我們會(huì)通過一個(gè)pandas DataFrame以及控制圖形網(wǎng)格的行、列和顏色的變量名稱來初始化一個(gè)對象。這些維度變量(控制行、列和顏色的變量)應(yīng)該是分類變量或者離散變量,然后這些變量的不同水平組合起來就構(gòu)成了整個(gè)圖形的每一個(gè)子圖(facet,在這里可以理解為我們維度拆解的最小粒度)。比如說我們想要檢驗(yàn)一下tips數(shù)據(jù)集中午餐和晚餐的差異。
另外,relplot()/catplot()/lmplot()內(nèi)置了FacetGrid對象,繪圖完成后他們都會(huì)返回這個(gè)對象,這樣我們就可以進(jìn)行更多的調(diào)整。
tips = sns.load_dataset('tips')g = sns.FacetGrid(tips, col='time')
傳入數(shù)據(jù)和維度變量名稱會(huì)初始化一個(gè)網(wǎng)格,其中生成了基于matplotlib的圖形和坐標(biāo)軸,但是不會(huì)在這些坐標(biāo)軸中畫任何東西(因?yàn)槲覀冞€沒告訴它們畫什么)。
在這些網(wǎng)格中畫圖的主要方式是使用FacetGrid.map()方法。我們需要告訴它使用哪個(gè)繪圖函數(shù)以及使用哪些(哪個(gè))變量。我們用直方圖來看下兩個(gè)數(shù)據(jù)子集中小費(fèi)的分布情況:
g = sns.FacetGrid(tips, col='time')g.map(plt.hist, 'tip');
這一函數(shù)的目標(biāo)是一步到位地提供一幅完整的成品圖,它在完成繪圖后還會(huì)對每個(gè)坐標(biāo)軸添加注釋。想要生成一個(gè)戰(zhàn)士變量關(guān)系的圖,只需要傳遞更多的變量名稱進(jìn)去。我們還可以提供關(guān)鍵字參數(shù),它會(huì)將他們傳遞給繪圖函數(shù):
g = sns.FacetGrid(tips, col='sex', hue='smoker')g.map(plt.scatter, 'total_bill', 'tip', alpha=.7)g.add_legend();
有很多選項(xiàng)可以傳遞給FacetGrid的構(gòu)造函數(shù),用以控制網(wǎng)格的樣式:
g = sns.FacetGrid(tips, row='smoker', col='time', margin_titles=True)g.map(sns.regplot, 'size', 'total_bill', color='.3', fit_reg=False, x_jitter=.1);
需要注意的是,margin_title參數(shù)并沒有被matplotlib API提供正式支持,在某些案例中或許并不可用。比如說當(dāng)圖外邊有圖例時(shí),它是不可用的。
圖的大小是通過每張子圖的高度和寬高比來控制的:
g = sns.FacetGrid(tips, col='day', height=4, aspect=.5)g.map(sns.barplot, 'sex', 'total_bill');/anaconda3/lib/python3.7/site-packages/seaborn/axisgrid.py:715: UserWarning: Using the barplot function without specifying `order` is likely to produce an incorrect plot. warnings.warn(warning)
它默認(rèn)會(huì)從DataFrame中推導(dǎo)分類的順序。如果用來控制某個(gè)方面(facet:維度/軸/角度,看哪個(gè)概念能幫助你理解它,你就用哪個(gè)名字)的變量是分類變量,那么分類變量的順序就會(huì)被使用。否則,seaborn會(huì)使用這些分類在數(shù)據(jù)集中出現(xiàn)的先后順序。當(dāng)然,我們完全可以通過*_order參數(shù)直接指定某個(gè)維度變量的順序:
ordered_days = tips.day.value_counts().indexg = sns.FacetGrid(tips, row='day', row_order=ordered_days, height=1.7, aspect=4)g.map(sns.distplot, 'total_bill', hist=False, rug=True);
我們可以指定某個(gè)seaborn調(diào)色板,也可以通過字典將hue變量中的每個(gè)分類與其對應(yīng)的matplotlib顏色傳遞給函數(shù)(這樣就可以隨心所以使用大量的matplotlib支持的色彩):
pal = dict(Lunch='seagreen', Dinner='gray')g = sns.FacetGrid(tips, hue='time', palette=pal, height=5)g.map(plt.scatter, 'total_bill', 'tip', s=50, alpha=.7, linewidth=.5, edgecolor='white')g.add_legend();
我們還可以控制hue變量的不同水平展示出來的其他樣式(方面),這些在黑白色調(diào)下(比如黑白印刷圖)對于提高圖形的可讀性尤其有用。我們需要將一個(gè)字典傳遞給hue_kws參數(shù),在這個(gè)字典中,key(字典的鍵)是繪圖函數(shù)的關(guān)鍵字參數(shù)名稱;而value(字典的值)則是一個(gè)列表,用于存儲關(guān)鍵字參數(shù)的取值,其中每個(gè)取值對應(yīng)了hue變量的一個(gè)水平。
g = sns.FacetGrid(tips, hue='sex', palette='Set1', height=5, hue_kws={'marker': ['^', 'v']})g.map(plt.scatter, 'total_bill', 'tip', s=100, linewidth=.5, edgecolor='white')g.add_legend();
如果某個(gè)維度變量(用于col/row/hue參數(shù)的變量,之后不再說明)具有非常多的水平(level:取值),我們可以把它們分布到不同的列,然后把它們“折疊”到不同的行中。當(dāng)我們使用這種操作時(shí),我們不能設(shè)置row變量。
attend = sns.load_dataset('attention').query('subject <= 12')g="sns.FacetGrid(attend," col='subject' ,="" col_wrap="4," height="2," ylim="(0," 10))g.map(sns.pointplot,="" 'solutions',="" 'score',="" color='.3' ,="" ci="None);/anaconda3/lib/python3.7/site-packages/seaborn/axisgrid.py:715:" userwarning:="" using="" the="" pointplot="" function="" without="" specifying="" `order`="" is="" likely="" to="" produce="" an="" incorrect="" plot.="">=>
當(dāng)我們已經(jīng)使用FacetGrid.map()完成了繪圖,我們可能還想對圖形的某些方面做些調(diào)整。FacetGrid支持很多在更高層級調(diào)整圖形的方法,最常用的是FacetGrid.set(),還有一些更加具體的方法比如FacetGrid.set_axis_labels(),如圖:
with sns.axes_style('white'): g = sns.FacetGrid(tips, row='sex', col='smoker', margin_titles=True, height=2.5)g.map(plt.scatter, 'total_bill', 'tip', color='#334488', edgecolor='white', lw=.5);g.set_axis_labels('Total bill (US Dollars)', 'Tip');g.set(xticks=[10, 30, 50], yticks=[2, 6, 10]);g.fig.subplots_adjust(wspace=.02, hspace=.02);
想要做更多定制的話,我們可以直接操作更底層的Figure和Axes對象,它們存儲在FacetGrid.fig和FacetGrid.axes中,其中,FacetGrid.axes是一個(gè)二維數(shù)組。假如我們沒有指定行和列,那么我們也可以直接使用FacetGrid.ax來操作那個(gè)唯一的坐標(biāo)軸:
g = sns.FacetGrid(tips, col='smoker', margin_titles=True, height=4)g.map(plt.scatter, 'total_bill', 'tip', color='#338844', edgecolor='white', s=50, lw=1)for ax in g.axes.flat: ax.plot((0, 50), (0, .2 * 50), c='.2', ls='--')g.set(xlim=(0, 60), ylim=(0, 14));
二、使用自定義繪圖函數(shù)
使用FacetGrid時(shí),我們并非只能使用現(xiàn)成的matplotlib和seaborn繪圖函數(shù)。不過,如果想要正常工作,我們的自定義函數(shù)需要滿足一下規(guī)則:它必須是一個(gè)坐標(biāo)軸級別的函數(shù)(僅對當(dāng)前活躍的坐標(biāo)軸進(jìn)行繪圖)。在matplotlib.pyplot的命名空間中存在的函數(shù)都是符合要求的,我們也可以調(diào)用plt.gca()(get current axes)來獲取符合要求的坐標(biāo)軸。
它必須支持以位置參數(shù)的方式接受數(shù)據(jù)傳入。FacetGrid內(nèi)部會(huì)把我們傳遞給FacetGrid.map()的多組序列數(shù)據(jù)分別傳遞給這些位置參數(shù)。
它必須支持接受關(guān)鍵字參數(shù)color和label,另外,理想情況下,它還會(huì)利用這兩個(gè)參數(shù)做一些有用的事情。在大多數(shù)情況下,接受一個(gè)關(guān)鍵字參數(shù)(**kwargs)的字典并傳遞給底層的繪圖函數(shù)是很容易的。
我們來看一個(gè)符合最低條件的例子,這個(gè)繪圖函數(shù)僅接受一組來自某個(gè)分類(子數(shù)據(jù)集)的向量型數(shù)據(jù):
from scipy import statsdef quantile_plot(x, **kwargs): qntls, xr = stats.probplot(x, fit=False) plt.scatter(xr, qntls, **kwargs) g = sns.FacetGrid(tips, col='sex', height=4)g.map(quantile_plot, 'total_bill');
如果我們想要繪制一個(gè)二元圖,我們需要讓函數(shù)接受兩組數(shù)據(jù),且x軸對應(yīng)的數(shù)據(jù)在前邊,y軸對應(yīng)的數(shù)據(jù)在后邊:
def qqplot(x, y, **kwargs): _, xr = stats.probplot(x, fit=False) _, yr = stats.probplot(y, fit=False) plt.scatter(xr, yr, **kwargs)g = sns.FacetGrid(tips, col='smoker', height=4)g.map(qqplot, 'total_bill', 'tip');
由于plt.scatter可以接受關(guān)鍵字參數(shù)color和label并且能正確處理它們,所以我們可以毫不費(fèi)力地增加一個(gè)hue參數(shù)(因?yàn)樗脑砭褪墙o不同的分類數(shù)據(jù)傳入不同的顏色參數(shù)):
g = sns.FacetGrid(tips, hue='time', col='sex', height=4)g.map(qqplot, 'total_bill', 'tip')g.add_legend();
我們還可以通過關(guān)鍵字參數(shù)控制額外的美學(xué)設(shè)計(jì)來區(qū)分hue變量的不同水平:
g = sns.FacetGrid(tips, hue='time', col='sex', height=4, hue_kws={'marker': ['s', 'D']})g.map(qqplot, 'total_bill', 'tip', s=40, edgecolor='w')g.add_legend();
當(dāng)然,有時(shí)我們完全不想處理color和label。這種情況下我們需要顯式地接受他們,然后用自己的邏輯去處理他們。比如下邊這個(gè)使用plt.hexbin的例子,在與FacetGridAPI搭配的過程中。如果我們沒有手動(dòng)調(diào)整顏色處理方式的話,它們的表現(xiàn)會(huì)不太好:
def hexbin(x, y, color, **kwargs): cmap = sns.light_palette(color, as_cmap=True) plt.hexbin(x, y, gridsize=15, cmap=cmap, **kwargs)with sns.axes_style('white'): g = sns.FacetGrid(tips, hue='time', col='time', height=4)g.map(hexbin, 'total_bill', 'tip', extent=[0, 50, 0, 10]);
三、展示變量間的兩兩(成對)關(guān)系
PairGrid也支持我們以同樣的方式快速繪制多個(gè)子圖。在PairGrid中,每行每列都被分配給一個(gè)不同的變量,所以最后生成的圖片可以展示數(shù)據(jù)集中所有的成對關(guān)系。這種風(fēng)格的圖形有時(shí)被稱作“散點(diǎn)圖矩陣”,因?yàn)樯Ⅻc(diǎn)圖是表現(xiàn)兩兩關(guān)系最常用的方法。不過PairGrid并不會(huì)僅僅局限于散點(diǎn)圖。
了解FacetGrid和PairGrid之間的區(qū)別非常重要。在FacetGrid中,每張圖表現(xiàn)的都是同樣的變量關(guān)系,只是每張圖對應(yīng)著不同的數(shù)據(jù)子集,數(shù)據(jù)子集的劃分是由我們指定的維度變量決定的(col、row和hue),這些變量相互交叉后產(chǎn)生一系列最小粒度的數(shù)據(jù)子集,每個(gè)子集就對應(yīng)了一張子圖,也就是說,不管是多少行、多少列還是多少顏色,它們都對應(yīng)著這些維度變量的取值(水平)。而在PairGrid中,每張子圖都代表了不同的兩個(gè)變量間的關(guān)系(當(dāng)然,上三角和下三角會(huì)有鏡像的關(guān)系,因?yàn)樗鼈兿喈?dāng)于互換了x軸和y軸)。PairGrid可以對于我們數(shù)據(jù)集中的變量關(guān)系提供一個(gè)非常快速、整體(不深入)的總結(jié)。
它的基本使用方法與FacetGrid非常類似。首先我們初始化一個(gè)網(wǎng)格,然后把繪圖函數(shù)傳遞給map方法,它會(huì)將我們的繪圖函數(shù)在所有的子圖中調(diào)用。與PairGrid對應(yīng)的函數(shù)是pairplot(),它失去了一些靈活性,但是讓我們的繪圖更加快捷。
iris = sns.load_dataset('iris')g = sns.PairGrid(iris)g.map(plt.scatter);
我們可以在對角線上用不同的函數(shù)來展示單變量的分布情況。不過需要注意的是,軸上的刻度與分桶計(jì)數(shù)或者密度沒有關(guān)系(因?yàn)槲覀円呀?jīng)用軸刻度去展示數(shù)據(jù)的取值了)。
g = sns.PairGrid(iris)g.map_diag(plt.hist)g.map_offdiag(plt.scatter);
在這種圖中,我們常常會(huì)對屬于不同分類的樣本標(biāo)記上不同的顏色。比如,iris數(shù)據(jù)集中有三種不同的鳶尾花,其中每個(gè)樣本都有4個(gè)特征,因此我們可以看下它們的區(qū)別在哪里。
g = sns.PairGrid(iris, hue='species')g.map_diag(plt.hist)g.map_offdiag(plt.scatter)g.add_legend();
默認(rèn)情況下,數(shù)據(jù)集中所有的數(shù)值型變量都會(huì)被使用,不過我們也可以僅選用特定的列:
g = sns.PairGrid(iris, vars=['sepal_length', 'sepal_width'], hue='species')g.map(plt.scatter);
我們也可以分別在上三角和下三角中使用不同的函數(shù),用以強(qiáng)調(diào)關(guān)系的不同角度。
g = sns.PairGrid(iris)g.map_upper(plt.scatter)g.map_lower(sns.kdeplot)g.map_diag(sns.kdeplot, lw=3, legend=False);
事實(shí)上,這種對稱的方形網(wǎng)格矩陣只是一個(gè)特例,我們可以在行和列上分別使用不同的變量。
g = sns.PairGrid(tips, y_vars=['tip'], x_vars=['total_bill', 'size'], height=4)g.map(sns.regplot, color='.3')g.set(ylim=(-1, 11), yticks=[0, 5, 10]);
當(dāng)然,設(shè)計(jì)(美學(xué))屬性都是可以配置的。比如,我們可以使用不同的調(diào)色板、可以給繪圖函數(shù)傳遞關(guān)鍵字參數(shù)。
g = sns.PairGrid(tips, hue='size', palette='GnBu_d')g.map(plt.scatter, s=50, edgecolor='white')g.add_legend();
PairGrid很靈活,但是想要快速觀察數(shù)據(jù)特點(diǎn)的話,使用pairplot()更容易。這個(gè)函數(shù)默認(rèn)使用散點(diǎn)圖和直方圖,但是也支持一些其他類型(現(xiàn)在我們還可以在非對角位置上畫回歸圖、在對角位置上畫KDE圖),未來還會(huì)支持更多。
sns.pairplot(iris, hue='species', height=2.5);
在pairplot()中我們也可以通過關(guān)鍵字參數(shù)調(diào)整設(shè)計(jì)風(fēng)格(美學(xué)),并且它會(huì)返回一個(gè)PairGrid對象用于更多的調(diào)整。
g = sns.pairplot(iris, hue='species', palette='Set2', diag_kind='kde', height=2.5)
總結(jié)
以上是生活随笔為你收集整理的7天学会python_7天学会Python最佳可视化工具Seaborn(五):结构化展示多维数据的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: golang mysql 防注入_Go,
- 下一篇: python读取oracle数据库性能_