作者:xiaoyu
微信公眾號:Python資料科學
知乎:python資料分析師
Seaborn學習大綱
seaborn
的學習內容主要包含以下幾個部分:
- 風格管理
- 繪圖風格設定
- 顏色風格設定
- 繪圖方法
資料集的分佈視覺化
- 分類資料視覺化
- 線性關係視覺化
- 結構網格
- 資料識別網格繪圖
本次將主要介紹資料集的分佈視覺化
的使用。
資料集分佈視覺化
當處理一個資料集的時候,我們經常會想要先看看特徵變數是如何分佈的。這會讓我們對資料特徵有個很好的初始認識,同時也會影響後續資料分析以及特徵工程的方法。本篇將會介紹如何使用 seaborn 的一些工具來檢測單變數和雙變數分佈情況。
首先還是先匯入需要的模組和資料集。
%matplotlib inline
import numpy as np
import pandas as pd
from scipy import stats, integrate
import matplotlib.pyplot as plt
import seaborn as sns
sns.set(color_codes=True)
np.random.seed(sum(map(ord, "distributions")))
複製程式碼
注意:這裡的資料集是隨機產生的分佈資料,由 numpy 生成,資料型別是ndarray。當然,pandas 的 Series 資料型別也是可以使用的,比如我們經常需要從 DataFrame 表中提取某一特徵(某一列)來檢視分佈情況。
繪製單變數分佈
在 seaborn 中,快速觀察單變數分佈的最方便的方法就是使用 distplot()
函式。預設會使用柱狀圖(histogram)來繪製,並提供一個適配的核密度估計(KDE)。
x = np.random.normal(size=100)
sns.distplot(x);
複製程式碼
直方圖(histograms
直方圖是比較常見的,並且在 matplotlib 中已經存在了 hist
函式。直方圖在橫座標的資料值範圍內均等分的形成一定數量的資料段(bins),並在每個資料段內用矩形條(bars)顯示y軸觀察數量的方式,完成了對的資料分佈的視覺化展示。
為了說明這個,我們可以移除 kde plot,然後新增 rug plot(在每個觀察點上的垂直小標籤)。當然,你也可以使用 rug plot 自帶的 rugplot()
函式,但是也同樣可以在 distplot
中實現:
sns.distplot(x, kde=False, rug=True);
複製程式碼
當繪製直方圖時,你最需要確定的引數是矩形條的數目以及如何放置它們。distplot()
使用了一個簡單的規則推測出預設情況下最合適的數量,但是或多或少的對 bins 數量進行一些嘗試也許能找出資料的其它特徵:
sns.distplot(x, bins=20, kde=False, rug=True);
複製程式碼
核密度估計(Kernel density estimation)
核密度估計可能不被大家所熟悉,但它對於繪製分佈的形狀是一個非常有用的工具。就像直方圖那樣,KDE plots 會在一個軸上通過高度沿著其它軸將觀察的密度編碼。
sns.distplot(x, hist=False, rug=True);
複製程式碼
繪製 KDE 比繪製直方圖需要更多的計算。它的計算過程是這樣的,每個觀察點首先都被以這個點為中心的正態分佈曲線所替代。
x = np.random.normal(0, 1, size=30)
bandwidth = 1.06 * x.std() * x.size ** (-1 / 5.)
support = np.linspace(-4, 4, 200)
kernels = []
for x_i in x:
kernel = stats.norm(x_i, bandwidth).pdf(support)
kernels.append(kernel)
plt.plot(support, kernel, color="r")
sns.rugplot(x, color=".2", linewidth=3);
複製程式碼
然後,這些替代的曲線進行加和,並計算出在每個點的密度值。最終生成的曲線被歸一化,以使得曲線下面包圍的面積是1。
density = np.sum(kernels, axis=0)
density /= integrate.trapz(density, support)
plt.plot(support, density);
複製程式碼
我們可以看到,如果我們使用 kdeplot()
函式,我們可以得到相同的曲線。這個函式實際上也被 distplot()
所使用,但是如果你就只想要密度估計,那麼 kdeplot()
會提供一個直接的介面更簡單的操作其它選項。
sns.kdeplot(x, shade=True);
複製程式碼
KDE 的頻寬引數(bw)控制著密度估計曲線的寬窄形狀,有點類似直方圖中的 bins 引數的作用。它對應著我們上面繪製的 KDE 的寬度。預設情況下,函式會按照一個通用的參考規則來估算出一個合適的值,但是嘗試更大或者更小也可能會有幫助:
sns.kdeplot(x)
sns.kdeplot(x, bw=.2, label="bw: 0.2")
sns.kdeplot(x, bw=2, label="bw: 2")
plt.legend();
複製程式碼
如上所述,高斯KDE過程的意味著估計延續了資料集中最大和最小的值。 可以通過cut
引數來控制繪製曲線的極值值的距離; 然而,這隻影響曲線的繪製方式,而不是曲線如何擬合:
sns.kdeplot(x, shade=True, cut=0)
sns.rugplot(x);
複製程式碼
擬合引數分佈
你也可以使用distplot()
將引數分佈擬合到資料集,並視覺化地評估其與觀察資料的對應程度:
x = np.random.gamma(6, size=200)
sns.distplot(x, kde=False, fit=stats.gamma);
複製程式碼
繪製雙變數分佈
對於雙變數分佈的視覺化也是非常有用的。在 seaborn 中最簡單的方法就是使用 joinplot()
函式,它能夠建立一個多皮膚圖形來展示兩個變數之間的聯合關係,以及每個軸上單變數的分佈情況。
mean, cov = [0, 1], [(1, .5), (.5, 1)]
data = np.random.multivariate_normal(mean, cov, 200)
df = pd.DataFrame(data, columns=["x", "y"])
複製程式碼
Scatterplots
雙變數分佈最熟悉的視覺化方法無疑是散點圖了,在散點圖中每個觀察結果以x軸和y軸值所對應的點展示。你可以用 matplotlib 的 plt.scatter
函式來繪製一個散點圖,它也是jointplot()
函式顯示的預設方式。
sns.jointplot(x="x", y="y", data=df)
複製程式碼
Hexbin plots
直方圖 histogram
的雙變數類似圖被稱為 “hexbin” 圖,因為它展示了落在六角形箱內的觀測量。這種繪圖對於相對大的資料集效果最好。它可以通過 matplotlib 的 plt.hexbin
函式使用,也可以作為 jointplot
的一種型別引數使用。它使用白色背景的時候視覺效果最好。
x, y = np.random.multivariate_normal(mean, cov, 1000).T
with sns.axes_style("white"):
sns.jointplot(x=x, y=y, kind="hex", color="k");
複製程式碼
Kernel density estimation
還使用上面描述的核密度估計過程來視覺化雙變數分佈。在 seaborn 中,這種繪圖以等高線圖展示,並且可以作為 jointplot()
的一種型別引數使用。
sns.jointplot(x="x", y="y", data=df, kind="kde");
複製程式碼
你也可以用 kdeplot
函式來繪製一個二維的核密度圖形。這可以將這種繪圖繪製到一個特定的(可能已經存在的)matplotlib軸上,而jointplot()
函式只能管理自己:
f, ax = plt.subplots(figsize=(6, 6))
sns.kdeplot(df.x, df.y, ax=ax)
sns.rugplot(df.x, color="g", ax=ax)
sns.rugplot(df.y, vertical=True, ax=ax);
複製程式碼
如果你希望讓雙變數密度看起來更連續,您可以簡單地增加 n_levels 引數增加輪廓級數:
f, ax = plt.subplots(figsize=(6, 6))
cmap = sns.cubehelix_palette(as_cmap=True, dark=0, light=1, reverse=True)
sns.kdeplot(df.x, df.y, cmap=cmap, n_levels=60, shade=True);
複製程式碼
jointplot()
函式使用JointGrid
來管理圖形。為了獲得更多的靈活性,您可能需要直接使用JointGrid
繪製圖形。jointplot()
在繪製後返回JointGrid物件,你可以用它來新增更多層或調整視覺化的其他方面:
g = sns.jointplot(x="x", y="y", data=df, kind="kde", color="m")
g.plot_joint(plt.scatter, c="w", s=30, linewidth=1, marker="+")
g.ax_joint.collections[0].set_alpha(0)
g.set_axis_labels("$X$", "$Y$");
複製程式碼
視覺化資料整合對關係
為了繪製資料集中多個成對的雙變數,你可以使用 pairplot()
函式。這建立了一個軸矩陣,並展示了在一個 DataFrame 中每對列的關係。預設情況下,它也繪製每個變數在對角軸上的單變數。
iris = sns.load_dataset("iris")
sns.pairplot(iris);
複製程式碼
就像 joinplot()
和 JoinGrid
之間的關係,pairplot()
函式建立在 PairGrid
物件之上,直接使用可以更靈活。
g = sns.PairGrid(iris)
g.map_diag(sns.kdeplot)
g.map_offdiag(sns.kdeplot, cmap="Blues_d", n_levels=6);
/Users/mwaskom/anaconda/lib/python2.7/site-packages/matplotlib/axes/_axes.py:545: UserWarning: No labelled objects found. Use label=`...` kwarg on individual plots.
warnings.warn("No labelled objects found. "
複製程式碼
參考:http://seaborn.pydata.org/tutorial.html
關注微信公眾號Python資料科學,獲取 120G
人工智慧 學習資料。