HOWTO · Seaborn

如何使用 Seaborn 创建小提琴图

本教程演示如何使用 Python 中的 Seaborn 模块创建小提琴图

本页内容

Seaborn 小提琴图展示数值变量的估计分布。图形的宽度表示密度:某个数值附近越宽,表示该处的估计密度越高。内部标记用于概括数据,并不代表每个观测值。图形形状可能显示多个峰,但解读时还应结合样本量和原始数据。

了解小提琴图展示的内容

小提琴图将密度形状与可选的汇总标记结合起来。密度是根据观测值估算的,因此它是一种平滑视图,而不是直方图或原始数据点的集合。根据 inner 设置,内部标记可以显示箱体、四分位数、每个观测值对应的短线,也可以不显示汇总标记。

小提琴图适合比较数值分布的形状和离散程度。它本身无法说明数据为何呈现这种形状;样本量较小时,估计出的密度可能显得比观测值实际支持的结果更确定或更细致。

绘制单个变量

将数值序列传给 violinplot() 即可绘制一个变量。这个独立示例直接使用 Python 列表,因此不需要转换成数组。运行前,请先在 Python 环境中安装 Seaborn 和 Matplotlib。代码会创建一个包含该分布的 Axes,不会打印文本输出。

import matplotlib.pyplot as plt
import seaborn as sns

values = [4, 5, 5, 6, 6, 7, 8, 8, 9, 10]
ax = sns.violinplot(y=values, inner="quartile", color="skyblue")
ax.set_ylabel("Value")
ax.set_title("Distribution of values")
plt.show()

纵轴表示数值。小提琴图较宽的部分表示该数值附近的估计集中程度较高。样本量较小时,除了平滑后的形状,也应查看各个观测值。

按类别比较分布

要按类别比较分布,请通过 y 提供数值列,并通过 x 提供类别列。示例使用 pandas DataFrame,将 Price 映射到 y,将 Product 映射到 x,因此 x 轴会为每种产品显示一个类别。此调用没有 hue 参数,也没有按日期分组。

import pandas as pd
import seaborn as sns

prices = pd.DataFrame(
    {
        "Price": [9, 10, 15, 16, 13, 14, 15, 18, 11, 12, 14, 15, 16, 17, 18, 19],
        "Product": ["A"] * 4 + ["B"] * 4 + ["A"] * 4 + ["B"] * 4,
    }
)
ax = sns.violinplot(data=prices, x="Product", y="Price")
ax.set_title("Price distribution by product")

每个小提琴图概括分配给相应产品的价格。若要增加第二个分组维度,可将对应列指定给 hue;随后,每个 hue 级别都会在 x 轴的各类别中分别区分显示。只有当绘图数据和参数确实包含某种分组时,才应描述该分组,例如按日期分组。

自定义小提琴图

观测值很少时,密度估计可能会产生误导。可以叠加 stripplot(),显示各个数值并将其与平滑后的形状对照。散点有助于检查样本,但不能让小样本变得更可靠。

import matplotlib.pyplot as plt
import seaborn as sns

values = [4, 5, 5, 6, 6, 7, 8, 8, 9, 10]
ax = sns.violinplot(y=values, inner=None, color="skyblue")
sns.stripplot(y=values, color="red", ax=ax)
ax.set_ylabel("Value")
plt.show()

使用 order 选择类别的显示顺序,例如 order=["B", "A"]。使用 inner 控制汇总标记;常见选项包括 "box"、"quartile"、"stick" 和 None。叠加箱线图可以补充一种熟悉的汇总视图,但它仍然表示同一组样本,不能代替对观测值的检查。

使用返回的绘图对象

violinplot() 返回 Matplotlib 的 Axes,可以用它设置标签、范围和标题,也可以添加其他标记。例如,单变量示例将结果保存到 ax,并调用 ax.set_ylabel() 和 ax.set_title()。

对于图级分类图,可以使用 catplot(kind="violin", ...);它返回 FacetGrid。如果要使用 row 或 col 等选项创建多个面板,这种接口会很有用。需要坐标轴级绘图时选择 violinplot();需要图级网格时选择 catplot()。