4.3 类别图工厂函数 (catplot) 第四章:Seaborn 分类图 (Categorical Plots) - 4.3 类别图工厂函数 (catplot) 详解 Seaborn 是一个基于 Matplotlib 的 Python 数据可视化库,专注于创建美观且信息丰富的统计图形。在 Seaborn 的第四章,我们聚焦于分类图 (Categorical Plots),这类图表旨在展示一个或多个类别变量与数值变量之间的关系,或者类别变量本身的分布情况。 函数是 Seaborn 库中用于绘制分类图的工厂函数 (Factory Function)。它的强大之处在于,它能够以统一的接口创建多种不同类型的分类图,极大地简化了代码并提升了绘图效率。
Seaborn 是一个基于 Matplotlib 的 Python 数据可视化库,专注于创建美观且信息丰富的统计图形。在 Seaborn 的第四章,我们聚焦于分类图 (Categorical Plots),这类图表旨在展示一个或多个类别变量与数值变量之间的关系,或者类别变量本身的分布情况。
catplot() 函数是 Seaborn 库中用于绘制分类图的工厂函数 (Factory Function)。它的强大之处在于,它能够以统一的接口创建多种不同类型的分类图,极大地简化了代码并提升了绘图效率。通过 catplot(),我们可以轻松地绘制散点图、箱线图、小提琴图、条形图等等,而无需记住每个特定图表类型的函数名称和细微差异。
为什么使用工厂函数 catplot()?
统一接口,简化学习: catplot() 提供了一个统一的入口点来创建各种分类图,降低了学习成本,无需记忆多个不同的函数。
代码简洁,提高效率: 通过 kind 参数,只需简单设置即可切换不同的图表类型,代码更加简洁易懂。
强大的灵活性: catplot() 底层基于 FacetGrid 对象,这意味着它可以轻松地进行分面 (facet) 绘图,处理更复杂的数据关系。
易于定制: catplot() 返回一个 FacetGrid 对象,我们可以利用该对象进一步定制图表的外观和细节。
4.3.1 catplot() 函数的基本语法和参数
catplot() 函数的基本语法如下:
seaborn.catplot( data=None, *, x=None, y=None, hue=None, row=None, col=None, col_wrap=None, kind='strip', height=3.5, aspect=1, palette=None, hue_order=None, hue_norm=None, col_order=None, row_order=None, legend='auto', legend_out=False, sharex=True, sharey=True, margin_titles=False, facet_kws=None, **kwargs, )
让我们逐个解析一些关键参数:
data: DataFrame, array, 或 list of arrays (可选)。输入的数据集,可以是 Pandas DataFrame、NumPy 数组或其他可转换为 DataFrame 的数据结构。
x, y, hue: 字符串 (可选)。
x: 水平轴上的变量名,通常是类别变量。
y: 垂直轴上的变量名,通常是数值变量。
hue: 用于分组的类别变量,会在图例中区分不同组别。
row, col: 字符串 (可选)。用于分面绘图的类别变量。row 定义行分面,col 定义列分面。
col_wrap: int (可选)。当使用 col 进行列分面时,指定每行最多显示的列数,用于控制分面图的布局。
kind: 字符串 (可选)。核心参数! 指定要绘制的分类图类型。catplot() 支持多种 kind 值,包括:
类别散点图: 'strip' (默认), 'swarm'
类别分布图: 'box', 'violin', 'boxen'
类别估计图: 'bar', 'count', 'point'
height: 标量 (可选)。每个分面的高度(以英寸为单位)。
aspect: 标量 (可选)。分面的纵横比,aspect * height 给出每个分面的宽度。
palette: 调色板名称、颜色列表或字典 (可选)。用于 hue 变量的不同类别着色。
hue_order: 列表 (可选)。指定 hue 变量类别的显示顺序。
col_order, row_order: 列表 (可选)。指定 col 和 row 分面变量类别的显示顺序。
legend: 'auto', 'brief', 'full', False (可选)。控制图例的显示。
sharex, sharey: bool 或 {'row', 'col'} (可选)。控制分面之间是否共享 x 轴和 y 轴。
**kwargs: 其他关键字参数。会被传递给底层绘图函数 (例如,传递给 matplotlib.pyplot.scatter() 或 matplotlib.pyplot.boxplot() 等)。
4.3.2 kind 参数详解:不同类型的分类图
kind 参数是 catplot() 的灵魂,它决定了最终生成的图表类型。我们来详细了解 catplot() 支持的各种 kind 值,并结合代码示例进行说明。
1. 类别散点图 (Categorical Scatter Plots)
kind='strip' (默认): 条形散点图 (Strip Plot)
条形散点图是类别散点图的基础类型。它沿着类别轴分布数据点,直观展示每个类别中数值变量的分布情况。为了避免点重叠,strip plot 通常会引入轻微的抖动 (jitter)。
import seaborn as sns import matplotlib.pyplot as plt # 加载示例数据集 'tips' tips = sns.load_dataset("tips") # 使用 catplot 绘制条形散点图 (默认 kind='strip') sns.catplot(data=tips, x="day", y="total_bill") plt.title("Strip Plot of Total Bill by Day") plt.show()
graph TD
A[开始] --> B{加载 tips 数据集}
B --> C[绘制条形散点图]
C --> D[添加标题 Strip Plot of Total Bill by Day]
D --> E[显示图表]
E --> F[结束]
**关键参数:** * **`jitter`**: 布尔值或数值 (可选)。控制抖动量。`True` 表示默认抖动,数值表示抖动幅度。设置为 `False` 可以禁用抖动。 * **`dodge`**: 布尔值 (可选)。当使用 `hue` 参数时,设置为 `True` 可以将不同 `hue` 分组的点沿类别轴分开显示,避免重叠。 ```python # 使用 hue 和 dodge 参数 sns.catplot(data=tips, x="day", y="total_bill", hue="sex", dodge=True) plt.title("Strip Plot with Hue and Dodge") plt.show()
kind='swarm' : 蜂群散点图 (Swarm Plot)
蜂群散点图也是一种类别散点图,它使用算法调整点的位置,避免重叠,同时尽可能保持数据的原始分布形状。相比 strip plot,swarm plot 更能清晰地展示每个类别内数据的密度和分布形态,但当数据量很大时,绘制速度可能会较慢。
# 使用 catplot 绘制蜂群散点图 (kind='swarm') sns.catplot(data=tips, x="day", y="total_bill", kind="swarm") plt.title("Swarm Plot of Total Bill by Day") plt.show()
graph TD
A[开始] --> B{加载 tips 数据集}
B --> C[绘制蜂群散点图]
C --> D[添加标题 Swarm Plot of Total Bill by Day]
D --> E[显示图表]
E --> F[结束]
```python # 蜂群散点图结合 hue 和 dodge sns.catplot(data=tips, x="day", y="total_bill", hue="sex", kind="swarm", dodge=True) plt.title("Swarm Plot with Hue and Dodge") plt.show()
2. 类别分布图 (Categorical Distribution Plots)
kind='box' : 箱线图 (Box Plot)
箱线图是一种常用的统计图,用于展示数值数据的分布概况。它通过箱子和须线展示数据的中位数、四分位数、以及异常值。箱线图能够清晰地比较不同类别之间数值分布的差异。
# 使用 catplot 绘制箱线图 (kind='box') sns.catplot(data=tips, x="day", y="total_bill", kind="box") plt.title("Box Plot of Total Bill by Day") plt.show()
graph TD
A[开始] --> B{加载 tips 数据集}
B --> C[绘制箱线图]
C --> D[添加标题 Box Plot of Total Bill by Day]
D --> E[显示图表]
E --> F[结束]
```python # 箱线图结合 hue sns.catplot(data=tips, x="day", y="total_bill", hue="sex", kind="box") plt.title("Box Plot with Hue") plt.show()
kind='violin' : 小提琴图 (Violin Plot)
小提琴图是箱线图和核密度估计图 (KDE) 的结合。它在箱线图的基础上,使用核密度估计展示了每个类别数据分布的形状。小提琴图能够更细致地展示类别内部数据的分布特征。
# 使用 catplot 绘制小提琴图 (kind='violin') sns.catplot(data=tips, x="day", y="total_bill", kind="violin") plt.title("Violin Plot of Total Bill by Day") plt.show()
graph TD
A[开始] --> B{加载 tips 数据集}
B --> C[绘制小提琴图]
C --> D[添加标题 Violin Plot of Total Bill by Day]
D --> E[显示图表]
E --> F[结束]
**关键参数:** * **`split`**: 布尔值 (可选)。当使用 `hue` 参数且 `hue` 变量只有两个类别时,设置为 `True` 可以将每个小提琴图分成两半,分别展示两个类别的分布,提高对比度。 * **`inner`**: 字符串 {'box', 'quart', 'point', 'stick', None} (可选)。指定小提琴图内部的标记类型,用于展示数据分布的细节。例如,`'box'` 在小提琴图内部绘制箱线图,`'quart'` 绘制四分位数线,`'point'` 绘制数据点,`'stick'` 绘制数据刻度线,`None` 则不绘制内部标记。 ```python # 小提琴图结合 hue 和 split sns.catplot(data=tips, x="day", y="total_bill", hue="sex", kind="violin", split=True) plt.title("Violin Plot with Hue and Split") plt.show()
kind='boxen' : 增强箱线图 (Boxen Plot)
boxen plot (也称为 letter-value plot) 是箱线图的增强版本,更适合展示大型数据集的分布。它在箱线图的基础上,绘制了更多的箱子,更详细地展示了数据的分位数信息,尤其是在分布的尾部。
# 使用 catplot 绘制增强箱线图 (kind='boxen') sns.catplot(data=tips, x="day", y="total_bill", kind="boxen") plt.title("Boxen Plot of Total Bill by Day") plt.show()
graph TD
A[开始] --> B{加载 tips 数据集}
B --> C[绘制箱线图]
C --> D[添加标题 Boxen Plot of Total Bill by Day]
D --> E[显示图表]
E --> F[结束]
```python # 增强箱线图结合 hue sns.catplot(data=tips, x="day", y="total_bill", hue="sex", kind="boxen") plt.title("Boxen Plot with Hue") plt.show()
3. 类别估计图 (Categorical Estimate Plots)
kind='bar' : 条形图 (Bar Plot)
条形图用于展示每个类别中数值变量的平均值 (或其他统计量)。条形的高度表示该统计量的值,误差线 (error bar) 通常表示置信区间或标准差。条形图适合比较不同类别之间的平均水平。
# 使用 catplot 绘制条形图 (kind='bar') sns.catplot(data=tips, x="day", y="total_bill", kind="bar") plt.title("Bar Plot of Total Bill by Day") plt.show()
graph TD
A[开始] --> B{加载 tips 数据集}
B --> C[sns catplot data tips x day y total bill kind bar]
C --> D[绘制条形图]
D --> E[添加标题 Bar Plot of Total Bill by Day]
E --> F[显示图表]
F --> G[结束]
**关键参数:** * **`estimator`**: 函数 (可选)。指定用于计算每个类别统计量的函数,默认为 `numpy.mean` (平均值)。可以自定义函数,例如 `numpy.median` (中位数), `numpy.sum` (总和) 等。 * **`ci`**: 数值或 "sd" 或 None (可选)。控制误差线的显示。数值 (0-100) 表示置信区间的百分比,`"sd"` 表示标准差,`None` 表示不显示误差线。 * **`n_boot`**: int (可选)。用于计算置信区间的 bootstrap 迭代次数。 ```python # 条形图结合 hue, 修改 estimator 和 ci sns.catplot(data=tips, x="day", y="total_bill", hue="sex", kind="bar", estimator=sum, ci="sd") plt.title("Bar Plot with Hue, Sum Estimator, and SD Error Bars") plt.show()
kind='count' : 计数图 (Count Plot)
计数图是一种特殊的条形图,它统计每个类别中样本的数量。它本质上是对类别变量的频率进行可视化。计数图只需要指定 x (或 y) 轴的类别变量,不需要数值变量。
# 使用 catplot 绘制计数图 (kind='count') sns.catplot(data=tips, x="day", kind="count") plt.title("Count Plot of Days") plt.show()
graph TD
A[开始] --> B{加载 tips 数据集}
B --> C[绘制计数图]
C --> D[添加标题 Count Plot of Days]
D --> E[显示图表]
E --> F[结束]
```python # 计数图结合 hue sns.catplot(data=tips, x="day", hue="sex", kind="count") plt.title("Count Plot with Hue") plt.show()
kind='point' : 点图 (Point Plot)
点图也用于展示每个类别中数值变量的平均值,但它使用点和连接线来表示,而不是条形。点图更适合展示多个类别变量之间的交互作用,以及类别变量在不同 hue 分组下的变化趋势。
# 使用 catplot 绘制点图 (kind='point') sns.catplot(data=tips, x="day", y="total_bill", kind="point") plt.title("Point Plot of Total Bill by Day") plt.show()
graph TD
A[开始] --> B{加载 tips 数据集}
B --> C[绘制点图]
C --> D[添加标题 Point Plot of Total Bill by Day]
D --> E[显示图表]
E --> F[结束]
**关键参数:** * **`join`**: 布尔值 (可选)。设置为 `True` (默认) 时,连接同一 `hue` 分组不同类别的点,形成折线。设置为 `False` 则只显示点。 ```python # 点图结合 hue 和 join sns.catplot(data=tips, x="day", y="total_bill", hue="sex", kind="point", join=False) plt.title("Point Plot with Hue and No Join") plt.show()
4.3.3 分面绘图 (Facetting) 与 FacetGrid 对象
catplot() 的强大之处不仅在于其统一的接口,还在于其强大的分面绘图能力。通过 row 和 col 参数,我们可以轻松地创建分面网格 (facet grid),将数据按照指定的类别变量分组,并在不同的子图中绘制相应的图表。
catplot() 函数实际上是构建并返回一个 FacetGrid 对象。我们可以利用这个 FacetGrid 对象进一步定制分面图的各个方面,例如设置标题、轴标签、调整布局等等。
# 使用 row 和 col 参数进行分面绘图 g = sns.catplot(data=tips, x="total_bill", y="tip", row="sex", col="smoker") g.fig.suptitle("Facet Grid of Tip vs Total Bill", y=1.03) # 设置整个分面图的标题 g.set_axis_labels("Total Bill ($)", "Tip ($)") # 设置轴标签 plt.show()
FacetGrid 对象常用方法:
g.fig: 访问 Matplotlib Figure 对象,可以设置整个图表的属性,例如标题 (suptitle)。
g.axes: 访问所有子图的 Matplotlib Axes 对象组成的 NumPy 数组。
g.axes_dict: 访问子图的 Matplotlib Axes 对象组成的字典,键是分面变量的组合。
g.set(...): 批量设置所有子图的属性,例如轴标签、刻度、标题等。
g.set_axis_labels(x_var, y_var): 设置所有子图的 x 轴和 y 轴标签。
g.set_titles(template): 设置每个子图的标题,可以使用模板字符串,例如 template = "{row_var} and {col_var}"。
g.add_legend(): 添加图例。
g.savefig(filename): 保存分面图。
4.3.4 catplot() 代码实践进阶
除了基本用法,catplot() 还可以进行更复杂的定制和应用。
示例 1: 调整图表外观和调色板
# 自定义调色板和样式 custom_palette = {"Male": "skyblue", "Female": "lightcoral"} sns.set_style("whitegrid") # 设置 Seaborn 样式 sns.catplot( data=tips, x="day", y="total_bill", hue="sex", kind="violin", split=True, palette=custom_palette, height=4, aspect=0.8 # 调整图表尺寸 ) plt.title("Customized Violin Plot with Palette and Style") plt.show()
示例 2: 使用 col_wrap 控制列分面布局
# 使用 col_wrap 控制列分面布局,每行最多显示 3 列 sns.catplot(data=tips, x="total_bill", y="tip", col="day", col_wrap=3) plt.suptitle("Column Facet with col_wrap", y=1.03) plt.show()
示例 3: 保存 catplot() 生成的图表
# 保存 catplot 生成的图表 g = sns.catplot(data=tips, x="day", y="total_bill", kind="box") g.savefig("catplot_boxplot.png") # 保存为 PNG 文件 plt.title("Box Plot Saved to File") plt.show()