首页编程开发Matplotlib【数据可视化(Matplo...

【数据可视化(Matplotlib篇)】38.绘制箱型图boxplot()

本系列文章配套代码获取有以下两种途径:

  • 通过百度网盘获取:
链接:https://pan.baidu.com/s/1jG-rGG4QMuZu0t0kEEl7SA?pwd=mnsj 提取码:mnsj
  • 前往GitHub获取
https://github.com/returu/Data_Visualization





箱型图(Box Plot)能直观展示数据的离散程度、集中趋势和极端值一目了然。它的每一个组成部分都在传递数据的关键信息:
  • 箱体:代表数据的 “核心分布区间”,上沿对应上四分位数(Q3),下沿对应下四分位数(Q1),箱体高度为 “四分位距(IQR = Q3 – Q1)”,包含了 50% 的核心数据;
  • 中位线:箱体内的横线,代表数据的中位数(Q2),反映数据的集中趋势;
  • 晶须(Whiskers):从箱体延伸出的线段,默认覆盖 1.5×IQR 范围内的所有数据点,超出这个范围的点会被标记为 “异常值”;
  • 异常值:用圆点或其他符号标记,代表偏离正常分布的极端数据。
01

函数语法


Matplotlib boxplot()函数专门用于绘制箱型图,其函数语法如下:
plt.boxplot(x, *, notch=None, sym=None, vert=None            orientation='vertical', 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            tick_labels=None, flierprops=None            medianprops=None, meanprops=None, capprops=None            whiskerprops=None, manage_ticks=True            autorange=False, zorder=None, capwidths=None            label=None, data=None)
其中:
  • 核心数据参数
  • x:输入的数据,可以是数组、列表或列表的列表。如果是多组数据,通常以列表嵌套的形式传入(如[data1, data2, data3])。
  • data:可选参数,用于指定数据来源(当x是字符串时,从data中查找对应的数据)。
  • 箱体结构与样式参数
  • notch:布尔值,默认None。如果为True,箱体将带有凹口,凹口表示中位数的置信区间(默认 95% 置信区间);False则为普通箱体。

  • sym:字符串,用于指定异常值的标记样式,默认None(使用默认样式‘b+’)。例如‘o’表示圆形,‘D’表示菱形。

  • vert:布尔值,默认None(等效于True)。控制箱型图方向,True为垂直箱型图,False为水平箱型图(与orientation参数功能类似)。

  • orientation:字符串,默认‘vertical’。指定箱型图方向,‘vertical’为垂直,‘horizontal’为水平(与vert参数作用相同,优先级更高)。
  • whis:浮点数或长度为 2 的序列,默认1.5。指定 “须” 的长度,默认是1.5*IQR(四分位距)。若为序列(如[5, 95]),则表示须延伸至指定的百分位数。

  • positions:数组,默认None。指定每个箱体的位置(x 轴坐标),默认按[1, 2, 3,…]排列。
  • widths:浮点数或数组,默认0.5。指定箱体的宽度,若为数组则为每个箱体单独设置宽度。
  • patch_artist:布尔值,默认None。如果为True,箱体将使用boxprops中的facecolor填充颜色;False则为空心箱体(仅显示边框)。

  • capwidths:浮点数或数组,默认None。指定帽子的宽度(相对于箱体宽度的比例)。

  • 统计计算参数

  • bootstrap:整数,默认None。当notch=True时,用于计算中位数置信区间的 bootstrap 抽样次数(如1000表示抽样 1000 次)。

  • usermedians:数组,默认None。用于指定自定义的中位数,而非自动计算。

  • conf_intervals:数组,默认None。当notch=True时,用于指定自定义的中位数置信区间,而非自动计算。

  • meanline:布尔值,默认None。如果为True,且showmeans=True,则用一条线表示均值(而非标记点)。

  • showmeans:布尔值,默认None。是否显示均值,默认不显示。

  • showcaps:布尔值,默认None(等效于True)。是否显示箱型图 “须” 两端的帽子(横线)。

  • showbox:布尔值,默认None(等效于True)。是否显示箱体。

  • showfliers:布尔值,默认None(等效于True)。是否显示异常值,False则隐藏异常值。

  • 样式定制参数(*props)

  • boxprops:箱体的样式,例如{‘color’: ‘blue’, ‘linewidth’: 2}

  • flierprops:异常值的样式,例如{‘marker’: ‘o’, ‘color’: ‘red’}

  • medianprops:中位线的样式,例如{‘color’: ‘green’, ‘linestyle’: ‘–‘}

  • meanprops:均值的样式(配合showmeans=True使用),例如{‘marker’: ‘^’, ‘markersize’: 6}

  • capprops:“须” 两端帽子的样式,例如{‘linewidth’: 1.5}

  • whiskerprops:“须” 的样式,例如{‘color’: ‘gray’, ‘linestyle’: ‘-‘}

  • 标签与刻度参数

  • tick_labels(旧版本为labels):列表,默认None。用于指定 x 轴(垂直箱型图)或 y 轴(水平箱型图)的刻度标签,替代默认的1,2,3…。

  • label(旧版本无该参数):字符串,默认None。为箱型图设置标签(用于图例)。

  • manage_ticks:布尔值,默认True。是否自动管理刻度和标签,False则需要手动设置。

通过调整这些参数,可以灵活控制箱型图的视觉效果。

# 生成多组数据
np.random.seed(1)
group1 = np.random.normal(100, 20, 200)
group2 = np.random.normal(120, 25, 200)
group3 = np.random.normal(90, 15, 200)
# 将三组数据整理为列表,作为箱型图的输入数据
data = [group1, group2, group3]
# 定义每组数据对应的标签,用于图表的x轴刻度显示
labels = ['组1''组2''组3']

plt.figure(figsize=(10, 6))
bp = plt.boxplot(
                data,                 # 输入的多组数据
                labels=labels,        # 设置x轴刻度标签为自定义标签
                meanline=True,        # 用线而不是点表示均值
                notch=True,           # 创建带缺口的箱型图(缺口表示中位数的置信区间)
                patch_artist=True,    # 允许对箱体进行填充(否则箱体为空心)
                sym='D',              # 异常值标记为菱形(D表示diamond)
                widths=[0.3,0.5,0.8], # 分别设置三个箱体的宽度(组1:0.3, 组2:0.5, 组3:0.8)
                showmeans=True        # 显示均值
                )

plt.title('多组数据箱型图')
plt.ylabel('测量值')
plt.grid(True, alpha=0.3)
plt.show()

可视化结果如下图所示:

  • 函数返回值解析:

boxplot()函数的返回值是一个字典(通常用变量如bp接收),包含箱型图各组成部分的图形对象(如线条、多边形、标记点等),键为组件名称,值为对应组件的对象列表(多组数据时,每个元素对应一组数据的组件)。

# 生成示例数据
data = np.random.normal(100, 20, 100)

# 绘制箱型图并获取返回值
bp = plt.boxplot(data)
plt.close()  # 关闭图形,避免显示

print("返回值类型:"type(bp))
print("返回值:", bp)

# 输出:
# 返回值类型: <class 'dict'>
# 返回值: 
# {
# 'whiskers': [<matplotlib.lines.Line2D object at 0x000001E39B685940>, <matplotlib.lines.Line2D object at 0x000001E39B685BE0>], 
# 'caps': [<matplotlib.lines.Line2D object at 0x000001E39B685E80>, <matplotlib.lines.Line2D object at 0x000001E39B102160>], 
# 'boxes': [<matplotlib.lines.Line2D object at 0x000001E39B6857C0>], 
# 'medians': [<matplotlib.lines.Line2D object at 0x000001E39B102400>], 
# 'fliers': [<matplotlib.lines.Line2D object at 0x000001E39B1026A0>], 
# 'means': []
# }

其中,各键及其含义如下所示:

键名
描述
数据类型
备注
‘boxes’
箱体部分(Q1到Q3的范围)
List[Line2D] 或 List[Patch]
若 patch_artist=True 则为 Patch
‘medians’
中位线(Q2)
List[Line2D]
每个箱型图一条线
‘whiskers’
须线(从箱体到边缘的线)
List[Line2D]
每组数据对应两条(上下须线)
‘caps’
须线末端的横线(”帽线”)
List[Line2D]
每组数据对应两条
‘fliers’
异常值点
List[Line2D]
若无异常值则为空列表
‘means’
均值线(需 showmeans=True
List[Line2D]
可选,需配合 showmeans=True 启用

通过上述返回对象,可在绘图后进一步精细化修改样式,例如循环遍历bp[‘boxes’]为每个箱体设置不同填充色,或调整bp[‘fliers’]的异常值标记样式。

# 创建多组数据
np.random.seed(12)
data = [np.random.normal(100, 20, 100),
        np.random.normal(120, 15, 100)]

plt.figure(figsize=(10, 6))
bp = plt.boxplot(data, patch_artist=True)

# 使用返回值自定义样式
# 1. 设置箱子颜色
colors = ['lightblue''lightgreen']
for i, box in enumerate(bp['boxes']):
    box.set(facecolor=colors[i], alpha=0.7, linewidth=2)

# 2. 设置中位数线样式
colors = ['blue''green']
for i, median in enumerate(bp['medians']):
    median.set(color=colors[i], linewidth=3, linestyle='-')

# 3. 设置须线样式
colors = ['blue''green','blue''green']
for i,whisker in enumerate(bp['whiskers']):
    whisker.set(color=colors[i], linewidth=1.5, linestyle='--')

# 4. 设置端点帽样式
colors = ['blue''green','blue''green']
for i,capin enumerate(bp['caps']):
    cap.set(color=colors[i], linewidth=2)

# 5. 设置异常值样式
colors = ['blue''green']
markers = ['^''o']
for i,flier in enumerate(bp['fliers']):
    flier.set(marker=markers[i], markerfacecolor=colors[i], markersize=10)

plt.title('使用返回值自定义样式的箱型图')
plt.ylabel('数值')
plt.xticks([1, 2], ['组A''组B'])
plt.grid(True, alpha=0.3)
plt.show()

可视化结果如下图所示:


02

使用示例


  • 示例1:自定义样式与颜色

boxplot()函数中,boxprops、flierprops、medianprops、meanprops、capprops、whiskerprops参数是用于定制箱型图各组成部分样式的核心参数,均为字典类型,通过键值对设置线条 / 标记的颜色、线宽、样式等属性。具体含义和常用配置如下:

  • boxprops:控制箱体(箱型图的主体矩形)的样式。常用键包括,color(边框颜色)、linewidth(线宽)、linestyle(线条样式,如‘-‘实线、‘–‘虚线);
  • flierprops:控制异常值(箱体外部的离散点)的样式。常用包括,marker(标记形状,如‘o’圆形、‘D’菱形)、color(标记边框色)、markerfacecolor(标记填充色)、markersize(标记大小);

  • medianprops:控制中位线(箱体内的横线,代表中位数)的样式。常用包括,color(线条颜色)、linewidth(线宽)、linestyle(线条样式);

  • meanprops:控制均值标记(需配合showmeans=True启用)的样式。若meanline=True,则为线条样式(同medianprops);否则为标记样式(同flierprops)示例:{‘color’: ‘purple’, ‘linestyle’: ‘–‘}(线条)或{‘marker’: ‘^’, ‘color’: ‘purple’}(标记);

  • capprops:控制箱型图 “须” 两端的帽子(横线)样式。常用包括,color(颜色)、linewidth(线宽)、linestyle(线条样式)示例:{‘color’: ‘orange’, ‘linewidth’: 2}

  • whiskerprops:控制 “须”(连接箱体与帽子的线段)的样式。常用键同capprops,用于区分须线与帽子的视觉效果示例:{‘color’: ‘gray’, ‘linestyle’: ‘–‘, ‘linewidth’: 1}

# 生成多组数据
np.random.seed(1)
group1 = np.random.normal(100, 20, 200)
group2 = np.random.normal(120, 25, 200)
group3 = np.random.normal(90, 15, 200)

data = [group1, group2, group3]
labels = ['组1''组2''组3']

# 自定义箱型图各部分的样式
box_style = {
            # 箱体样式:实线、线宽2、深蓝色边框
            'boxprops': dict(linestyle='-', linewidth=2, color='darkblue'),
            # 须线样式:虚线、线宽1.5、绿色
            'whiskerprops': dict(linestyle='--', linewidth=1.5, color='green'),
            # 须线端点帽子样式:线宽2、红色
            'capprops': dict(linewidth=2, color='red'),
            # 中位线样式:实线、线宽1.5、橙色
            'medianprops': dict(linestyle='-', linewidth=1.5, color='orange'),
            # 异常值样式:菱形标记、橙色边框、黑色填充、大小6
            'flierprops': dict(marker='D', color='orange', markerfacecolor='k', markersize=6),
            # 均值线样式:虚线、线宽1.5、紫色(需配合showmeans=True使用)
            'meanprops':dict(linestyle='--', linewidth=1.5, color='purple')
            # 'meanprops':dict(marker='^', color='purple')
}

plt.figure(figsize=(10, 6))
bp = plt.boxplot(
                data,                 # 输入的多组数据
                labels=labels,        # 设置x轴刻度标签
                patch_artist=True,    # 开启箱体填充功能(必须设置才能自定义填充色)
                showmeans=True,       # 显示均值(配合meanprops和meanline使用)
                meanline=True,        # 将均值显示为线而非点(与meanprops的线条样式对应)
                **box_style           # 通过解包操作应用自定义样式字典
)

# 为每个箱体设置不同的填充颜色
colors = ['lightblue''lightgreen''lightyellow']
# 遍历箱体对象和颜色列表,逐一设置填充色
# bp['boxes']是一个包含所有箱体的列表,与colors按顺序对应
for patch, color in zip(bp['boxes'], colors):
    patch.set_facecolor(color)
    

plt.title('自定义样式与颜色')
plt.ylabel('测量值')
plt.grid(True, alpha=0.3)
plt.show()

可视化结果如下图所示:


  • 示例2:分组箱型图

绘制分组箱型图其原理是借坐标偏移实现多分组有序排列,以颜色编码次级维度、位置编码主类别,同时保留箱型图展示中位数、离散度等功能,可直观呈现多维度数据分布差异,适用于多类别多时间维度等对比场景。

# 创建分组数据
np.random.seed(1)
categories = ['A类''B类''C类']
quarter1 = [np.random.normal(100, 15, 50) for _ in range(3)]
quarter2 = [np.random.normal(120, 12, 50) for _ in range(3)]
quarter3 = [np.random.normal(110, 10, 50) for _ in range(3)]

data = [quarter1, quarter2, quarter3]

plt.figure(figsize=(12, 7))

# 设置箱体位置和宽度(实现同类别内多季度数据并排显示)
# 计算每个产品类别的基准位置(间隔为2,避免箱体重叠)
positions = np.arange(len(categories)) * 2
# 单个箱体的宽度(设置为0.6,确保同类别内三个季度的箱体紧凑排列)
width = 0.6

# 循环绘制每个季度的箱型图
for i, quarter in enumerate(data):
    bp = plt.boxplot(
        quarter, 
        # 计算箱体位置:基准位置 + 季度偏移(i*width确保同类别内横向排列)
        positions=positions + i*width, 
        widths=width, 
        patch_artist=True
    )
    
    # 为当前季度的所有箱体设置统一颜色
    for box in bp['boxes']:
        box.set_facecolor(plt.cm.Set3(i/3))

# 设置x轴标签
plt.xticks(positions + width, categories)
plt.xlabel('产品类别')
plt.ylabel('性能指标')
plt.title('分组箱型图')

# 添加图例(手动创建,因为箱型图默认不生成图例)
from matplotlib.patches import Patch # 导入补丁类用于创建图例元素
# 为每个季度创建一个图例元素(使用对应的填充色和标签)
legend_elements = [Patch(facecolor=plt.cm.Set3(i/3), 
                        label=f'第{i+1}季度'for i in range(3)]
plt.legend(handles=legend_elements)

plt.tight_layout()
plt.show()

可视化结果如下图所示:


更多内容可以前往官网查看

https://matplotlib.org/stable/


本篇文章来源于微信公众号: 码农设计师

RELATED ARTICLES

欢迎留下您的宝贵建议

Please enter your comment!
Please enter your name here

- Advertisment -

Most Popular

Recent Comments