Python Matplotlib数据可视化绘图之(二)————箱线图

文章目录

  • 前言
  • 一、所用到的模块
  • 二、单一颜色的普通不分组箱线图
  • 1.示例数据如下
  • 2.代码如下
  • 2.1 代码如下(示例):
  • 2.1.1 Case1:
  • 三、多种颜色的普通不分组箱线图
  • 1.示例数据如下
  • 2.代码如下
  • 2.1 代码如下(示例):
  • 2.1.1 Case1:
  • 四、多种颜色的普通分组箱线图和散点图的叠加图
  • 1.示例数据如下
  • 2.代码如下
  • 2.1 代码如下(示例):
  • 2.1.1 Case1:
  • 五、总结

  • 前言

    本文我们主要介绍利用Python中的Matplotlib模块进行几种箱线图的画法,包括整张图片只有一种颜色的不分组箱线图、整张图片有好几种颜色的不分组箱线图、整张图片有好几种颜色的分组箱线图等。


    一、所用到的模块

    主要利用Python中的Matplotlib模块完成该功能。

    二、单一颜色的普通不分组箱线图

    1.示例数据如下

    表格如下(示例):


    班别 语文成绩(分/100分制)
    甲班 80
    90
    75
    65
    85
    95
    100
    100
    80
    70
    90
    95
    85
    86
    92
    90
    95
    90
    85
    100
    乙班 60
    70
    80
    65
    75
    80
    73
    75
    85
    90
    95
    65
    70
    75
    80
    85
    95
    85
    80
    70
    丙班 60
    80
    100
    100
    100
    100
    90
    95
    95
    95
    85
    95
    95
    95
    95
    80
    95
    90
    90
    90

    现在需要把表格中的数据绘制成箱线图,从而进一步分析每个班级的学生成绩情况。

    2.代码如下

    2.1 代码如下(示例):

    2.1.1 Case1:

    import matplotlib.pyplot as plt
    
    # 设置字体, 解决中文乱码问题
    plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
    # 解决图像中的'-'负号的乱码问题
    plt.rcParams['axes.unicode_minus'] = False
    
    ClassA_C = [80, 90, 75, 65, 85, 95, 100, 100, 80, 70, 90, 95, 85, 86, 92, 90, 95, 90, 85, 100]
    ClassB_C = [60, 70, 80, 65, 75, 80, 73, 75, 85, 90, 95, 65, 70, 75, 80, 85, 95, 85, 80, 70]
    ClassC_C = [60, 80, 100, 100, 100, 100, 90, 95, 95, 95, 85, 95, 95, 95, 95, 80, 95, 90, 90, 90]
    
    fig = plt.figure(figsize=(8, 6), facecolor='#B0C4DE')
    ax = fig.add_subplot(facecolor='white')
    # 红橙黄绿青蓝紫
    color_list = ['#FF0000', '#FF8C00', '#FFFF00', '#00FF00', '#00FFFF', '#0000FF', '#800080']
    
    x_labels = ['甲班', '乙班', '丙班']
    x_loc = [1, 2, 3]
    
    boxplot_data = [ClassA_C, ClassB_C, ClassC_C]
    
    ax.boxplot(boxplot_data, positions=x_loc, widths=0.4, patch_artist=True,
               medianprops={'lw': 1, 'color': '#FF8C00'},
               boxprops={'facecolor': 'None', 'edgecolor': '#FF8C00'},
               capprops={'lw': 1, 'color': '#FF8C00'},
               whiskerprops={'ls': '-', 'lw': 1, 'color': '#FF8C00'},
               showfliers=True,
               flierprops={'marker': 'o', 'markerfacecolor': '#FF8C00', 'markeredgecolor': '#FF8C00', 'markersize': 8})
    ax.grid(True, ls=':', color='b', alpha=0.3)
    plt.title('甲乙丙各班语文成绩Box_chart分析', fontweight='bold')
    ax.set_xticks(x_loc)
    ax.set_xticklabels(x_labels, rotation=90)
    ax.set_ylabel('分数/百分制', fontweight='bold')
    # 设置x, y坐标轴的刻度标签字体加粗
    plt.xticks(weight='bold')
    plt.yticks(weight='bold')
    fig.tight_layout()
    plt.show()
    

    输出结果如下:

    注意:如果想保存这种画布带背景颜色且轴域也带背景颜色的图片(在此图中,画布[fig]背景颜色为#B0C4DE,轴域[ax]背景颜色为white),需要使用以下语句保存到本地,具体语句如下:

    plt.savefig(picture_name + '.jpg', facecolor=self.fig.get_facecolor())
    # 其中picture_name为给图片命的名字
    

    三、多种颜色的普通不分组箱线图

    1.示例数据如下

    表格如下(示例):


    班别 语文成绩(分/100分制)
    甲班 80
    90
    75
    65
    85
    95
    100
    100
    80
    70
    90
    95
    85
    86
    92
    90
    95
    90
    85
    100
    乙班 60
    70
    80
    65
    75
    80
    73
    75
    85
    90
    95
    65
    70
    75
    80
    85
    95
    85
    80
    30
    丙班 60
    80
    100
    100
    100
    100
    90
    95
    95
    95
    85
    95
    95
    95
    95
    80
    95
    90
    90
    90

    现在需要把表格中的数据绘制成箱线图,从而进一步分析每个班级的学生成绩情况。

    2.代码如下

    2.1 代码如下(示例):

    2.1.1 Case1:

    import matplotlib.pyplot as plt
    
    # 设置字体, 解决中文乱码问题
    plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
    # 解决图像中的'-'负号的乱码问题
    plt.rcParams['axes.unicode_minus'] = False
    
    ClassA_C = [80, 90, 75, 65, 85, 95, 100, 100, 80, 70, 90, 95, 85, 86, 92, 90, 95, 90, 85, 100]
    ClassB_C = [60, 70, 80, 65, 75, 80, 73, 75, 85, 90, 95, 65, 70, 75, 80, 85, 95, 85, 80, 30]
    ClassC_C = [60, 80, 100, 100, 100, 100, 90, 95, 95, 95, 85, 95, 95, 95, 95, 80, 95, 90, 90, 90]
    
    fig = plt.figure(figsize=(8, 6), facecolor='#B0C4DE')
    ax = fig.add_subplot(facecolor='white')
    # 橙绿蓝
    color_list = ['#FF8C00', '#00FF00', '#0000FF']
    # marker的形状列表
    marker_list = ['o', 'D', 's']
    # marker的大小列表
    markersize_list = [3, 8, 13]
    
    x_labels = ['甲班', '乙班', '丙班']
    x_loc = [1, 2, 3]
    
    boxplot_data = [ClassA_C, ClassB_C, ClassC_C]
    print(len(boxplot_data))
    
    bp = ax.boxplot(boxplot_data, positions=x_loc, widths=0.4, patch_artist=True, showfliers=True)
    
    for i in range(len(bp['boxes'])):
        bp['boxes'][i].set(facecolor='None', edgecolor=color_list[i])
    
        # 顶端, 末端两条线; 顶端:0, 2, 4; 末端:1, 3, 5
        bp['caps'][2 * i].set(color=color_list[i])
        bp['caps'][2 * i + 1].set(color=color_list[i])
    
        # 中位数那条线
        bp['medians'][i].set(color=color_list[i])
    
        # 顶端, 末端两条须; 顶端:0, 2, 4; 末端:1, 3, 5
        bp['whiskers'][2 * i].set(color=color_list[i])
        bp['whiskers'][2 * i + 1].set(color=color_list[i])
    
        # 分别设置异常点的形状, 填充颜色, 轮廓颜色, 大小
        bp['fliers'][i].set_marker(marker_list[i])
        bp['fliers'][i].set_markerfacecolor(color_list[i])
        bp['fliers'][i].set_markeredgecolor(color_list[i])
        bp['fliers'][i].set_markersize(markersize_list[i])
    
    ax.grid(True, ls=':', color='b', alpha=0.3)
    plt.title('甲乙丙各班语文成绩Box_chart分析', fontweight='bold')
    ax.set_xticks(x_loc)
    ax.set_xticklabels(x_labels, rotation=90)
    ax.set_ylabel('分数/百分制', fontweight='bold')
    plt.xticks(weight='bold')
    plt.yticks(weight='bold')
    fig.tight_layout()
    plt.show()
    

    输出结果如下:

    注意:如果想保存这种画布带背景颜色且轴域也带背景颜色的图片(在此图中,画布[fig]背景颜色为#B0C4DE,轴域[ax]背景颜色为white),需要使用以下语句保存到本地,具体语句如下:

    plt.savefig(picture_name + '.jpg', facecolor=self.fig.get_facecolor())
    # 其中picture_name为给图片命的名字
    

    四、多种颜色的普通分组箱线图和散点图的叠加图

    1.示例数据如下

    表格如下(示例):


    班别 语文成绩(分/100分制) 数学成绩(分/100分制) 英语成绩(分/100分制)
    甲班 80 70 90
    90 90 100
    75 95 100
    65 85 85
    85 75 75
    95 85 90
    100 90 100
    100 100 100
    80 100 75
    70 85 70
    90 90 85
    95 95 90
    85 98 95
    86 99 95
    92 85 90
    90 88 80
    95 86 70
    90 75 80
    85 78 70
    100 90 75
    乙班 60 60 70
    70 70 75
    80 75 75
    65 80 70
    75 75 60
    80 75 90
    73 65 98
    75 80 95
    85 60 85
    90 80 75
    95 90 70
    65 95 60
    70 95 65
    75 90 70
    80 80 75
    85 85 75
    95 75 80
    85 75 75
    80 60 70
    70 65 80
    丙班 60 100 80
    80 100 90
    100 100 100
    100 95 100
    100 95 100
    100 95 90
    90 95 95
    95 95 95
    95 90 95
    95 85 90
    85 90 95
    95 90 90
    95 90 95
    95 95 90
    95 90 95
    80 95 90
    95 95 95
    90 95 90
    90 95 95
    90 90 85

    现在需要把表格中的数据绘制成箱线图,从而进一步分析每个班级的学生成绩情况。

    2.代码如下

    2.1 代码如下(示例):

    2.1.1 Case1:

    import matplotlib.pyplot as plt
    import numpy as np
    
    # 设置字体, 解决中文乱码问题
    plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
    # 解决图像中的'-'负号的乱码问题
    plt.rcParams['axes.unicode_minus'] = False
    
    ClassA_C = [80, 90, 75, 65, 85, 95, 100, 100, 80, 70, 90, 95, 85, 86, 92, 90, 95, 90, 85, 100]
    ClassA_M = [70, 90, 95, 85, 75, 85, 90, 100, 100, 85, 90, 95, 98, 99, 85, 88, 86, 75, 78, 90]
    ClassA_E = [90, 100, 100, 85, 75, 90, 100, 100, 75, 70, 85, 90, 95, 95, 90, 80, 70, 80, 70, 75]
    
    ClassB_C = [60, 70, 80, 65, 75, 80, 73, 75, 85, 90, 95, 65, 70, 75, 80, 85, 95, 85, 80, 70]
    ClassB_M = [60, 70, 75, 80, 75, 75, 65, 80, 60, 80, 90, 95, 95, 90, 80, 85, 75, 75, 60, 65]
    ClassB_E = [70, 75, 75, 70, 60, 90, 98, 95, 85, 75, 70, 60, 65, 70, 75, 75, 80, 75, 70, 80]
    
    ClassC_C = [60, 80, 100, 100, 100, 100, 90, 95, 95, 95, 85, 95, 95, 95, 95, 80, 95, 90, 90, 90]
    ClassC_M = [100, 100, 100, 95, 95, 95, 95, 95, 90, 85, 90, 90, 90, 95, 90, 95, 95, 95, 95, 90]
    ClassC_E = [80, 90, 100, 100, 100, 90, 95, 95, 95, 90, 95, 90, 95, 90, 95, 90, 95, 90, 95, 85]
    
    fig = plt.figure(figsize=(8, 6), facecolor='#B0C4DE')
    ax = fig.add_subplot(facecolor='white')
    
    # 每个刻度标签下有几个group就有几个箱子
    group_dataA = [ClassA_C, ClassA_M, ClassA_E]
    
    boxplot_dataABC_C = [ClassA_C, ClassB_C, ClassC_C]
    boxplot_dataABC_M = [ClassA_M, ClassB_M, ClassC_M]
    boxplot_dataABC_E = [ClassA_E, ClassB_E, ClassC_E]
    
    # 橙绿蓝
    color_list = ['#FF8C00', '#00FF00', '#0000FF']
    
    x_labels = ['甲班', '乙班', '丙班']
    legend_labels = ['语文', '数学', '英语']
    length = len(x_labels)
    x_loc = np.arange(length)
    
    group_number = len(group_dataA)
    total_width = 0.6
    box_total_width = total_width * 0.65
    interval_total_width = total_width * 0.35
    box_width = box_total_width / group_number
    
    ###################################################
    if group_number == 1:
        interval_width = interval_total_width
    else:
        interval_width = interval_total_width / (group_number - 1)
    
    ###################################################
    if group_number % 2 == 0:
        x1_box = x_loc - (group_number / 2 - 1) * box_width - box_width / 2 - (group_number / 2 - 1) * interval_width - interval_width / 2
    else:
        x1_box = x_loc - ((group_number - 1) / 2) * box_width - ((group_number - 1) / 2) * interval_width
    x_list_box = [x1_box + box_width * i + interval_width * i for i in range(group_number)]
    
    
    boxplot_data = [boxplot_dataABC_C, boxplot_dataABC_M, boxplot_dataABC_E]
    
    for i in range(len(boxplot_data)):
        #####################################################################
        # 先画boxplot
        #######################
        # boxplot_data_num用来统计每组数据的长度, 画scatter图时会用到
        boxplot_data_num = []
        for j in boxplot_data[i]:
            boxplot_data_num_tmp = len(j)
            boxplot_data_num.append(boxplot_data_num_tmp)
        #######################
        ax.boxplot(boxplot_data[i], positions=x_list_box[i], widths=box_width, patch_artist=True,
                   medianprops={'lw': 1, 'color': color_list[i]},
                   boxprops={'facecolor': 'None', 'edgecolor': color_list[i]},
                   capprops={'lw': 1, 'color': color_list[i]},
                   whiskerprops={'ls': '-', 'lw': 1, 'color': color_list[i]},
                   showfliers=False, zorder=1)
        # flierprops = {'marker': 'o', 'markerfacecolor': color_list[i], 'markeredgecolor': color_list[i], 'markersize': 8}
        #####################################################################
        # 再画scatter
        # 将每一组箱线图统计的所有点绘制在图上
        # spotx是每一组箱线图所有的点的横坐标
        spotx = []
        for j_spotx, k_spotx in zip(x_list_box[i], boxplot_data_num):
            spotx_tmp = [j_spotx] * k_spotx
            spotx.append(spotx_tmp)
        # print('$$$spotx:', spotx)
        ax.scatter(spotx, boxplot_data[i], c=color_list[i], s=30, label=legend_labels[i], zorder=2)
    ax.grid(True, ls=':', color='b', alpha=0.3)
    plt.title('甲乙丙各班语文/数学/英语成绩Box_chart分析', fontweight='bold')
    ax.set_xticks(x_loc)
    ax.set_xticklabels(x_labels, rotation=90)
    ax.set_ylabel('分数/百分制', fontweight='bold')
    ################################################################################################################
    ################################################################################################################
    plt.legend(title='学科', loc='center left', bbox_to_anchor=(1.02, 0.5), facecolor='None', edgecolor='#000000',
               frameon=True, ncol=1, markerscale=3, borderaxespad=0, handletextpad=0.1, fontsize='x-large', title_fontsize='x-large')
    ################################################################################################################
    ################################################################################################################
    plt.xticks(weight='bold')
    plt.yticks(weight='bold')
    fig.tight_layout()
    plt.show()
    

    输出结果如下:

    注意:如果想保存这种画布带背景颜色且轴域也带背景颜色的图片(在此图中,画布[fig]背景颜色为#B0C4DE,轴域[ax]背景颜色为white),需要使用以下语句保存到本地,具体语句如下:

    plt.savefig(picture_name + '.jpg', facecolor=self.fig.get_facecolor())
    # 其中picture_name为给图片命的名字
    

    五、总结

    以上就是今天要讲的内容,本文详细介绍了各种箱线图的绘制过程和方法,并用实例给大家演示了具体的实现代码和实现逻辑,希望对大家学习画箱线图有帮助。最后我提出以下几个问题:
    (1)为什么我不直接在ax.boxplot()函数中直接用labels这个参数生成legend,反而要利用ax.scatter()函数中的label参数生成legend?
    (2)还有什么方法能够生成箱线图的图例?
    (3)箱线图的图例生成方法和柱状图、折线图、饼图、直方图、散点图等图的图例生成方法有什么不同之处或特别之处?
    这些将在后面将要写的一篇博文名为《Python Matplotlib数据可视化绘图之(五)————箱线图与散点图的叠加图》的文章中详细讲解

    物联沃分享整理
    物联沃-IOTWORD物联网 » Python Matplotlib数据可视化绘图之(二)————箱线图

    发表评论