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

本文详细介绍如何使用Python的Matplotlib模块绘制不同类型的箱线图,包括单一颜色不分组箱线图、多种颜色不分组箱线图及分组箱线图,并结合实际案例展示了具体代码实现。


前言

本文我们主要介绍利用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分制)
甲班807090
9090100
7595100
658585
857575
958590
10090100
100100100
8010075
708570
909085
959590
859895
869995
928590
908880
958670
907580
857870
1009075
乙班606070
707075
807575
658070
757560
807590
736598
758095
856085
908075
959070
659560
709565
759070
808075
858575
957580
857575
806070
706580
丙班6010080
8010090
100100100
10095100
10095100
1009590
909595
959595
959095
958590
859095
959090
959095
959590
959095
809590
959595
909590
909595
909085

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

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数据可视化绘图之(五)————箱线图与散点图的叠加图》的文章中详细讲解

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

北极熊在南极_whl

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值