資料視覺化Seaborn從零開始學習教程(三) 資料分佈視覺化篇

Python資料科學發表於2019-03-01

作者:xiaoyu

微信公眾號:Python資料科學

知乎:python資料分析師


Seaborn學習大綱

seaborn的學習內容主要包含以下幾個部分:

  1. 風格管理
    • 繪圖風格設定
    • 顏色風格設定
  2. 繪圖方法
    • 資料集的分佈視覺化
    • 分類資料視覺化
    • 線性關係視覺化
  3. 結構網格
    • 資料識別網格繪圖

本次將主要介紹資料集的分佈視覺化的使用。

資料集分佈視覺化

當處理一個資料集的時候,我們經常會想要先看看特徵變數是如何分佈的。這會讓我們對資料特徵有個很好的初始認識,同時也會影響後續資料分析以及特徵工程的方法。本篇將會介紹如何使用 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);
複製程式碼
資料視覺化Seaborn從零開始學習教程(三) 資料分佈視覺化篇

直方圖(histograms

直方圖是比較常見的,並且在 matplotlib 中已經存在了 hist 函式。直方圖在橫座標的資料值範圍內均等分的形成一定數量的資料段(bins),並在每個資料段內用矩形條(bars)顯示y軸觀察數量的方式,完成了對的資料分佈的視覺化展示。

為了說明這個,我們可以移除 kde plot,然後新增 rug plot(在每個觀察點上的垂直小標籤)。當然,你也可以使用 rug plot 自帶的 rugplot() 函式,但是也同樣可以在 distplot 中實現:

sns.distplot(x, kde=False, rug=True);
複製程式碼
資料視覺化Seaborn從零開始學習教程(三) 資料分佈視覺化篇

當繪製直方圖時,你最需要確定的引數是矩形條的數目以及如何放置它們。distplot()使用了一個簡單的規則推測出預設情況下最合適的數量,但是或多或少的對 bins 數量進行一些嘗試也許能找出資料的其它特徵:

sns.distplot(x, bins=20, kde=False, rug=True);
複製程式碼
資料視覺化Seaborn從零開始學習教程(三) 資料分佈視覺化篇

核密度估計(Kernel density estimation)

核密度估計可能不被大家所熟悉,但它對於繪製分佈的形狀是一個非常有用的工具。就像直方圖那樣,KDE plots 會在一個軸上通過高度沿著其它軸將觀察的密度編碼。

sns.distplot(x, hist=False, rug=True);
複製程式碼
資料視覺化Seaborn從零開始學習教程(三) 資料分佈視覺化篇

繪製 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);
複製程式碼
資料視覺化Seaborn從零開始學習教程(三) 資料分佈視覺化篇

然後,這些替代的曲線進行加和,並計算出在每個點的密度值。最終生成的曲線被歸一化,以使得曲線下面包圍的面積是1。

density = np.sum(kernels, axis=0)
density /= integrate.trapz(density, support)
plt.plot(support, density);
複製程式碼
資料視覺化Seaborn從零開始學習教程(三) 資料分佈視覺化篇

我們可以看到,如果我們使用 kdeplot() 函式,我們可以得到相同的曲線。這個函式實際上也被 distplot() 所使用,但是如果你就只想要密度估計,那麼 kdeplot() 會提供一個直接的介面更簡單的操作其它選項。

sns.kdeplot(x, shade=True);
複製程式碼
資料視覺化Seaborn從零開始學習教程(三) 資料分佈視覺化篇

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();
複製程式碼
資料視覺化Seaborn從零開始學習教程(三) 資料分佈視覺化篇

如上所述,高斯KDE過程的意味著估計延續了資料集中最大和最小的值。 可以通過cut引數來控制繪製曲線的極值值的距離; 然而,這隻影響曲線的繪製方式,而不是曲線如何擬合:

sns.kdeplot(x, shade=True, cut=0)
sns.rugplot(x);
複製程式碼
資料視覺化Seaborn從零開始學習教程(三) 資料分佈視覺化篇

擬合引數分佈

你也可以使用distplot()將引數分佈擬合到資料集,並視覺化地評估其與觀察資料的對應程度:

x = np.random.gamma(6, size=200)
sns.distplot(x, kde=False, fit=stats.gamma);
複製程式碼
資料視覺化Seaborn從零開始學習教程(三) 資料分佈視覺化篇

繪製雙變數分佈

對於雙變數分佈的視覺化也是非常有用的。在 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)
複製程式碼
資料視覺化Seaborn從零開始學習教程(三) 資料分佈視覺化篇

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");
複製程式碼
資料視覺化Seaborn從零開始學習教程(三) 資料分佈視覺化篇

Kernel density estimation

還使用上面描述的核密度估計過程來視覺化雙變數分佈。在 seaborn 中,這種繪圖以等高線圖展示,並且可以作為 jointplot()的一種型別引數使用。

sns.jointplot(x="x", y="y", data=df, kind="kde");
複製程式碼
資料視覺化Seaborn從零開始學習教程(三) 資料分佈視覺化篇

你也可以用 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);
複製程式碼
資料視覺化Seaborn從零開始學習教程(三) 資料分佈視覺化篇

如果你希望讓雙變數密度看起來更連續,您可以簡單地增加 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);
複製程式碼
資料視覺化Seaborn從零開始學習教程(三) 資料分佈視覺化篇

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$");
複製程式碼
資料視覺化Seaborn從零開始學習教程(三) 資料分佈視覺化篇

視覺化資料整合對關係

為了繪製資料集中多個成對的雙變數,你可以使用 pairplot() 函式。這建立了一個軸矩陣,並展示了在一個 DataFrame 中每對列的關係。預設情況下,它也繪製每個變數在對角軸上的單變數。

iris = sns.load_dataset("iris")
sns.pairplot(iris);
複製程式碼
資料視覺化Seaborn從零開始學習教程(三) 資料分佈視覺化篇

就像 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. "
複製程式碼
資料視覺化Seaborn從零開始學習教程(三) 資料分佈視覺化篇

參考:http://seaborn.pydata.org/tutorial.html


關注微信公眾號Python資料科學,獲取 120G 人工智慧 學習資料。

資料視覺化Seaborn從零開始學習教程(三) 資料分佈視覺化篇
資料視覺化Seaborn從零開始學習教程(三) 資料分佈視覺化篇

相關文章