seaborn + matplotlib 畫圖(一): 小提琴圖,箱型圖

Seaborn 是一個基于 matplotlib 且數(shù)據(jù)結(jié)構(gòu)與 pandas 統(tǒng)一的統(tǒng)計圖制作庫

前段時間有一些作圖需求,處理數(shù)據(jù)用的又是pandas,于是就發(fā)現(xiàn)了Seaborn這個作圖的好工具。之前的代碼在Jupyter notebook里,比較分散又沒有整理,平時也記不住這么多函數(shù)和參數(shù),想想還是整理一下分享出來,即方便自己查看,也能幫助有需要的人。
另外,在寫這篇文章的時候發(fā)現(xiàn)了Seaborn的中文文檔,相見恨晚啊,向翻譯大大們致敬。鏈接貼到下面了,有空了要好好學習學習。
Seaborn 中文文檔:https://seaborn.apachecn.org/#/README

seaborn + matplotlib 畫圖(一): 小提琴圖,箱型圖
seaborn + matplotlib 畫圖(二): 柱狀圖,散點圖
seaborn + matplotlib 畫圖(三): 熱圖

這篇文章中使用Iris數(shù)據(jù)集作為示例,提供一些簡單圖形的繪制方法,下面正式開始。

1. 導入所需包

主要用到的包有numpy,pandas,matplotlib 和 seaborn。

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

2. 載入Iris數(shù)據(jù)

df = pd.read_csv('http://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data', header=None)
df.columns = ['sepal_length','sepal_width','petal_length','petal_width','class']
print(df.shape)
print(df.head())
print(df['class'].value_counts())

-----outputs-----
(150, 5)

   sepal_length  sepal_width  petal_length  petal_width        class
0           5.1          3.5           1.4          0.2  Iris-setosa
1           4.9          3.0           1.4          0.2  Iris-setosa
2           4.7          3.2           1.3          0.2  Iris-setosa
3           4.6          3.1           1.5          0.2  Iris-setosa
4           5.0          3.6           1.4          0.2  Iris-setosa

Iris-virginica     50
Iris-setosa        50
Iris-versicolor    50
Name: class, dtype: int64

Iris數(shù)據(jù)集為 150行 5列,每一行為一個觀測對象,前4列分別是 sepal_length(花萼長度),sepal_width (花萼寬度),petal_length(花瓣長度),petal_width(花瓣寬度)。最后一列為class類別。共三類(Iris-virginica,Iris-setosa,Iris-versicolor),每類各50條記錄。

3. 顏色和marker類型

這里貼了3個網(wǎng)站,是matplotlib預(yù)設(shè)的顏色和marker,方便我們選擇顏色和marker形狀。
Named colors: https://matplotlib.org/stable/gallery/color/named_colors.html
Colormaps: https://matplotlib.org/stable/tutorials/colors/colormaps.html
Markers: https://matplotlib.org/stable/api/markers_api.html
這里我先為3種不同的鳶尾花指定3種顏色,存放到字典里,方便后面使用。選擇的顏色都是named colors里預(yù)設(shè)的。
另外,用一個列表存儲3種鳶尾花的繪圖順序。

pal = {'Iris-setosa':'lightcoral','Iris-versicolor':'navajowhite','Iris-virginica':'cornflowerblue'}
class_order = ['Iris-setosa','Iris-versicolor','Iris-virginica']

4. violinplot小提琴圖

首先使用violinplot()畫一個簡單的小提琴圖。

plt.figure(figsize=(5,5))        #定義圖像大小
g = sns.violinplot(data=df, x='class', y='sepal_length',         #傳入數(shù)據(jù),對sepal_length這一列畫圖,根據(jù)class分組
                   linewidth=3,        #線寬
                   inner='box',        #內(nèi)部數(shù)據(jù)形式,默認為box,內(nèi)部畫個小箱型圖            
                   palette=pal,        #指定顏色盤繪制不同顏色,若使用color參數(shù),則統(tǒng)一設(shè)置為一種顏色
                   order=class_order,        #指定順序
                   saturation=1)        #色彩飽和度,默認0.75
plt.show()
violinplot

雖然還行,不過還需要一些修改,比如軸標簽有下劃線,字體太小,想去掉上框線和右框線。

plt.figure(figsize=(5,5))
g = sns.violinplot(data=df, x='class', y='sepal_length', linewidth=3,
                   inner='box', palette=pal, order=class_order, saturation=1)

ylabel = 'Sepal length'
plt.ylabel(ylabel, fontsize=18)        #設(shè)置y軸標簽
plt.yticks(fontsize=15)        #設(shè)置y軸刻度字體大小
plt.xlabel('')        #去掉x軸標簽
plt.xticks(ticks=[0,1,2],        #設(shè)置要顯示的x軸刻度,若指定空列表則去掉x軸刻度
           labels=['Setosa','Versicolor','Virginiical'],        #設(shè)置x軸刻度顯示的文字,要與ticks對應(yīng)   
           fontsize=15,        #設(shè)置刻度字體大小
           rotation=60,        #設(shè)置刻度文字旋轉(zhuǎn)角度
           ha='right', va='center',        #刻度文字對齊方式,當rotation_mode為’anchor'時,對齊方式?jīng)Q定了文字旋轉(zhuǎn)的中心。ha也可以寫成horizontalalignment,va也可以寫成verticalalignment。
           rotation_mode='anchor')        #我的設(shè)置表示文字以右邊線的中點為中心旋轉(zhuǎn)。

ax = plt.axes()
ax.spines['top'].set_visible(False)        #去掉圖像上邊框和右邊框
ax.spines['right'].set_visible(False)

plt.show()
violinplot

看起來還不錯,但如果想要知道每個點的具體情況呢?不如把所有的點也畫上去吧。swarmplot()看起來非常合適。

plt.figure(figsize=(5,5))
g1 = sns.violinplot(data=df, x='class', y='sepal_length', linewidth=3,
                   inner='box', palette=pal, order=class_order, saturation=1)
ylabel = 'Sepal length'
plt.ylabel(ylabel, fontsize=18)
plt.yticks(fontsize=15)
plt.xlabel('')
plt.xticks(ticks=[0,1,2], labels=['Setosa','Versicolor','Virginiical'],
           fontsize=15, rotation=60, ha='right', va='center', rotation_mode='anchor')
ax = plt.axes()
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)

g2 = sns.swarmplot(data=df, x='class', y='sepal_length',
                   color='grey', alpha=0.5, size=4,        #顏色,透明度,大小
                   linewidth=0.5, edgecolor='black',        #邊線寬度,邊線顏色
                   order=class_order)        #順序和violinplot保持一致

plt.show()
violinplot

5. boxplot箱型圖

單獨的箱型圖

plt.figure(figsize=(5,5))
g = sns.boxplot(data=df, x='class', y='sepal_length',        #傳入數(shù)據(jù)
                linewidth=3,        #箱邊線寬度
                width=0.8,        #箱體寬度,默認0.8
                whis=1.5        #計算上限和下限時四分位距(IQR)前的系數(shù),默認1.5
                showfliers=True,        #是否顯示異常值
                fliersize=5,        #異常值大小,默認5
                palette=pal,        #顏色盤
                order=class_order,        #順序
                saturation=1)        #顏色飽和度,默認0.75

ylabel = 'Sepal length'
plt.ylabel(ylabel, fontsize=18)
plt.yticks(fontsize=15)
plt.xlabel('')
plt.xticks(ticks=[0,1,2], labels=['Setosa','Versicolor','Virginiical'],
           fontsize=15, ha='center', va='top')
ax = plt.axes()
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)

plt.show()
boxplot

這里順便對箱型圖做個介紹:
箱體(有顏色的部分)上邊緣:上四分位數(shù),Q3
箱體下邊緣:下四分位數(shù),Q1
箱體中線:中位數(shù)
上方橫線:上限范圍內(nèi)的最大值
下方橫線:下限范圍內(nèi)的最小值
橫線之外的點:異常值
上限計算:Q3+1.5×IQR
下限計算:Q1-1.5×IQR
IQR:四分位距 (interquartile range),IQR = Q3 - Q1

barplot + swarmplot
和小提琴圖一樣,我們可以在箱型圖的基礎(chǔ)上,畫上散點圖,這樣所有數(shù)據(jù)點的分布更加直觀。

plt.figure(figsize=(5,5))
g = sns.boxplot(data=df, x='class', y='sepal_length', linewidth=3, showfliers=False,
                palette=pal, order=class_order, saturation=1)


sns.swarmplot(data=df, x='class', y='sepal_length',
              color='grey', size=4, linewidth=0.5, edgecolor='k',
              order=class_order, alpha=0.75)
# sns.stripplot()

ylabel = 'Sepal length'
plt.ylabel(ylabel, fontsize=18)
plt.yticks(fontsize=15)
plt.xlabel('')
plt.xticks(ticks=[0,1,2], labels=['Setosa','Versicolor','Virginiical'],
           fontsize=15, ha='center', va='top')
ax = plt.axes()
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)

plt.show()
barplot

空心的箱型圖
有時會在一些文獻中看到空心的箱型圖,雖然可以通過將顏色設(shè)置成白色達到空心的效果,但是barplot()中似乎沒有參數(shù)可以用來設(shè)置線的顏色,所以只能是黑色的線。好在還是有其它辦法設(shè)置的。

plt.figure(figsize=(5,5))
g = sns.boxplot(data=df, x='class', y='sepal_length', linewidth=5,showfliers=False,
                order=class_order,saturation=1)
for i in range(len(g.artists)):
    box = g.artists[i]
    box.set_edgecolor(pal[class_order[i]])
    box.set_facecolor('white')
    for j in range(5):
        k = i*5 + j
        line = g.lines[k]
        line.set_color(pal[class_order[i]])

sns.swarmplot(data=df, x='class', y='sepal_length',
              color='grey', size=4, linewidth=0.5, edgecolor='k',
              order=class_order, alpha=0.75)
# sns.stripplot()

ylabel = 'Sepal length'
plt.ylabel(ylabel, fontsize=18)
plt.yticks(fontsize=15)
plt.xlabel('')
plt.xticks(ticks=[0,1,2], labels=['Setosa','Versicolor','Virginiical'],
           fontsize=15, ha='center', va='top')
ax = plt.axes()
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)

plt.show()
barplot

其它部分基本一樣,主要的不同在于添加了4~11行設(shè)置顏色的代碼。
g.artists是一個列表,有3個元素(數(shù)量和箱型圖的數(shù)量一樣,對象類型是matplotlib.patches.PathPatch),分別是3個箱型圖的箱體,通過set_edgecolor()set_facecolor()方法這是邊線顏色(不包括中位線的顏色)和箱體顏色。
g.lines也是一個列表,有15個元素(對象類型是matplotlib.lines.Line2D),包含了箱體那個長方形之外的所有其它線,一個箱型圖有5條線(上邊線,下邊線,2條垂直線,1條中位線),第i個(從0開始)箱型圖的5條線index范圍是[i*5+0, i*5+4],通過set_color()方法設(shè)置顏色。

下面的例子可以更清楚的看到g.lines中的每個元素所對應(yīng)的線是哪條。

plt.figure(figsize=(5,5))
g = sns.boxplot(data=df, x='class', y='sepal_length', linewidth=5,showfliers=False,
              palette=pal, order=class_order,saturation=1)
for i in range(len(g.artists)):
    box = g.artists[i]
    box.set_edgecolor(pal[class_order[i]])
    box.set_facecolor('white')
    g.lines[i*5 + 0].set_color('r')
    g.lines[i*5 + 1].set_color('g')
    g.lines[i*5 + 2].set_color('b')
    g.lines[i*5 + 3].set_color('y')
    g.lines[i*5 + 4].set_color('purple')

ylabel = 'Sepal length'
plt.ylabel(ylabel, fontsize=18)
plt.yticks(fontsize=15)
plt.xlabel('')
plt.xticks(ticks=[0,1,2], labels=['Setosa','Versicolor','Virginiical'],
           fontsize=15, ha='center', va='top')
ax = plt.axes()
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)

plt.show()

按照紅、綠、藍、黃、紫的順序?qū).lines中的元素設(shè)置顏色。

barplot

6. savefig保存圖片

目前支持的圖片格式:eps, pdf, pgf, png, ps, raw, rgba, svg, svgz。
plt.savefig() 需要放在 plt.show() 之前。

outfig = 'E:/fig.png'     #supported formats: eps, pdf, pgf, png, ps, raw, rgba, svg, svgz
plt.savefig(outfig,
            dpi=300,        # 設(shè)置分辨率
            format=None,        #設(shè)置圖片格式,默認None,如果未設(shè)置使用文件名設(shè)置的格式
            bbox_inches='tight',        #設(shè)置為tight,防止有時圖片保存不完整
            facecolor='w',        #背景顏色,默認'w'白色
            edgecolor='w')        #邊框顏色,默認'w'白色
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容