美文网首页相关性
seaborn + matplotlib 画图(一): 小提琴图

seaborn + matplotlib 画图(一): 小提琴图

作者: WuYankang | 来源:发表于2021-03-26 15:48 被阅读0次

    Seaborn 是一个基于 matplotlib 且数据结构与 pandas 统一的统计图制作库

    前段时间有一些作图需求,处理数据用的又是pandas,于是就发现了Seaborn这个作图的好工具。之前的代码在Jupyter notebook里,比较分散又没有整理,平时也记不住这么多函数和参数,想想还是整理一下分享出来,即方便自己查看,也能帮助有需要的人。
    另外,在写这篇文章的时候发现了Seaborn的中文文档,相见恨晚啊,向翻译大大们致敬。链接贴到下面了,有空了要好好学习学习。
    Seaborn 中文文档:https://seaborn.apachecn.org/#/README

    seaborn + matplotlib 画图(一): 小提琴图,箱型图
    seaborn + matplotlib 画图(二): 柱状图,散点图
    seaborn + matplotlib 画图(三): 热图

    这篇文章中使用Iris数据集作为示例,提供一些简单图形的绘制方法,下面正式开始。

    1. 导入所需包

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

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

    2. 载入Iris数据

    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数据集为 150行 5列,每一行为一个观测对象,前4列分别是 sepal_length(花萼长度),sepal_width (花萼宽度),petal_length(花瓣长度),petal_width(花瓣宽度)。最后一列为class类别。共三类(Iris-virginica,Iris-setosa,Iris-versicolor),每类各50条记录。

    3. 颜色和marker类型

    这里贴了3个网站,是matplotlib预设的颜色和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里预设的。
    另外,用一个列表存储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',         #传入数据,对sepal_length这一列画图,根据class分组
                       linewidth=3,        #线宽
                       inner='box',        #内部数据形式,默认为box,内部画个小箱型图            
                       palette=pal,        #指定颜色盘绘制不同颜色,若使用color参数,则统一设置为一种颜色
                       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)        #设置y轴标签
    plt.yticks(fontsize=15)        #设置y轴刻度字体大小
    plt.xlabel('')        #去掉x轴标签
    plt.xticks(ticks=[0,1,2],        #设置要显示的x轴刻度,若指定空列表则去掉x轴刻度
               labels=['Setosa','Versicolor','Virginiical'],        #设置x轴刻度显示的文字,要与ticks对应   
               fontsize=15,        #设置刻度字体大小
               rotation=60,        #设置刻度文字旋转角度
               ha='right', va='center',        #刻度文字对齐方式,当rotation_mode为’anchor'时,对齐方式决定了文字旋转的中心。ha也可以写成horizontalalignment,va也可以写成verticalalignment。
               rotation_mode='anchor')        #我的设置表示文字以右边线的中点为中心旋转。
    
    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',        #传入数据
                    linewidth=3,        #箱边线宽度
                    width=0.8,        #箱体宽度,默认0.8
                    whis=1.5        #计算上限和下限时四分位距(IQR)前的系数,默认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

    这里顺便对箱型图做个介绍:
    箱体(有颜色的部分)上边缘:上四分位数,Q3
    箱体下边缘:下四分位数,Q1
    箱体中线:中位数
    上方横线:上限范围内的最大值
    下方横线:下限范围内的最小值
    横线之外的点:异常值
    上限计算:Q3+1.5×IQR
    下限计算:Q1-1.5×IQR
    IQR:四分位距 (interquartile range),IQR = Q3 - Q1

    barplot + swarmplot
    和小提琴图一样,我们可以在箱型图的基础上,画上散点图,这样所有数据点的分布更加直观。

    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)
    
    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

    空心的箱型图
    有时会在一些文献中看到空心的箱型图,虽然可以通过将颜色设置成白色达到空心的效果,但是barplot()中似乎没有参数可以用来设置线的颜色,所以只能是黑色的线。好在还是有其它办法设置的。

    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)
    
    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行设置颜色的代码。
    g.artists是一个列表,有3个元素(数量和箱型图的数量一样,对象类型是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()方法设置颜色。

    下面的例子可以更清楚的看到g.lines中的每个元素所对应的线是哪条。

    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()
    

    按照红、绿、蓝、黄、紫的顺序对g.lines中的元素设置颜色。

    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,        # 设置分辨率
                format=None,        #设置图片格式,默认None,如果未设置使用文件名设置的格式
                bbox_inches='tight',        #设置为tight,防止有时图片保存不完整
                facecolor='w',        #背景颜色,默认'w'白色
                edgecolor='w')        #边框颜色,默认'w'白色
    

    相关文章

      网友评论

        本文标题:seaborn + matplotlib 画图(一): 小提琴图

        本文链接:https://www.haomeiwen.com/subject/tzarhltx.html