文章目录
- 前言
- 一、Matplotlib绘制箱线图介绍
- 1. plt.boxplot()参数详解
- 1.1、x:指定要绘制箱线图的数据
- 1.2、notch:是否以凹口的形式展现箱线图
- 1.3、sym:指定异常点的形状
- 1.4、vert:是否需要将箱线图垂直摆放,True:垂直,False:水平;默认垂直摆放
- 1.5、whis:指定上下须与上下四分位的距离,默认为1.5倍的四分位差
- 1.6、positions:指定箱线图的位置,默认为[0,1,2…]
- 1.7、widths=None:指定箱线图的宽度
- 1.8、patch_artist:是否填充箱体的颜色,True:填充,False:不填充;默认False
- 1.9、showmeans:是否显示均值,默认不显示
- 1.10、meanline:是否用线的形式表示均值,默认用点来表示
- 1.11、showcaps:是否显示箱线图顶端和末端的两条线,默认显示
- 1.12、showbox:是否显示箱线图的箱体,默认显示
- 1.13、showfliers:是否显示异常值,默认显示
- 1.14、labels:为箱线图添加标签,类似于图例的作用
- 1.15、boxprops:设置箱体的属性,如边框色,填充色等
- 1.16、filerprops:设置异常值的属性
- 1.17、medianprops:设置中位数的属性,如线的类型、粗细等
- 1.18、meanprops:设置均值的属性,如点的大小、颜色等(注:showmeans必须设置为True,不然均值不显示)
- 1.19、capprops:设置箱线图顶端和末端线条的属性,如颜色、粗细等
- 1.20、whiskerprops:设置须的属性,如颜色、粗细、线的类型等
- 2. 在箱线图上叠加散点图时图层参数设置(zorder)
- 3. 回答往期文章《Python Matplotlib数据可视化绘图之(二)————箱线图》中的总结中所提的问题,文章网址链接为:https://blog.csdn.net/Mr_Dragon66/article/details/127814202?spm=1001.2014.3001.5501
- 二、多种颜色的普通分组箱线图和散点图的叠加图
- 三、总结
前言
本文我们主要介绍利用Python中的Matplotlib模块进行箱线图的画法介绍,以及箱线图和散点图的叠加图的画法介绍,包括整张图片只有一种颜色的不分组箱线图和散点图的叠加图、整张图片有好几种颜色的不分组箱线图和散点图的叠加图、整张图片有好几种颜色的分组箱线图和散点图的叠加图等。
一、Matplotlib绘制箱线图介绍
1. plt.boxplot()参数详解
Python绘制箱线图主要用matplotlib库里的pyplot模块里的boxplot()函数。
plt.boxplot(x, # 指定要绘制箱线图的数据;
notch=None, # 是否是凹口的形式展现箱线图,默认非凹口;
sym=None, # 指定异常点的形状,默认为+号显示;
vert=None, # 是否需要将箱线图垂直摆放,默认垂直摆放;
whis=None, # 指定上下须与上下四分位的距离,默认为1.5倍的四分位差;
positions=None, # 指定箱线图的位置,默认为[0, 1, 2…];
widths=None, # 指定箱线图的宽度;
patch_artist=None, # 是否填充箱体的颜色;
bootstrap=None, #
usermedians=None, #
conf_intervals=None, #
meanline=None, # 是否用线的形式表示均值,默认用点来表示;
showmeans=None, # 是否显示均值,默认不显示;
showcaps=None, # 是否显示箱线图顶端和末端的两条线,默认显示;
showbox=None, # 是否显示箱线图的箱体,默认显示;
showfliers=None, # 是否显示异常值,默认显示;
boxprops=None, # 设置箱体的属性,如边框色,填充色等;
labels=None, # 为箱线图添加标签,类似于图例的作用;
flierprops=None, # 设置异常值的属性,如异常点的形状,大小,填充色等;
medianprops=None, # 设置中位数的属性,如线的类型、粗细等;
meanprops=None, # 设置均值的属性,如点的大小、颜色等;
capprops=None, # 设置箱线图顶端和末端线条的属性,如颜色、粗细等;
whiskerprops=None, # 设置须的属性,如颜色、粗细、线的类型等;
manage_xticks=True, #
autorange=False, #
zorder=None, #
hold=None, #
data=None) #
1.1、x:指定要绘制箱线图的数据
示例:x=[80, 90, 75, 65, 85, 95, 100, 100, 80, 70, 90, 95, 85, 86, 92, 90, 95, 90, 85, 100]
1.1.1、代码如下(示例):
import matplotlib.pyplot as plt
x = [80, 90, 75, 65, 85, 95, 100, 100, 80, 70, 90, 95, 85, 86, 92, 90, 95, 90, 85, 100]
plt.boxplot(x)
plt.show()
1.1.2、输出结果如下:
1.2、notch:是否以凹口的形式展现箱线图
示例:x=[80, 90, 75, 65, 85, 95, 100, 100, 80, 70, 90, 95, 85, 86, 92, 90, 95, 90, 85, 100]
1.2.1、代码如下(示例):
import matplotlib.pyplot as plt
x = [80, 90, 75, 65, 85, 95, 100, 100, 80, 70, 90, 95, 85, 86, 92, 90, 95, 90, 85, 100]
plt.boxplot(x, notch=True)
plt.show()
1.2.2、输出结果如下:
1.3、sym:指定异常点的形状
示例:x=[80, 90, 75, 65, 85, 95, 100, 100, 80, 70, 90, 95, 85, 86, 92, 90, 95, 90, 85, 100]
1.3.1、代码如下(示例):
import matplotlib.pyplot as plt
x = [80, 90, 75, 65, 85, 95, 100, 100, 80, 70, 90, 95, 85, 86, 92, 90, 95, 90, 85, 100]
plt.boxplot(x, sym='*')
plt.show()
1.3.2、输出结果如下:
1.4、vert:是否需要将箱线图垂直摆放,True:垂直,False:水平;默认垂直摆放
示例:x=[80, 90, 75, 65, 85, 95, 100, 100, 80, 70, 90, 95, 85, 86, 92, 90, 95, 90, 85, 100]
1.4.1、代码如下(示例):
import matplotlib.pyplot as plt
x = [80, 90, 75, 65, 85, 95, 100, 100, 80, 70, 90, 95, 85, 86, 92, 90, 95, 90, 85, 100]
plt.boxplot(x, vert=False)
plt.show()
1.4.2、输出结果如下:
1.5、whis:指定上下须与上下四分位的距离,默认为1.5倍的四分位差
示例:x=[80, 90, 75, 65, 85, 95, 100, 100, 80, 70, 90, 95, 85, 86, 92, 90, 95, 90, 85, 100]
1.5.1、代码如下(默认情况示例):
import matplotlib.pyplot as plt
x = [80, 90, 75, 65, 85, 95, 100, 100, 80, 70, 90, 95, 85, 86, 92, 90, 95, 90, 85, 100]
plt.boxplot(x)
plt.show()
1.5.2、输出结果如下:
1.5.3、代码如下(指定whis=3时的示例):
import matplotlib.pyplot as plt
x = [80, 90, 75, 65, 85, 95, 100, 100, 80, 70, 90, 95, 85, 86, 92, 90, 95, 90, 85, 100]
plt.boxplot(x, whis=3)
plt.show()
1.5.4、输出结果如下:
1.6、positions:指定箱线图的位置,默认为[0,1,2…]
示例:x=[80, 90, 75, 65, 85, 95, 100, 100, 80, 70, 90, 95, 85, 86, 92, 90, 95, 90, 85, 100]
1.6.1、代码如下(默认情况示例):
import matplotlib.pyplot as plt
x = [80, 90, 75, 65, 85, 95, 100, 100, 80, 70, 90, 95, 85, 86, 92, 90, 95, 90, 85, 100]
plt.boxplot(x)
plt.show()
1.6.2、输出结果如下:
1.6.3、代码如下(positions=[4]时的示例):
import matplotlib.pyplot as plt
x = [80, 90, 75, 65, 85, 95, 100, 100, 80, 70, 90, 95, 85, 86, 92, 90, 95, 90, 85, 100]
plt.boxplot(x, positions=[4])
plt.show()
1.6.4、输出结果如下:
1.7、widths=None:指定箱线图的宽度
示例:x=[80, 90, 75, 65, 85, 95, 100, 100, 80, 70, 90, 95, 85, 86, 92, 90, 95, 90, 85, 100]
1.7.1、代码如下(widths=0.5时示例):
import matplotlib.pyplot as plt
x = [80, 90, 75, 65, 85, 95, 100, 100, 80, 70, 90, 95, 85, 86, 92, 90, 95, 90, 85, 100]
plt.boxplot(x, widths=0.5)
plt.show()
1.7.2、输出结果如下:
1.7.3、代码如下(widths=1时示例):
import matplotlib.pyplot as plt
x = [80, 90, 75, 65, 85, 95, 100, 100, 80, 70, 90, 95, 85, 86, 92, 90, 95, 90, 85, 100]
plt.boxplot(x, widths=1)
plt.show()
1.7.4、输出结果如下:
1.8、patch_artist:是否填充箱体的颜色,True:填充,False:不填充;默认False
示例:x=[80, 90, 75, 65, 85, 95, 100, 100, 80, 70, 90, 95, 85, 86, 92, 90, 95, 90, 85, 100]
1.8.1、代码如下(patch_artist=True时示例):
import matplotlib.pyplot as plt
x = [80, 90, 75, 65, 85, 95, 100, 100, 80, 70, 90, 95, 85, 86, 92, 90, 95, 90, 85, 100]
plt.boxplot(x, patch_artist=True)
plt.show()
1.8.2、输出结果如下:
1.8.1、代码如下(patch_artist=False时示例):
import matplotlib.pyplot as plt
x = [80, 90, 75, 65, 85, 95, 100, 100, 80, 70, 90, 95, 85, 86, 92, 90, 95, 90, 85, 100]
plt.boxplot(x, patch_artist=False)
plt.show()
1.8.2、输出结果如下:
1.9、showmeans:是否显示均值,默认不显示
示例:x=[80, 90, 75, 65, 85, 95, 100, 100, 80, 70, 90, 95, 85, 86, 92, 90, 95, 90, 85, 100]
1.9.1、代码如下(showmeans=True时示例):
import matplotlib.pyplot as plt
x = [80, 90, 75, 65, 85, 95, 100, 100, 80, 70, 90, 95, 85, 86, 92, 90, 95, 90, 85, 100]
plt.boxplot(x, showmeans=True)
plt.show()
1.9.2、输出结果如下:
1.9.3、代码如下(showmeans=False时示例):
import matplotlib.pyplot as plt
x = [80, 90, 75, 65, 85, 95, 100, 100, 80, 70, 90, 95, 85, 86, 92, 90, 95, 90, 85, 100]
plt.boxplot(x)
plt.show()
1.9.4、输出结果如下:
1.10、meanline:是否用线的形式表示均值,默认用点来表示
示例:x=[80, 90, 75, 65, 85, 95, 100, 100, 80, 70, 90, 95, 85, 86, 92, 90, 95, 90, 85, 100]
1.10.1、代码如下(meanline=True时示例):
import matplotlib.pyplot as plt
x = [80, 90, 75, 65, 85, 95, 100, 100, 80, 70, 90, 95, 85, 86, 92, 90, 95, 90, 85, 100]
plt.boxplot(x, showmeans=True, meanline=True)
plt.show()
1.10.2、输出结果如下:
1.10.3、代码如下(meanline=False时示例):
import matplotlib.pyplot as plt
x = [80, 90, 75, 65, 85, 95, 100, 100, 80, 70, 90, 95, 85, 86, 92, 90, 95, 90, 85, 100]
plt.boxplot(x, showmeans=True, meanline=False)
plt.show()
1.10.4、输出结果如下:
1.11、showcaps:是否显示箱线图顶端和末端的两条线,默认显示
示例:x=[80, 90, 75, 65, 85, 95, 100, 100, 80, 70, 90, 95, 85, 86, 92, 90, 95, 90, 85, 100]
1.11.1、代码如下(showcaps=True时示例):
import matplotlib.pyplot as plt
x = [80, 90, 75, 65, 85, 95, 100, 100, 80, 70, 90, 95, 85, 86, 92, 90, 95, 90, 85, 100]
plt.boxplot(x)
plt.show()
1.11.2、输出结果如下:
1.11.3、代码如下(showcaps=False时示例):
import matplotlib.pyplot as plt
x = [80, 90, 75, 65, 85, 95, 100, 100, 80, 70, 90, 95, 85, 86, 92, 90, 95, 90, 85, 100]
plt.boxplot(x, showcaps=False)
plt.show()
1.11.4、输出结果如下:
1.12、showbox:是否显示箱线图的箱体,默认显示
示例:x=[80, 90, 75, 65, 85, 95, 100, 100, 80, 70, 90, 95, 85, 86, 92, 90, 95, 90, 85, 100]
1.12.1、代码如下(showbox=False时示例):
import matplotlib.pyplot as plt
x = [80, 90, 75, 65, 85, 95, 100, 100, 80, 70, 90, 95, 85, 86, 92, 90, 95, 90, 85, 100]
plt.boxplot(x, showbox=False)
plt.show()
1.12.2、输出结果如下:
1.13、showfliers:是否显示异常值,默认显示
示例:x=[80, 90, 75, 65, 85, 95, 100, 100, 80, 70, 90, 95, 85, 86, 92, 90, 95, 90, 85, 100]
1.13.1、代码如下(showfliers=False时示例):
import matplotlib.pyplot as plt
x = [80, 90, 75, 65, 85, 95, 100, 100, 80, 70, 90, 95, 85, 86, 92, 90, 95, 90, 85, 100]
plt.boxplot(x, showfliers=False)
plt.show()
1.13.2、输出结果如下:
1.14、labels:为箱线图添加标签,类似于图例的作用
示例:x=[80, 90, 75, 65, 85, 95, 100, 100, 80, 70, 90, 95, 85, 86, 92, 90, 95, 90, 85, 100]
1.14.1、代码如下(示例):
import matplotlib.pyplot as plt
# 设置字体, 解决中文乱码问题
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
# 解决图像中的'-'负号的乱码问题
plt.rcParams['axes.unicode_minus'] = False
x = [80, 90, 75, 65, 85, 95, 100, 100, 80, 70, 90, 95, 85, 86, 92, 90, 95, 90, 85, 100]
plt.boxplot(x, labels=['标签'])
plt.show()
1.14.2、输出结果如下:
1.15、boxprops:设置箱体的属性,如边框色,填充色等
示例:x=[80, 90, 75, 65, 85, 95, 100, 100, 80, 70, 90, 95, 85, 86, 92, 90, 95, 90, 85, 100]
1.15.1-1、color 边框颜色
import matplotlib.pyplot as plt
# 设置字体, 解决中文乱码问题
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
# 解决图像中的'-'负号的乱码问题
plt.rcParams['axes.unicode_minus'] = False
x = [80, 90, 75, 65, 85, 95, 100, 100, 80, 70, 90, 95, 85, 86, 92, 90, 95, 90, 85, 100]
plt.boxplot(x, boxprops={'color': 'red'})
plt.show()
1.15.1-2、输出结果如下:
1.15.2-1、facecolor 箱体填充颜色(patch_artist必须为True)
import matplotlib.pyplot as plt
# 设置字体, 解决中文乱码问题
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
# 解决图像中的'-'负号的乱码问题
plt.rcParams['axes.unicode_minus'] = False
x = [80, 90, 75, 65, 85, 95, 100, 100, 80, 70, 90, 95, 85, 86, 92, 90, 95, 90, 85, 100]
plt.boxplot(x, patch_artist=True, boxprops={'color': 'orangered', 'facecolor': 'pink'})
plt.show()
1.15.2-2、输出结果如下:
1.16、filerprops:设置异常值的属性
示例:x=[80, 90, 75, 65, 85, 95, 100, 100, 80, 70, 90, 95, 85, 86, 92, 90, 95, 90, 85, 100]
1.16.1、代码如下(示例):
import matplotlib.pyplot as plt
# 设置字体, 解决中文乱码问题
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
# 解决图像中的'-'负号的乱码问题
plt.rcParams['axes.unicode_minus'] = False
x = [80, 90, 75, 65, 85, 95, 100, 100, 80, 70, 90, 95, 85, 86, 92, 90, 95, 90, 85, 100]
plt.boxplot(x, patch_artist=True, flierprops={'marker': 'o', 'markerfacecolor': 'pink'})
plt.show()
1.16.2、输出结果如下:
1.17、medianprops:设置中位数的属性,如线的类型、粗细等
示例:x=[80, 90, 75, 65, 85, 95, 100, 100, 80, 70, 90, 95, 85, 86, 92, 90, 95, 90, 85, 100]
1.17.1、代码如下(示例):
import matplotlib.pyplot as plt
# 设置字体, 解决中文乱码问题
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
# 解决图像中的'-'负号的乱码问题
plt.rcParams['axes.unicode_minus'] = False
x = [80, 90, 75, 65, 85, 95, 100, 100, 80, 70, 90, 95, 85, 86, 92, 90, 95, 90, 85, 100]
plt.boxplot(x, medianprops={'linestyle': '--', 'linewidth': 3})
plt.show()
1.17.2、输出结果如下:
1.18、meanprops:设置均值的属性,如点的大小、颜色等(注:showmeans必须设置为True,不然均值不显示)
示例:x=[80, 90, 75, 65, 85, 95, 100, 100, 80, 70, 90, 95, 85, 86, 92, 90, 95, 90, 85, 100]
1.18.1、代码如下(示例):
import matplotlib.pyplot as plt
# 设置字体, 解决中文乱码问题
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
# 解决图像中的'-'负号的乱码问题
plt.rcParams['axes.unicode_minus'] = False
x = [80, 90, 75, 65, 85, 95, 100, 100, 80, 70, 90, 95, 85, 86, 92, 90, 95, 90, 85, 100]
plt.boxplot(x, meanprops={'marker': 'D', 'markerfacecolor': 'white'})
plt.show()
1.18.2、输出结果如下:
1.18.3、代码如下(示例):
import matplotlib.pyplot as plt
# 设置字体, 解决中文乱码问题
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
# 解决图像中的'-'负号的乱码问题
plt.rcParams['axes.unicode_minus'] = False
x = [80, 90, 75, 65, 85, 95, 100, 100, 80, 70, 90, 95, 85, 86, 92, 90, 95, 90, 85, 100]
plt.boxplot(x, showmeans=True, meanprops={'marker': 'D', 'markerfacecolor': 'white'})
plt.show()
1.18.4、输出结果如下:
1.18.5、代码如下(示例):
import matplotlib.pyplot as plt
# 设置字体, 解决中文乱码问题
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
# 解决图像中的'-'负号的乱码问题
plt.rcParams['axes.unicode_minus'] = False
x = [80, 90, 75, 65, 85, 95, 100, 100, 80, 70, 90, 95, 85, 86, 92, 90, 95, 90, 85, 100]
plt.boxplot(x, showmeans=True, meanline=True, meanprops={'marker': 'D', 'markerfacecolor': 'white'})
plt.show()
1.18.6、输出结果如下:
1.19、capprops:设置箱线图顶端和末端线条的属性,如颜色、粗细等
示例:x=[80, 90, 75, 65, 85, 95, 100, 100, 80, 70, 90, 95, 85, 86, 92, 90, 95, 90, 85, 100]
1.19.1、代码如下(示例):
import matplotlib.pyplot as plt
# 设置字体, 解决中文乱码问题
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
# 解决图像中的'-'负号的乱码问题
plt.rcParams['axes.unicode_minus'] = False
x = [80, 90, 75, 65, 85, 95, 100, 100, 80, 70, 90, 95, 85, 86, 92, 90, 95, 90, 85, 100]
plt.boxplot(x, capprops={'linestyle': '--', 'linewidth': 3, 'color': 'red'})
plt.show()
1.19.2、输出结果如下:
1.20、whiskerprops:设置须的属性,如颜色、粗细、线的类型等
示例:x=[80, 90, 75, 65, 85, 95, 100, 100, 80, 70, 90, 95, 85, 86, 92, 90, 95, 90, 85, 100]
1.20.1、代码如下(示例):
import matplotlib.pyplot as plt
# 设置字体, 解决中文乱码问题
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
# 解决图像中的'-'负号的乱码问题
plt.rcParams['axes.unicode_minus'] = False
x = [80, 90, 75, 65, 85, 95, 100, 100, 80, 70, 90, 95, 85, 86, 92, 90, 95, 90, 85, 100]
plt.boxplot(x, whiskerprops={'linestyle': '--', 'linewidth': 3, 'color': 'red'})
plt.show()
1.20.2、输出结果如下:
2. 在箱线图上叠加散点图时图层参数设置(zorder)
使用 “zorder=2”这样的确定叠加的图层的先后次序,数字越大,越后。因为现在是在箱线图上叠加散点图,所以需要先画箱线图,后画散点图,即画箱线图时zorder=1,画散点图时zorder=2
3. 回答往期文章《Python Matplotlib数据可视化绘图之(二)————箱线图》中的总结中所提的问题,文章网址链接为:https://blog.csdn.net/Mr_Dragon66/article/details/127814202?spm=1001.2014.3001.5501
3.1、为什么我不直接在ax.boxplot()函数中直接用labels这个参数生成legend,反而要利用ax.scatter()函数中的label参数生成legend?
3.1.1、首先我演示一下在ax.boxplot()函数中直接用labels这个参数,看是否能够生成legend
3.1.1-1、代码如下(数据来自往期文章):
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)
labels = [['语文', '语文', '语文'], ['数学', '数学', '数学'], ['英语', '英语', '英语']]
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, labels=labels[i])
# 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, 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', labels=legend_labels)
################################################################################################################
################################################################################################################
plt.xticks(weight='bold')
plt.yticks(weight='bold')
fig.tight_layout()
plt.show()
3.1.1-2、输出结果如下:
由输出结果可知,并没有像我们预期的那样生成正确的legend。原因是因为我们在画箱线图时,并不是按照Group来画的,即不是按照[甲班语文,甲班数学,甲班英语,乙班语文,乙班数学,乙班英语,丙班语文,丙班数学,丙班英语]的顺序,而是按照[甲班语文,乙班语文,丙班语文,甲班数学,乙班数学,丙班数学,甲班英语,乙班英语,丙班英语]的顺序来画的。
如果我们按照Group来画的,即按照[甲班语文,甲班数学,甲班英语,乙班语文,乙班数学,乙班英语,丙班语文,丙班数学,丙班英语]的顺序来画,请看3.1.1-3和3.1.1-4的内容:
3.1.1-3、代码如下(数据来自往期文章):
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_dataA_CME = [ClassA_C, ClassA_M, ClassA_E]
boxplot_dataB_CME = [ClassB_C, ClassB_M, ClassB_E]
boxplot_dataC_CME = [ClassC_C, ClassC_M, ClassC_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)
labels = ['语文', '数学', '英语']
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)]
x_list_box_new = []
for i in range(len(group_dataA)):
for j in range(len(group_dataA)):
x_list_box_new.append(x_list_box[i][j])
x_list_box_new = sorted(x_list_box_new)
x_list_box_final = []
for i in range(len(group_dataA)):
x_list_box_final.append(x_list_box_new[3 * i:3 * (i + 1)])
bplot1 = plt.boxplot(boxplot_dataA_CME, positions=x_list_box_final[0], widths=box_width,
patch_artist=True, showfliers=False, zorder=1, labels=labels)
for patch, color in zip(bplot1['boxes'], color_list):
patch.set_edgecolor(color)
patch.set_facecolor('None')
bplot2 = plt.boxplot(boxplot_dataB_CME, positions=x_list_box_final[1], widths=box_width,
patch_artist=True, showfliers=False, zorder=1, labels=labels)
for patch, color in zip(bplot2['boxes'], color_list):
patch.set_edgecolor(color)
patch.set_facecolor('None')
bplot3 = plt.boxplot(boxplot_dataC_CME, positions=x_list_box_final[2], widths=box_width,
patch_artist=True, showfliers=False, zorder=1, labels=labels)
for patch, color in zip(bplot3['boxes'], color_list):
patch.set_edgecolor(color)
patch.set_facecolor('None')
########################################################################
########################################################################
boxplot_data = [boxplot_dataABC_C, boxplot_dataABC_M, boxplot_dataABC_E]
for i in range(len(boxplot_data)):
# 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)
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)
ax.scatter(spotx, boxplot_data[i], c=color_list[i], s=30, 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(handles=bplot1['boxes'], 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', labels=legend_labels)
################################################################################################################
################################################################################################################
plt.xticks(weight='bold')
plt.yticks(weight='bold')
fig.tight_layout()
plt.show()
3.1.1-4、输出结果如下:
由输出结果可知,这样操作才能输出我们想要的效果,但是这样生成图例的方法并不适用于数据集比较多的情况,也不适用于自动读取数据集并批量绘制箱线图的操作,所以我们在往期中没有采取这种生成图例的方式。
3.2、还有什么方法能够生成箱线图的图例?
详见3.1.1-3和3.1.1-4的内容,采取面向对象画图例的方式,bp[‘boxes’]是为了获取箱线图的箱体这个对象,它的属性也会被获取到,比如颜色和形状。
3.3、箱线图的图例生成方法和柱状图、折线图、饼图、直方图、散点图等图的图例生成方法有什么不同之处或特别之处?
柱状图采用plt.bar(label=‘字符串’);plt.legend()来生成图例;
折线图采用plt.plot(label=‘字符串’);plt.legend()来生成图例;
直方图采用plt.hist(label=‘字符串’);plt.legend()来生成图例;
散点图采用plt.scatter(label=‘字符串’);plt.legend()来生成图例;
饼图采用的方式如下所示:
3.3.1、方式一:既生成图例又在扇形旁显示标签
3.3.1-1、代码如下:
# 扇形图例标识
import matplotlib.pyplot as plt
# 这两行代码解决 plt 中文显示的问题
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# 扇形图例标识
labels = ['0-10岁', '10-20岁', '20-30岁', '30-40岁', '40-100岁']
# 扇形大小
sizes = [40, 30, 20, 5, 5]
# 第二块扇形偏移
explode = [0, 0.1, 0, 0, 0]
# 创建图形
fig, ax = plt.subplots()
# 开始画饼图
ax.pie(sizes, labels=labels, explode=explode, autopct='%1.1f%%', shadow=True)
# 确保画的饼是圆的
ax.axis('equal')
ax.set_title('各年龄段长蛀牙情况')
# 设置图例
ax.legend()
plt.show()
3.3.1-2、输出结果如下:
3.3.2、方式二:只生成图例,且不在扇形旁显示标签
3.3.2-1、代码如下:
# 扇形图例标识
import matplotlib.pyplot as plt
# 这两行代码解决 plt 中文显示的问题
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# 扇形图例标识
labels = ['0-10岁', '10-20岁', '20-30岁', '30-40岁', '40-100岁']
# 扇形大小
sizes = [40, 30, 20, 5, 5]
# 第二块扇形偏移
explode = [0, 0.1, 0, 0, 0]
# 创建图形
fig, ax = plt.subplots()
# 开始画饼图
ax.pie(sizes, explode=explode, autopct='%1.1f%%', shadow=True)
# 确保画的饼是圆的
ax.axis('equal')
ax.set_title('各年龄段长蛀牙情况')
# 设置图例
ax.legend(labels=labels)
plt.show()
3.3.2-2、输出结果如下:
3.3.3、方式三:只在扇形旁显示标签,且不生成图例
3.3.3-1、代码如下:
# 扇形图例标识
import matplotlib.pyplot as plt
# 这两行代码解决 plt 中文显示的问题
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# 扇形图例标识
labels = ['0-10岁', '10-20岁', '20-30岁', '30-40岁', '40-100岁']
# 扇形大小
sizes = [40, 30, 20, 5, 5]
# 第二块扇形偏移
explode = [0, 0.1, 0, 0, 0]
# 创建图形
fig, ax = plt.subplots()
# 开始画饼图
ax.pie(sizes, labels=labels, explode=explode, autopct='%1.1f%%', shadow=True)
# 确保画的饼是圆的
ax.axis('equal')
ax.set_title('各年龄段长蛀牙情况')
# 设置图例
# ax.legend()
plt.show()
3.3.3-2、输出结果如下:
3.3.4、方式四:只在扇形旁显示标签,且不生成图例,如果不想把扇形做分离,可以去掉explode参数
3.3.4-1、代码如下:
# 扇形图例标识
import matplotlib.pyplot as plt
# 这两行代码解决 plt 中文显示的问题
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# 扇形图例标识
labels = ['0-10岁', '10-20岁', '20-30岁', '30-40岁', '40-100岁']
# 扇形大小
sizes = [40, 30, 20, 5, 5]
# 第二块扇形偏移
explode = [0, 0.1, 0, 0, 0]
# 创建图形
fig, ax = plt.subplots()
# 开始画饼图
ax.pie(sizes, labels=labels, autopct='%1.1f%%', shadow=True)
# 确保画的饼是圆的
ax.axis('equal')
ax.set_title('各年龄段长蛀牙情况')
# 设置图例
# ax.legend()
plt.show()
3.3.4-2、输出结果如下:
二、多种颜色的普通分组箱线图和散点图的叠加图
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为给图片命的名字
三、总结
以上就是今天要讲的内容,本文详细介绍了各种箱线图的绘制过程和方法,并用实例给大家演示了具体的实现代码和实现逻辑,并且在文中也详细回答了往期《Python Matplotlib数据可视化绘图之(二)————箱线图》(文章链接为:https://blog.csdn.net/Mr_Dragon66/article/details/127814202?spm=1001.2014.3001.5501)这篇文章中最后总结中所提的问题,希望对大家学习画箱线图有帮助。