Python绘图:箱线图的理解与绘制

Python绘图:箱线图的理解与绘制

一、箱线图简介

如下图所示,箱线图(箱形图、盒须图)是一种基于5个统计量(上边界、上四分位数、中位数、下四分位数以及下边界)显示数据分布的标准化方法,其可以用来检测数据的异常值和数据分布的形状,以及数据集的离散程度。图中矩形框显示数据集的上下四分位数,而矩形框中延伸出的线段(触须)则用于显示其余数据的分布位置,剩下超过上下四分位间距的数据点则被视为“异常值”。

箱线图主要的组成元素及其具体含义如下所示:

下四分位数Q1:将所有数据按照从小到大的顺序排在第25%的数;上四分位数Q3:将所有数据按照从小到大的顺序排在第75%的数;四分位间距(IQR, Interquartile Range):统计学中的一种数学表示方法(也称为四分差),为上四分位数与下四分位之间的距离,可表示为Δ=Q3−Q1Δ=𝑄3−𝑄1。上边界:除异常点以外数据中的最大值,可表示为Q3+1.5Δ𝑄3+1.5Δ;下边界:除异常点以外数据中的最小值,可表示为Q1−1.5Δ𝑄1−1.5Δ;异常值:小于下边界与大于上边界的值。

二、箱线图的绘制

本文给出基于matplotlib与seaborn库的两种箱线图绘制方法。

2.1 基于matplotlib库的箱线图绘制

matplotlib中绘制箱线图的函数为boxplot(),其函数原型如下所示:

matplotlib.pyplot.boxplot(x, notch=None, sym=None, vert=None, whis=None, positions=None, 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_ticks=True, autorange=False, zorder=None, capwidths=None, *, data=None)

(1)函数主要参数及功能

常用的参数及功能如下表所示,为了方便理解各个参数的含义,本文将其划分为三个不同类别:常规参数、显示控制参数以及细节属性参数。

参数功能参数功能常规参数x指定要绘制箱形图的数据notch是否绘制带缺口的箱形图patch_artist是否填充箱体的颜色vert是否将箱线图垂直摆放widths指定箱线图的宽度sym指定异常点的形状whis指定上下边界与上下四分位数的距离labels为箱线图添加标签capwidths设置须线帽长度position指定箱线图的位置显示控制参数showmeans是否显示均值点meanline是否显示均值线showbox是否显示箱形图的箱体showcaps是否显示须线帽showfliers是否显示异常值细节属性参数medianprops设置中位线属性meanprops设置均值点属性boxprops设置箱体属性capprops设置须帽属性whiskerprops设置须线属性flierprops设置异常点属性

注意💥:对于细节属性参数需要输入字典格式的数据,其设置方法可参考📖 python-matplotlib | 箱线图及解读 - 知乎

(2)函数返回值

boxplot()函数是以字典格式返回箱线图的每个组件对象,每个键的键值为matplotlib.lines.Line2D类对象的列表,具体包括:

boxes:箱体的主体显示四分位数;medians:每个箱体的中位数水平线;whiskers:每个箱体的须线;caps:须线末端的直线,即须线帽;fliers:异常值;means:均值点或直线。

注意💥:如果不启用箱线图的相应元素,相应键值则返回空列表。

(3)示例

更为详细的内容可参考matplotlib官方手册📚:matplotlib.pyplot.boxplot — Matplotlib 3.7.2 documentation。这里选取matplotlib官网上一个具有代表性的箱线图示例作为演示对象(参考🎨:Box plots with custom fill colors — Matplotlib 3.7.2 documentation)。在官网示例的基础上,本文添加了相关参数的使用方法并对代码进行注释,代码如下所示:

import matplotlib.pyplot as plt

import numpy as np

#! 解决不显示的问题:中文设置为宋体格式

plt.rcParams['font.family'] = ["Times New Roman", 'SimSun']

# 生成一个包含三个随机数的数组,每个随机数包含100个数据,且他们的标准差分别为1,2,3

all_data = [np.random.normal(0, std, size=100) for std in range(1,4)]

labels = ['$x_1$', '$x_2$', '$x_3$']

fig, (ax1, ax2) = plt.subplots(nrows=1, ncols=2, figsize=(9, 4))

# 绘制矩形箱线图

bplot_rect = ax1.boxplot(

x=all_data, # 需要绘制的数据

vert=True, # 垂直排列箱线图

widths=0.3, # 箱形宽度

labels=labels, # 箱形图的标签

patch_artist=True, # 是否为箱子填充颜色,默认为False

medianprops={ # 设置中位线属性

'linestyle': '-', 'color': 'r', 'linewidth': 1.5

},

# showmeans=True, # 是否显示均值点,默认为False

# meanline=True, # 是否显示均值线,默认为False

# meanprops={ # 设置均值点属性

# 'marker': 'o', 'markersize': 7.5, 'markeredgewidth': 0.75, 'markerfacecolor': '#b7e1a1', 'markeredgecolor': 'r', 'color': 'k', 'linewidth': 1.5

# },

showfliers=True, # 是否显示异常值,默认为True

flierprops={ # 设置异常点属性

'marker': '^', 'markersize': 6.75, 'markeredgewidth': 0.75, 'markerfacecolor': '#ee5500', 'markeredgecolor': 'k'

},

whiskerprops={ # 设置须的线条属性

'linestyle': '--', 'linewidth': 1.2, 'color': '#480656'

},

capprops={

'linestyle': '-', 'linewidth': 1.5, 'color': '#480656'

}

)

title_rect = ax1.set_title("矩形箱形图")

# 绘制带缺口象形图

bplot_notch = ax2.boxplot(

x=all_data, # 需要绘制的数据

notch=True, # 是否带有缺口,默认False

# vert=True, # 垂直排列箱线图,默认为True

widths=0.3, # 箱形宽度

labels=labels, # 箱形图的标签

patch_artist=True, # 是否为箱子填充颜色,默认为False

medianprops={ # 设置中位线属性

'linestyle': '-', 'color': 'r', 'linewidth': 1.5

},

# showmeans=True, # 是否显示均值点,默认为False

# meanline=True, # 是否显示均值线,默认为False

# meanprops={ # 设置均值点属性

# 'marker': 'o', 'markersize': 7.5, 'markeredgewidth': 0.75, 'markerfacecolor': '#b7e1a1', 'markeredgecolor': 'r', 'color': 'k', 'linewidth': 1.5

# },

showfliers=True, # 是否显示异常值,默认为True

flierprops={ # 设置异常点属性

'marker': '^', 'markersize': 6.75, 'markeredgewidth': 0.75, 'markerfacecolor': '#ee5500', 'markeredgecolor': 'k'

},

whiskerprops={ # 设置须的线条属性

'linestyle': '--', 'linewidth': 1.2, 'color': '#480656'

},

capprops={

'linestyle': '-', 'linewidth': 1.5, 'color': '#480656'

},

)

title_notch = ax2.set_title("带有缺口的箱形图")

# 为箱形图填充颜色

colors = ['pink', 'lightblue', 'lightgreen']

for bplot in (bplot_rect, bplot_notch):

for patch, color in zip(bplot['boxes'], colors):

patch.set_facecolor(color)

# 添加水平网格线并设置轴标签

for ax in [ax1, ax2]:

ax.yaxis.grid(True)

ax.set_xlabel("样本")

ax.set_ylabel("观测值")

代码执行结果如下图所示

后续替换中文为宋体的图片

2.2 基于seaborn库的箱线图绘制

Seaborn是基于matplotlib的python数据可视化库。它提供了高层级的接口用于画出统计图。它与pandas库数据接口非常相近,可以直接使用pandas的数据结构。相比较于matplotlib的箱线图绘制,searborn绘制的更加美观。seaborn中绘制箱线图的函数为boxplot(),其函数原型如下所示:

seaborn.boxplot(data=None, *, x=None, y=None, hue=None, hue_order=None, orient=None, color=None, palette=None, saturation=0.75, width=0.8, dodge=True, fliersize=5, linewidth=None, whis=1.5, ax=None, **kwargs)

注意💥: (1)虽然seaborn的boxplot()能以array、list以及DataFrame。但是其更适合于对DataFrame格式的数据进行箱线图绘制。因此,在绘制箱线图之前,建议将数据转换为DataFrame格式。本文的介绍以DataFrame格式的数据为例。 (2)由于seaborn是基于matplotlib的,因此我们可以直接调用matplotlib.boxplot的参数对箱线图进行设置。

(1)函数主要参数功能及其返回值

常用的参数及功能如下表所示:

参数功能参数功能x、y数据或向量的变量名data用于绘图的数据集width箱体的宽度linewidth构成图元素的灰线宽度orient绘图方向,v(垂直)、h(水平)color所有元素的颜色fliersize异常值标记的大小notch是否绘制带缺口的箱形图whis控制在超过高低四分位时IQR的比例ax使用的Axes轴对象,默认使用当前轴palette调色板名称saturation控制用于绘制颜色的原始饱和度比例hue指定色调的分组dodge使用色调嵌套时,元素是否沿分类轴移动kwargs可调用matplotlib.axes.Axes.boxplot参数,比如medianprops、boxprops等

seaborn.boxplot()函数的返回值为当前绘制图像数matplotlib.Axes据格式的句柄对象。

更为详细的内容可参考seaborn官方手册📚:seaborn.boxplot — seaborn 0.12.2 documentation。

(2)示例

下面通过若干个绘图示例来理解seaborn.boxplot参数的功能:

import seaborn as sns

import matplotlib.pyplot as plt

#! 解决不显示的问题:中文设置为宋体格式

plt.rcParams['font.family'] = ["Times New Roman", 'SimSun']

df = sns.load_dataset("titanic")

fig, axs = plt.subplots(nrows=2, ncols=3, figsize=(14,11))

sns.boxplot(ax=axs[0,0], data=df, x ="age", y="class")

axs[0,0].set_title("图1:舱位等级的年龄分布", fontsize=14)

axs[0,0].xaxis.grid(True)

# sns.boxplot(ax=axs[0,1], data=df, x="age", y="class", hue="alive")

sns.boxplot(ax=axs[0,1], data=df, x="class", y="age", hue="alive") # 对掉x、y参数可以切换水平、垂直绘图

axs[0,1].set_ylabel('')

axs[0,1].set_title("图2:基于存活与否分组的舱位等级年龄分布", fontsize=14)

axs[0,1].yaxis.grid(True)

sns.boxplot(ax=axs[0,2], data=df[["age", "fare"]], orient="h")

axs[0,2].set_title("图3:绘制多列数值型数组的箱线图", fontsize=14)

axs[0,2].xaxis.grid(True)

sns.boxplot(ax=axs[1,0], data=df, x="fare", y="deck", hue="deck", dodge=False)

axs[1,0].set_title("图4:hue参数与dodge参数的作用", fontsize=14)

axs[1,0].xaxis.grid(True)

sns.boxplot(ax=axs[1,1], data=df, x="fare", y="deck", order=["G", "F", "E", "D", "C", "B", "A"], hue="deck", dodge=False)

axs[1,1].set_title("图5:改变图4中y轴的排列次序", fontsize=14)

axs[1,1].xaxis.grid(True)

sns.boxplot(

ax=axs[1,2], data=df, x="age", y="class",

notch=True, showcaps=False,

flierprops={"marker": "^"},

# boxprops={"facecolor": (.4, .6, .8, .5)},

medianprops={"color": "r"}

)

axs[1,2].set_title("图6:使用matplotlib.boxplot参数进行配置", fontsize=14)

axs[1,2].xaxis.grid(True)

PYTHON 折叠 复制 全屏

防采坑💣:在使用df = sns.load_dataset("titanic")导入seaborn自带的数据时,由于网络原因会出现加载不了的问题。对此,可参考博文📖 解决seaborn数据无法导入的问题_无法解析导入

相关阅读:

1、https://blog.wanwuguiyi.com/python-plt-plot/

2、https://blog.wanwuguiyi.com/python-real-esrgan/

3、https://blog.wanwuguiyi.com/python-opencv-lib/

4、https://blog.wanwuguiyi.com/python-matplotlib-pyplot-learning/

相关推荐

什么是URL编码?为什么需要进行URL编码?
365三式投注

什么是URL编码?为什么需要进行URL编码?

📅 07-12 🔥 271
巴西永久保留“世界杯”,但却被偷了
365bet盘口开户

巴西永久保留“世界杯”,但却被偷了

📅 07-21 🔥 601
3、梦幻西游手游超级神鸡玩法
365bet盘口开户

3、梦幻西游手游超级神鸡玩法

📅 06-28 🔥 654
二建app哪个免费又好?
365bet盘口开户

二建app哪个免费又好?

📅 07-18 🔥 909
Win11系统如何调整硬盘顺序?如何更改硬盘优先级?
歸來的異世界王者
365 双式投注

歸來的異世界王者

📅 07-05 🔥 589