箱线图(Box Plot)是一种常用的统计图表,用于展示数值型数据的分布情况,包括中位数、上下四分位数、异常值等。它能够直观地显示数据的集中趋势、离散程度以及异常值的情况,是探索性数据分析中常用的工具之一。
箱线图通常由五个要素组成:
下四分位数(Q1):数据中所有观察值由小到大排列后,处于第 25 百分位的值。即将全部观察值分成四等份,Q1 表示第一等份的边界。
中位数(Q2 或者所谓的第二四分位数):数据中所有观察值由小到大排列后,处于中间位置的值。即将全部观察值分成两等份,中位数表示第二等份的边界。
上四分位数(Q3):数据中所有观察值由小到大排列后,处于第 75 百分位的值。即将全部观察值分成四等份,Q3 表示第三等份的边界。
箱体(Box):由 Q1 到 Q3 所构成的矩形,它包含了数据的中间 50% 范围。箱体的长度代表了数据的离散程度,越长表示数据的离散程度越大。
异常值(Outliers):位于 Q1 - 1.5 * IQR 或 Q3 + 1.5 * IQR(其中 IQR 表示四分位距,即 Q3 - Q1)范围之外的数据点。异常值通常被认为是与大多数数据点显著不同的值。
在箱线图中,箱体的上边界通常延伸至上四分位数,下边界延伸至下四分位数。从箱体的顶部和底部延伸出的线段称为“须”,它们表示数据的范围。有时,须的末端可能会标记异常值。
▌一般多组箱线图
本例数据的Excel文件为 boxplot.xlsx
,以该数据使用 Seaborn 库绘制的一般箱线图如图 1 所示。
图 1. 一般箱线图绘制实例
图 1 的完整绘图代码如下:
import os
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
# 设置主题风格和背景
sns.set_theme(style="white", rc={"axes.facecolor": (0, 0, 0, 0)})
# 读取Excel文件中的数据
df = pd.read_excel('boxplot.xlsx')
# 绘制箱线图
plt.figure(figsize=(4, 4))
sns.boxplot(x="species", y="sepal_length", hue="species", data=df, palette="Blues", legend=False)
# 设置刻度线
plt.xticks(fontsize=12, fontweight='bold', fontname='Arial')
plt.yticks(fontsize=12, fontweight='bold', fontname='Arial')
# 设置坐标轴标签和标题
plt.xlabel('Species', fontsize=14, fontweight='bold', fontname='Arial')
plt.ylabel('Sepal Length (cm)', fontsize=14, fontweight='bold', fontname='Arial')
# 调整图像布局,确保所有元素居中
plt.tight_layout()
# 保存图像
output_path = '图1 一般箱线图绘制实例.png'
os.makedirs(os.path.dirname(output_path), exist_ok=True)
plt.savefig(output_path, dpi=600)
# 显示图形
plt.show()
在上述代码中,使用了 Seaborn 的 boxplot
函数绘制箱线图,其中:
x="species"
指定 x 轴的变量为species
。y="sepal_length"
指定 y 轴的变量为sepal_length
。hue="species"
将species
变量用于着色,以区分不同类别的箱线图。data=df
指定数据来源为 DataFramedf
。palette="Blues"
使用蓝色调色板。legend=False
禁用图例显示。
Seaborn 的 sns.boxplot
函数提供了许多参数,允许用户对绘制的箱线图进行详细的定制。以下是一些常用的参数及其说明:
基本参数
data
:传递给函数的数据集,可以是 DataFrame、数组或列表。x
,y
,hue
:指定数据中用于绘制箱线图的变量。order
,hue_order
:控制 x 轴和 hue 的类别顺序。orient
:控制图表的方向('v' 表示垂直,'h' 表示水平)。color
:整体颜色。palette
:指定调色板(例如 'deep', 'muted', 'pastel', 'dark', 'colorblind' 或颜色列表)。
统计参数
saturation
:控制箱线图颜色的饱和度。width
:控制箱线图的宽度。dodge
:当 hue 不为空时,是否对箱线图进行 dodge 分布。fliersize
:控制异常值点的大小。linewidth
:控制箱线图线条的宽度。
绘图元素参数
whis
:设置须状线的长度,默认为 1.5 倍的四分位距。notch
:是否在箱线图中绘制凹槽。sym
:控制异常值的符号,默认为 'o'。meanline
:是否用线条表示均值。showmeans
:是否显示均值。
样式参数
ax
:指定绘制的轴对象。zorder
:控制绘图元素的层次顺序。ci
:置信区间的大小(默认为 95)。n_boot
:引导样本的数量。
其他参数
formatter
:格式化工具。kwargs
:其他绘图参数传递给 matplotlib 的plt.boxplot
函数。
在图 2 的示例中,设置了 palette
、width
、notch
、fliersize
、linewidth
等参数,以展示如何自定义箱线图的外观。可以根据需要调整这些参数,以达到所需的视觉效果。
图 2. 缺口箱线图绘制实例
图 2 的核心绘图代码如下:
# 绘制箱线图
plt.figure(figsize=(4, 4))
sns.boxplot(x="species", y="sepal_length", hue="species", data=df,
palette="Set3", # 调色板
width=0.6, # 箱线图宽度
notch=True, # 是否绘制凹槽
fliersize=5, # 异常值点大小
linewidth=2.5, # 线条宽度
showcaps=True, # 显示箱线图的端点线
showmeans=True, # 显示均值
meanline=True) # 均值线
▌ 分组箱线图
在上一节已经详细介绍了使用 Seaborn 的 boxplot
函数绘制箱线图的参数,可以发现只需要设置 hue
参数就可以绘制分组箱线图。使用示例数据 Grouped Box Plot.xlex
进行绘制,如图 3 所示。
图 3. 分组箱线图绘制实例
图 3 的核心绘图代码如下所示:
# 绘制箱线图
plt.figure(figsize=(4, 4))
sns.boxplot(x="day", y="total_bill", hue="smoker", data=df,
palette="Set1", # 调色板
width=0.8, # 箱线图宽度
fliersize=5, # 异常值点大小
linewidth=1, # 线条宽度
showcaps=True) # 显示箱线图的端点线
▌ 散点箱线图
为了更直观地观察每一个数据点的位置,我们可以使用散点箱线图(Boxplot with Points)。这种图表不但结合了箱线图的优点,还通过在箱线图上叠加散点,揭示了数据的具体分布情况。仍以示例数据 Grouped Box Plot.xlex
为例,图 4 展示了散点箱线图的绘制示例。
图 4. 散点箱线图绘制实例
图 4 绘图的核心代码如下所示:
# 绘制箱线图
plt.figure(figsize=(4, 4))
palette = sns.color_palette("Set1")
ax = sns.boxplot(x="day", y="total_bill", data=df, palette=palette,
width=0.8, linewidth=1, showfliers=False)
# 绘制散点图
sns.stripplot(x="day", y="total_bill", data=df, palette=palette,
edgecolor="black", linewidth=1, ax=ax)
在以上代码中,设置 showfliers=False
用于隐藏箱线图中的异常值,以便更清楚地显示散点。在绘制箱线图的基础上,通过 stripplot()
函数绘制了散点图,并且使用与箱线图一致的配色方案。
▌带显著性标记的散点箱线图
通过散点箱线图,我们能够更加直观地观察数据点的具体分布情况。然而,有时候我们还需要进一步比较不同组间的数据,判断其差异是否具有统计显著性。在这种情况下,带显著性标记的散点箱线图(Boxplot with Points and Significance Markers)就显得尤为重要。它不仅能显示每组数据的分布,还能够在图中直接标记出显著性差异,使数据分析和结果呈现更加清晰明了。仍以示例数据 Grouped Box Plot.xlex
为例,我们为其增加显著性差异标记,如图 5 所示。
图 5. 带显著性标注的散点箱线图绘制实例
图 5 的核心代码如下所示:
from statannotations.Annotator import Annotator
# 读取Excel文件中的数据
df = pd.read_excel('Grouped_boxplot.xlsx')
# 绘制箱线图
plt.figure(figsize=(4, 4))
palette = sns.color_palette("Set1")
ax = sns.boxplot(x="day", y="total_bill", data=df, palette=palette,
width=0.8, linewidth=1, showfliers=False)
# 绘制散点图
sns.stripplot(x="day", y="total_bill", data=df, palette=palette,
edgecolor="black", linewidth=1, ax=ax)
# 定义需要进行显著性检验的组对
pairs = [("Thur", "Fri"), ("Thur", "Sat"), ("Fri", "Sun")]
# 初始化Annotator对象,进行显著性标记
annotator = Annotator(ax, pairs, data=df, x="day", y="total_bill")
annotator.configure(test='Mann-Whitney', text_format='simple', line_height=0.03, line_width=1, loc='inside')
# 可以尝试其他检验方法,如注释中这些:
# annotator.configure(test='t-test_ind')
# annotator.configure(test='Wilcoxon', paired=True)
# annotator.configure(test='Kruskal')
annotator.apply_and_annotate()
在以上代码中,我们使用一个列表 pairs
来指定我们感兴趣的需要进行显著性检验的组对。本例子,我们选择了 ("Thur", "Fri")
, ("Thur", "Sat")
和 ("Fri", "Sun")
。通过Annotator
类,我们可以传入感兴趣的组对、数据、x轴和y轴变量。在 configure
方法中,我们指定了使用 Mann-Whitney U 检验 (test='Mann-Whitney'
),并选择简单文本格式 (text_format='simple'
) 以及线条高度和宽度。
关于 Mann-Whitney U 检验,它是非参数检验,适用于两个独立样本之间的比较,不要求数据服从正态分布。还有其他方法可以用于显著性差异检验,比如:t 检验(t-test),Welch’s t-test,Wilcoxon 符号秩检验(Wilcoxon Signed-Rank Test),ANOVA(方差分析)等,具体选择取决于数据特性和研究的具体需求。
如果您喜欢我们的文章,欢迎关注