Skip to content

Matplotlib - 小提琴图

小提琴图(Violin Plot)是一种强大的可视化方法,它结合了**箱线图(Box Plot)和核密度估计(Kernel Density Estimation, KDE)**图的特点。它们用于可视化数值数据的分布,特别适用于比较不同类别之间的分布。

小提琴图的关键特征:

  • 密度估计 (Density Estimation): 小提琴的主体是核密度估计 (KDE) 图,并在两侧镜像。小提琴在特定值处的宽度表示围绕该值的估计密度或数据点频率。
  • 箱线图元素(可选): 通常,在小提琴内部绘制一个微型箱线图或相关标记。这通常包括: - 中位数的标记 (Marker for the median)。 - 表示四分位数间距 (Interquartile Range, IQR: Q1 到 Q3) 的箱体 (Box)。 - 有时会有延伸到特定范围的线条(须,whiskers),但这不如标准箱线图常见。

与简单的箱线图相比,小提琴图提供了对数据分布更丰富、更深入的理解,揭示了箱线图摘要统计量所隐藏的多峰性(Multiple Peaks)等特征。

Matplotlib 中的 ax.violinplot() 方法用于创建小提琴图。

ax.violinplot(dataset, positions=None, showmeans=False, showextrema=True, showmedians=False, **kwargs)
  • dataset: 数组/向量的列表或序列。每个元素对应一个独立的小提琴。
  • positions: 类似数组的类型。设置小提琴的水平位置(默认为 [1, 2, 3, ...])。
  • showmeans: 布尔值。如果为 True,渲染平均值的标记。
  • showextrema: 布尔值。如果为 True(默认值),渲染数据极值的线条。
  • showmedians: 布尔值。如果为 True,渲染中位数的标记。
  • quantiles: 介于 0 和 1 之间的类似数组的类型。如果设置(例如 [0.25, 0.75]),则在小提琴内部渲染指定分位数 (quantiles) 的线条(通常用于替代完整的箱线图)。
  • bw_method: 字符串或浮点数。用于计算 KDE 估计器带宽的方法(影响平滑度)。
  • vert: 布尔值。如果为 True(默认值),创建垂直小提琴。如果为 False,创建水平小提琴。

示例:使用小提琴图比较不同分布。

import matplotlib.pyplot as plt
import numpy as np
# 1. 生成样本数据(例如,具有不同形状的分布)
np.random.seed(10)
dist1_normal = np.random.normal(100, 10, 200)
dist2_skewed = np.random.gamma(6, 15, 200) # 偏态分布
dist3_bimodal = np.concatenate([
np.random.normal(60, 10, 100),
np.random.normal(110, 10, 100)
]) # 双峰
dist4_uniform = np.random.uniform(70, 130, 200)
# 将数据集组合成列表
data_to_plot = [dist1_normal, dist2_skewed, dist3_bimodal, dist4_uniform]
labels = ['Normal', 'Skewed', 'Bimodal', 'Uniform']
# 2. 创建图表
fig, ax = plt.subplots(figsize=(10, 6))
# 3. 创建小提琴图
# 显示中位数和分位数(Q1、Q3),而不是默认的箱/极值
parts = ax.violinplot(data_to_plot,
showmeans=False,
showmedians=True,
quantiles=[[0.25, 0.75]] * len(data_to_plot) # 为分位数传递列表的列表
)
# 4. 自定义外观(可选)
colors = ['lightblue', 'lightgreen', 'lightcoral', 'lightsalmon']
for pc, color in zip(parts['bodies'], colors):
pc.set_facecolor(color)
pc.set_edgecolor('black')
pc.set_alpha(0.7)
# 自定义中位线
parts['cmedians'].set_colors('red')
parts['cmedians'].set_linewidth(2)
# 自定义分位线(如果显示)
if 'cquantiles' in parts:
parts['cquantiles'].set_colors('black')
parts['cquantiles'].set_linestyles(':')
parts['cquantiles'].set_linewidth(1.5)
# 自定义其他部分(如果显示平均值/极值的 cbars,以及 cmins、cmaxes)
# 5. 添加标签和标题
ax.set_title('Comparison of Data Distributions using Violin Plots')
ax.set_ylabel('Value')
ax.set_xticks(np.arange(1, len(labels) + 1)) # 设置标签位置
ax.set_xticklabels(labels)
ax.yaxis.grid(True)
plt.show()

此示例生成具有不同分布形状(正态、偏态、双峰、均匀)的数据,并使用 ax.violinplot 将其可视化。通过显示中位数和分位数(代表 IQR),以及观察小提琴的形状(KDE),我们可以比仅使用箱线图更清楚地了解每个分布的特征。