選自TowardsDataScience
作者:William Koehrsen
編譯:機(jī)器之心(almosthuman2014)
原文:https://towardsdatascience.com/visualizing-data-with-pair-plots-in-python-f228cf529166
本文,我們將介紹如何使用 Seaborn 可視化庫(kù)(https://seaborn.pydata.org/)在 Python 中啟動(dòng)和運(yùn)行散點(diǎn)圖矩陣。我們將看到如何為快速檢查數(shù)據(jù)而創(chuàng)建默認(rèn)散點(diǎn)圖矩陣,以及如何為了更深入的分析定制可視化方案。
代碼地址(點(diǎn)擊閱讀原文即可訪問):https://github.com/WillKoehrsen/Data-Analysis/blob/master/pairplots/Pair%20Plots.ipynb
我們將探索一個(gè)現(xiàn)實(shí)世界數(shù)據(jù)集,它由國(guó)家級(jí)的社會(huì)經(jīng)濟(jì)數(shù)據(jù)組成,這些數(shù)據(jù)都是 Gapminder 收集的。
Seaborn 中的散點(diǎn)圖矩陣
我們需要先了解一下數(shù)據(jù),以便開始后續(xù)的進(jìn)展。我們可以 pandas 數(shù)據(jù)幀的形式加載這些社會(huì)經(jīng)濟(jì)數(shù)據(jù),然后我們會(huì)看到下面這些列:
每一行代表一個(gè)國(guó)家一年的觀察數(shù)據(jù),列代表變量(這種格式的數(shù)據(jù)被稱作整潔數(shù)據(jù),tidy data),其中有兩個(gè)類別列(國(guó)家和洲)和四個(gè)數(shù)值列。這些列簡(jiǎn)單易懂:life_exp 是出生時(shí)的預(yù)期壽命,以年為單位,popis 是人口數(shù)量,gdp_per_cap 是人均 GDP(以國(guó)際元)為單位。
seaborn 中的默認(rèn)散點(diǎn)圖矩陣僅僅畫出數(shù)值列,盡管我們隨后也會(huì)使用類別變量來著色。創(chuàng)建默認(rèn)的散點(diǎn)圖矩陣很簡(jiǎn)單:我們加載 seaborn 庫(kù),然后調(diào)用 pairplot 函數(shù),向它傳遞我們的數(shù)據(jù)幀即可:
# Seaborn visualization library
import seaborn as sns
# Create the default pairplot
sns.pairplot(df)
我仍舊大為吃驚,一行簡(jiǎn)單的代碼就能夠讓我們得到整個(gè)圖。散點(diǎn)圖矩陣會(huì)構(gòu)建兩種基本圖形:直方圖和散點(diǎn)圖。位于對(duì)角線位置的直方圖讓我們看到了每一個(gè)變量的分布,而對(duì)角線上下的散點(diǎn)圖則展示了變量?jī)蓛芍g的關(guān)系。例如,第二行最左側(cè)的散點(diǎn)圖展示了 life_exp 和 year 之間的關(guān)系。
默認(rèn)的散點(diǎn)圖矩陣通常能夠提供有價(jià)值的洞見。我們可以看到 life-exp 和 gdp_per_cap 是正相關(guān)的,這表明較高收入國(guó)家的國(guó)民要活得更久一些(盡管這并不能表明二者存在因果關(guān)系)。令人欣慰的是,這也顯示出世界范圍內(nèi)的人口壽命隨著時(shí)間逐漸增長(zhǎng)。我們可以從直方圖中了解到人口和 GDP 變量呈嚴(yán)重右偏態(tài)分布。為了在以后的圖中更好地展示這些變量,我們可以通過對(duì)列數(shù)值取對(duì)數(shù)來進(jìn)行列變換:
# Take the log of population and gdp_per_capita
df[ log_pop ] = np.log10(df[ pop ])
df[ log_gdp_per_cap ] = np.log10(df[ gdp_per_cap ])
# Drop the non-transformed columns
df = df.drop(columns = [ pop , gdp_per_cap ])
盡管這一張圖在分析中就很有用,然而我們發(fā)現(xiàn)基于類別變量(例如洲)對(duì)圖進(jìn)行著色能夠讓它更有價(jià)值。這在 seaborn 中也是極其簡(jiǎn)單的。我們唯一要做的就是在調(diào)用 sns.pairplot 函數(shù)的時(shí)候使用關(guān)鍵詞 hue。
sns.pairplot(df, hue = continent )
現(xiàn)在我們發(fā)現(xiàn)大洋洲和歐洲趨向于擁有最高的期望壽命,而亞洲擁有最多的人口量。注意我們對(duì)人口和 GDP 的對(duì)數(shù)變換使得這些變量呈正態(tài)分布,這提供了一個(gè)關(guān)于這些變量更加全面的表征。
這張圖具有更多的信息,但是還存在一些問題:正如對(duì)角線上看到的一樣,我認(rèn)為堆疊的直方圖可解釋性不是很好。展示來自多類別的單變量分布的一個(gè)更好方法就是密度圖(density plot)。我們可以通過調(diào)用函數(shù)將直方圖變成密度圖。向散點(diǎn)圖輸入一些關(guān)鍵詞,改變點(diǎn)的透明度、大小和邊緣顏色。
# Create a pair plot colored by continent with a density plot of the # diagonal and format the scatter plots.
sns.pairplot(df, hue = continent , diag_kind = kde ,
plot_kws = { alpha : 0.6, s : 80, edgecolor : k },
size = 4)
對(duì)角線上的密度圖使得對(duì)比洲之間的分布相對(duì)于堆疊的直方圖更加容易。改變散點(diǎn)圖的透明度增加了圖的可讀性,因?yàn)檫@些圖存在相當(dāng)多的重疊(ovelapping)。
現(xiàn)在是默認(rèn)散點(diǎn)圖矩陣的最后一個(gè)例子。為減少?gòu)?fù)雜度,我們僅畫出 2000 年以后的數(shù)據(jù)。我們?nèi)耘f把洲著色,但是不畫出「年」這一列。為了限制畫出的列的數(shù)量,我們給函數(shù)傳遞了一個(gè) vars 列表。為了更好的闡明這個(gè)圖,我們還加上了標(biāo)題。
# Plot colored by continent for years 2000-2007
sns.pairplot(df[df[ year ] >= 2000],
vars = [ life_exp , log_pop , log_gdp_per_cap ],
hue = continent , diag_kind = kde ,
plot_kws = { alpha : 0.6, s : 80, edgecolor : k },
size = 4);
# Title
plt.suptitle( Pair Plot of Socioeconomic Data for 2000-2007 ,
size = 28);
現(xiàn)在開始變得相當(dāng)好看了!如果繼續(xù)建模,我們可能會(huì)使用這些圖中的信息指導(dǎo)我們的選擇。例如,我們知道 log_gdp_per_cap 與 life_exp 是成正相關(guān)的,所以我們會(huì)創(chuàng)建一個(gè)線性模型來量化這種關(guān)系。本文主要集中在畫圖上面,如果希望更多地探索數(shù)據(jù),我們可以使用 PairGrid 類定制散點(diǎn)圖。
使用 PairGrid 的定制化
與 sns.pairplot 函數(shù)相反,sns.PairGrid 是一個(gè)類,這意味著它不能自動(dòng)填充圖。我們創(chuàng)建一個(gè)類實(shí)例,然后為網(wǎng)格的不同部分匹配特定的函數(shù)。為了給數(shù)據(jù)創(chuàng)建 PairGrid 實(shí)例,我們使用了以下的代碼,這也限制了我們所展示的變量:
# Create an instance of the PairGrid class.
grid = sns.PairGrid(data= df_log[df_log[ year ] == 2007],
vars = [ life_exp , log_pop ,
log_gdp_per_cap ], size = 4)
如果我們要顯示內(nèi)容的話,則會(huì)得到一個(gè)空?qǐng)D,因?yàn)槲覀冞€沒有為網(wǎng)格部分匹配任何函數(shù)。一個(gè) PairGrid 需要填充三個(gè)網(wǎng)格部分:上三角、下三角和對(duì)角線。為了給這些部分匹配圖,我們使用在這一部分使用 grid.map 方法。例如,為了給上三角匹配一個(gè)散點(diǎn)圖,我們使用:
# Map a scatter plot to the upper triangle
grid = grid.map_upper(plt.scatter, color = darkred )
map_upper 方法采用任意接受兩個(gè)變量數(shù)組的函數(shù)(例如 plt.scatter),以及相關(guān)的關(guān)鍵詞(例如 color)。map_lower 方法幾乎與其相同,但是它填充的是網(wǎng)格的下三角。map_diag 與這兩者稍有不同,因?yàn)樗捎媒邮軉蝹€(gè)數(shù)組的函數(shù)(回想一下,對(duì)角線只顯示單個(gè)變量)。一個(gè)例子是 plt.hist,我們使用它來填充對(duì)角線部分:
# Map a histogram to the diagonal
grid = grid.map_diag(plt.hist, bins = 10, color = darkred ,
edgecolor = k )
# Map a density plot to the lower triangle
grid = grid.map_lower(sns.kdeplot, cmap = Reds )
在這個(gè)例子中,我們?cè)谙氯侵惺褂枚S核密度估計(jì)(即密度圖)。將上面的內(nèi)容合在一起,這段代碼就會(huì)給出下圖:
當(dāng)我們想要?jiǎng)?chuàng)建自定義函數(shù)將不同的信息匹配到該圖時(shí),使用 PairGrid 類的實(shí)際好處就會(huì)顯露出來。例如,我可能希望在散點(diǎn)圖上增加兩個(gè)變量的皮爾遜相關(guān)系數(shù)。為了做到這一點(diǎn),我會(huì)寫一個(gè)使用兩個(gè)數(shù)組的函數(shù),用它來計(jì)算統(tǒng)計(jì)數(shù)據(jù),然后畫在圖上。下面的代碼展示的就是如何做到這件事(來源:https://stackoverflow.com/questions/30942577/seaborn-correlation-coefficient-on-pairgrid)。
# Function to calculate correlation coefficient between two arrays
def corr(x, y, **kwargs):
# Calculate the value
coef = np.corrcoef(x, y)[0][1]
# Make the label
label = r $
ho$ = + str(round(coef, 2))
# Add the label to the plot
ax = plt.gca()
ax.annotate(label, xy = (0.2, 0.95), size = 20, xycoords = ax.transAxes)
# Create a pair grid instance
grid = sns.PairGrid(data= df[df[ year ] == 2007],
vars = [ life_exp , log_pop , log_gdp_per_cap ], size = 4)
# Map the plots to the locations
grid = grid.map_upper(plt.scatter, color = darkred )
grid = grid.map_upper(corr)
grid = grid.map_lower(sns.kdeplot, cmap = Reds )
grid = grid.map_diag(plt.hist, bins = 10, edgecolor = k , color = darkred );
我們的新函數(shù)被匹配到上三角中了,因?yàn)槲覀冃枰獌蓚€(gè)數(shù)組來計(jì)算相關(guān)系數(shù)(還要注意到,我們可以將多個(gè)函數(shù)匹配到網(wǎng)格部分中)。這樣就得到了下圖:
現(xiàn)在相關(guān)系數(shù)已經(jīng)出現(xiàn)在上面的散點(diǎn)圖上了。這是一個(gè)比較直接的例子,但是我們可以使用 PairGrid 映射任何一個(gè)我們想要映射到圖上的函數(shù)。我們可以按照需要增加相關(guān)的信息,這可以幫助我們解決如何寫這個(gè)函數(shù)的問題!最后一個(gè)例子,下圖對(duì)角線上展示了總結(jié)統(tǒng)計(jì)信息:
雖然還需要一些整理,但是它展示了一個(gè)通用的思想:除了使用庫(kù)中現(xiàn)有的函數(shù)將數(shù)據(jù)映射到圖上,例如 matplotlib,我們可以寫自己的函數(shù)來展示自定義信息。
總結(jié)
散點(diǎn)圖矩陣(pairs plots)是一款強(qiáng)大的工具,可以快速探索數(shù)據(jù)集中的分布和關(guān)系。為了讓散點(diǎn)圖矩陣可定制、可擴(kuò)展,Seaborn 通過 Pair Grid 類提供了一個(gè)簡(jiǎn)單的默認(rèn)方法。在數(shù)據(jù)分析項(xiàng)目中,大部分的價(jià)值通常不是來自于酷炫的機(jī)器學(xué)習(xí),而是來自對(duì)數(shù)據(jù)的直接可視化。散點(diǎn)圖矩陣給我們提供了對(duì)數(shù)據(jù)的概覽,是數(shù)據(jù)分析項(xiàng)目很棒的起點(diǎn)。
聯(lián)系客服