一、Seaborn概述
Seaborn是基于Matplotlib构建的Python统计可视化库,由Michael Waskom于2012年创建。它的核心理念是"让统计图表既美观又有信息量",通过简洁的API和优雅的默认主题,使数据分析人员能够用最少的代码生成高质量的统计图形。
Pandas集成
原生支持DataFrame,自动处理缺失值
Seaborn与Matplotlib的关系
理解Seaborn与Matplotlib的关系是学习的第一步。Matplotlib提供了底层绘图基础,而Seaborn在其之上构建了更高层次的API:
- Seaborn是Matplotlib的封装 — 所有Seaborn图表底层都是Matplotlib图形对象
- Seaborn提供默认主题 — 自动设置更美观的配色方案和图形样式
- Seaborn专精统计图表 — 提供分布图、热力图、分类图等统计专用图表
- Seaborn原生支持DataFrame — 列名直接作为参数,自动处理分类数据
- 可无缝结合使用 — 用Seaborn绘图,用Matplotlib微调细节
核心原则:Seaborn的设计哲学
- 高层级抽象 — 绘图函数直接映射数据列到视觉属性
- 美观优先 — 默认配色和样式经过精心挑选
- 统计驱动 — 自动计算置信区间、分布拟合等统计量
- 灵活扩展 — 支持FacetGrid创建多子图,适应复杂数据分析场景
# 安装和导入Seaborn
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
print(sns.__version__)
print(sns.get_dataset_names())
二、Seaborn内置数据集
Seaborn提供了多个经典数据集用于学习和演示,这些数据集覆盖了不同的数据类型和分析场景:
| 数据集 |
描述 |
适用场景 |
| iris |
鸢尾花数据集(150条,4个特征) |
分类、聚类、分布可视化 |
| tips |
餐厅小费数据(244条) |
分类分析、回归分析 |
| penguins |
企鹅数据(344条,3个物种) |
多维分类、分布对比 |
| titanic |
泰坦尼克号乘客数据 |
生存分析、分类统计 |
| diamonds |
钻石价格数据(约54000条) |
大规模数据可视化 |
| planets |
系外行星数据 |
散点图、时间序列 |
| fmri |
功能性磁共振数据 |
时间序列、置信区间 |
| flights |
航空乘客数据 |
热力图、时间序列 |
tips = sns.load_dataset("tips")
print(tips.head())
print(tips.info())
penguins = sns.load_dataset("penguins")
print(penguins.head())
print(tips.describe())
print(tips["day"].value_counts())
数据集加载说明
Seaborn数据集通过 sns.load_dataset() 加载,返回Pandas DataFrame对象。首次加载时会自动从GitHub仓库下载并缓存到本地。如果网络受限,也可以手动下载CSV文件后用 pd.read_csv() 读取。
三、分布可视化
分布可视化是数据分析中最常用的图表类型之一,用于理解数据的分布形态、集中趋势、离散程度和异常值。Seaborn提供了丰富的分布可视化工具。
3.1 displot — 通用分布图(Seaborn 0.11+)
displot 是Seaborn 0.11版本引入的通用分布绘图函数,它整合了直方图、核密度估计、经验累积分布和地毯图等多种分布可视化方式。该函数基于FacetGrid构建,天然支持多子图分面。
sns.displot(data=tips, x="total_bill")
plt.title("消费金额分布")
plt.show()
sns.displot(data=tips, x="total_bill", kde=True)
sns.displot(data=tips, x="tip", hue="sex", multiple="dodge")
sns.displot(data=tips, x="total_bill", hue="day", multiple="stack")
sns.displot(data=tips, x="total_bill", col="time", row="sex")
3.2 histplot — 直方图
直方图将数据划分为若干个连续的区间(bins),统计每个区间内的数据频数。它是理解数据分布最直观的方式。
sns.histplot(
data=tips,
x="total_bill",
bins=30,
binwidth=2,
kde=True,
color="steelblue",
alpha=0.7,
edgecolor="white"
)
sns.histplot(data=tips, x="total_bill", hue="sex",
element="step", fill=False)
3.3 kdeplot — 核密度估计图
核密度估计图用平滑的曲线表示数据的概率密度分布,是直方图的平滑版本。它使用核函数(默认为高斯核)对每个数据点周围进行平滑处理。
sns.kdeplot(data=tips, x="total_bill", fill=True)
sns.kdeplot(data=tips, x="total_bill", y="tip",
fill=True, cmap="Blues")
sns.kdeplot(data=tips, x="total_bill", hue="time",
fill=True, alpha=0.5)
sns.kdeplot(data=tips, x="total_bill", bw_adjust=0.5, label="带宽=0.5")
sns.kdeplot(data=tips, x="total_bill", bw_adjust=2.0, label="带宽=2.0")
plt.legend()
3.4 ecdfplot — 经验累积分布图
ECDF(Empirical Cumulative Distribution Function)图绘制数据从小到大的累积比例,每个数据点对应一个跳跃。它不需要选择带宽或柱子宽度参数,忠实反映原始数据分布。
sns.ecdfplot(data=tips, x="total_bill")
sns.ecdfplot(data=tips, x="total_bill", hue="sex")
sns.ecdfplot(data=tips, x="total_bill", y="tip")
3.5 rugplot — 地毯图
地毯图在坐标轴上绘制短须线标记每个数据点的位置,通常作为其他分布图的补充,显示数据的精确位置和密度。
sns.rugplot(data=tips, x="total_bill")
sns.histplot(data=tips, x="total_bill", kde=True)
sns.rugplot(data=tips, x="total_bill", color="red", height=0.05)
sns.kdeplot(data=tips, x="total_bill", hue="sex", fill=True)
sns.rugplot(data=tips, x="total_bill", hue="sex")
分布图选择指南
- 连续变量单变量分布 — 使用
histplot(样本量大)或 kdeplot(平滑连续)
- 连续变量双变量分布 — 使用
kdeplot(等高线/填充)或 histplot(2D分箱)
- 精确查看数据位置 — 使用
rugplot 叠加在分布图上
- 无参数选择的分布 — 使用
ecdfplot 显示精确的累积比例
四、关系可视化
关系可视化用于探索两个或多个数值变量之间的关联模式,发现相关性、趋势、聚类和异常值。
4.1 scatterplot — 散点图
散点图是展示两个连续变量关系的基础图表,每个点代表一个观测样本。
sns.scatterplot(data=tips, x="total_bill", y="tip")
sns.scatterplot(
data=tips,
x="total_bill",
y="tip",
hue="time",
size="size",
style="sex",
palette="deep",
sizes=(20, 200)
)
4.2 lineplot — 线图
线图用于展示变量随某个连续维度的变化趋势,特别适合时间序列数据。
fmri = sns.load_dataset("fmri")
sns.lineplot(data=fmri, x="timepoint", y="signal")
sns.lineplot(
data=fmri,
x="timepoint",
y="signal",
hue="event",
style="region"
)
sns.lineplot(data=fmri, x="timepoint", y="signal", ci=None)
4.3 relplot — 关系图(高级接口)
relplot 是关系图的统一接口,通过 kind 参数切换散点图和线图,天然支持FacetGrid分面。
sns.relplot(data=tips, x="total_bill", y="tip",
hue="day", col="time", kind="scatter")
sns.relplot(data=fmri, x="timepoint", y="signal",
hue="event", col="region", kind="line")
sns.relplot(data=tips, x="total_bill", y="tip",
hue="sex", col="time", row="day",
kind="scatter")
4.4 hue / style / size 语义映射
Seaborn的语义映射系统允许将数据列映射到视觉属性,在一个图表中展示多个维度的信息:
| 映射参数 |
视觉属性 |
适用数据类型 |
示例 |
hue |
颜色 |
分类或连续变量 |
hue="sex", hue="total_bill" |
style |
标记/线型 |
分类变量 |
style="day" |
size |
点大小/线宽 |
分类或连续变量 |
size="tip", size="group" |
alpha |
透明度 |
连续变量 |
alpha="distance" |
marker |
标记形状 |
分类变量 |
marker=True |
语义映射最佳实践
- 使用
hue 区分最重要的分组变量
- 使用
style 辅助区分分类变量(方便黑白打印)
- 使用
size 编码数值变量(如权重、数量)
- 避免在一张图中使用超过3种映射,防止视觉过载
- 搭配
palette 参数选择合适的颜色方案
五、分类可视化
分类可视化用于比较不同类别之间的数值分布和统计特征。Seaborn的 catplot 系列提供了丰富的分类图表类型。
5.1 catplot — 分类图统一接口
catplot 是分类可视化的高级接口,通过 kind 参数切换不同类型的分类图。
sns.catplot(data=tips, x="day", y="total_bill", kind="box")
sns.catplot(data=tips, x="day", y="total_bill", kind="violin")
sns.catplot(data=tips, x="day", y="total_bill",
hue="sex", col="time", kind="box")
5.2 boxplot — 箱线图
箱线图通过四分位数直观展示数据的分布特征。箱体表示数据的四分位距(IQR),中位数用横线标记,须线延伸至1.5倍IQR范围,之外的为异常值。
sns.boxplot(data=tips, x="day", y="total_bill")
sns.boxplot(data=tips, x="day", y="total_bill", hue="sex")
sns.boxplot(data=tips, y="day", x="total_bill")
5.3 violinplot — 小提琴图
小提琴图结合了箱线图和核密度估计图的优点:外侧形状表示数据的概率密度分布,内部显示四分位数和中位数。宽度越大的区域表示数据越集中。
sns.violinplot(data=tips, x="day", y="total_bill")
sns.violinplot(data=tips, x="day", y="total_bill",
hue="sex", split=True)
sns.violinplot(
data=tips, x="day", y="total_bill",
inner="quart",
cut=0,
bw=0.2
)
5.4 stripplot 与 swarmplot
stripplot(带状图)在每个类别上绘制散点,swarmplot(蜂群图)对点进行避让排列避免重叠。两者常与箱线图或小提琴图叠加使用。
sns.stripplot(data=tips, x="day", y="total_bill", jitter=True)
sns.swarmplot(data=tips, x="day", y="total_bill",
color="black", alpha=0.5)
sns.violinplot(data=tips, x="day", y="total_bill",
inner=None, alpha=0.4)
sns.swarmplot(data=tips, x="day", y="total_bill",
color="#2c3e50", alpha=0.7)
5.5 barplot / countplot / pointplot
sns.barplot(data=tips, x="day", y="total_bill")
sns.barplot(data=tips, x="day", y="total_bill", hue="sex")
sns.countplot(data=tips, x="day")
sns.countplot(data=tips, x="day", hue="sex")
sns.pointplot(data=tips, x="day", y="total_bill")
sns.pointplot(data=tips, x="day", y="total_bill",
hue="sex", dodge=True,
markers=["o", "s"], linestyles=["--", "-"])
分类图选择建议
- 箱线图 — 适合展示整体分布和异常值,数据量大时效果好
- 小提琴图 — 显示分布形状,适合中等规模数据
- 蜂群图 — 展示所有数据点,适合小样本(<200个点)
- 柱状图 — 展示均值比较,适合呈现汇总统计量
- 计数图 — 展示类别出现频次
- 点图 — 简洁展示均值变化趋势
六、回归可视化
回归可视化用于探索变量间的线性或非线性关系,并拟合统计模型进行预测分析。
6.1 lmplot — 线性回归图(高级接口)
lmplot 绘制散点图并拟合回归线,自动显示置信区间。它基于FacetGrid构建,天然支持分面。
sns.lmplot(data=tips, x="total_bill", y="tip")
sns.lmplot(data=tips, x="total_bill", y="tip",
hue="sex", markers=["o", "x"])
sns.lmplot(data=tips, x="total_bill", y="tip",
col="time", row="sex")
sns.lmplot(data=tips, x="total_bill", y="tip",
order=2)
sns.lmplot(data=tips, x="total_bill", y="tip",
ci=95)
6.2 regplot — 回归图(底层接口)
regplot 的绘图逻辑与 lmplot 相同,但不支持分面。它更灵活,可以直接在已有坐标轴上绘图。
sns.regplot(data=tips, x="total_bill", y="tip")
fig, ax = plt.subplots(figsize=(8, 6))
sns.regplot(data=tips, x="total_bill", y="tip",
scatter_kws={"alpha": 0.5, "s": 50},
line_kws={"color": "red", "lw": 3},
ax=ax)
ax.set_title("消费金额 vs 小费 回归分析")
sns.regplot(data=tips, x="total_bill", y="tip",
logx=True)
6.3 residplot — 残差图
残差图用于评估回归模型的拟合效果。理想情况下,残差应随机分布在零线附近,无明显模式。
sns.residplot(data=tips, x="total_bill", y="tip")
sns.residplot(data=tips, x="total_bill", y="tip",
lowess=True, line_kws={"color": "red", "lw": 2})
sns.residplot(data=tips, x="total_bill", y="tip",
scatter_kws={"alpha": 0.6})
回归分析注意事项
lmplot 适合快速探索变量间关系,自动分面展示
regplot 适合在定制化图表中嵌入回归线
- 多项式回归(order参数)需谨慎使用,避免过拟合
- 拟合前检查数据的线性假设是否成立
- 残差图是评估模型质量的重要工具
- 置信区间宽度随样本量减小而增大
七、Seaborn主题与调色板
Seaborn提供了强大的主题和配色系统,让用户能够快速定制图表的整体外观风格。
7.1 set_theme 与 set_style
sns.set_theme()
sns.set_style("whitegrid")
sns.set_style("darkgrid")
sns.set_style("white")
sns.set_style("dark")
sns.set_style("ticks")
with sns.axes_style("whitegrid"):
sns.histplot(data=tips, x="total_bill")
sns.set_context("paper")
sns.set_context("notebook")
sns.set_context("talk")
sns.set_context("poster")
sns.set_context("talk", font_scale=1.2,
rc={"lines.linewidth": 2.5})
7.2 set_palette 与 color_palette
Seaborn的调色板系统提供了多种配色方案,适应不同数据类型和可视化需求。
sns.set_palette("deep")
sns.set_palette("pastel")
sns.set_palette("bright")
sns.set_palette("dark")
sns.set_palette("colorblind")
sns.set_palette("Set2")
sns.set_palette("viridis")
sns.set_palette("rocket")
sns.set_palette("Blues")
custom_palette = sns.color_palette("husl", 8)
sns.set_palette(custom_palette)
sns.palplot(sns.color_palette("coolwarm", 7))
my_colors = ["#3498db", "#e74c3c", "#2ecc71", "#f39c12"]
sns.set_palette(my_colors)
调色板选择原则
- 分类数据(离散类别) — 使用
deep, pastel, Set1-3 等分类调色板
- 连续数据(数值渐变) — 使用
viridis, rocket, Blues 等连续调色板
- 发散数据(有零点的正负值) — 使用
coolwarm, RdBu 等发散调色板
- 色觉障碍友好 — 优先使用
viridis 或 colorblind 调色板
7.3 axes_style 与 plotting_context
print(sns.axes_style())
print(sns.plotting_context())
sns.set_style("darkgrid", {
"axes.facecolor": "#f0f0f0",
"axes.edgecolor": "#333333",
"grid.color": "white",
"grid.linestyle": "--"
})
sns.set_theme(
style="whitegrid",
palette="muted",
font="SimHei",
font_scale=1.1,
rc={"figure.figsize": (10, 6)}
)
八、FacetGrid 多子图
FacetGrid是Seaborn构建多子图的核心组件,它根据数据列的值将数据分配到多个子图中,实现分面可视化。这在探索多变量数据时非常有用。
8.1 基本FacetGrid用法
g = sns.FacetGrid(tips, col="time")
g.map(sns.histplot, "total_bill")
g = sns.FacetGrid(tips, col="day", row="sex")
g.map(sns.scatterplot, "total_bill", "tip")
g = sns.FacetGrid(tips, col="day", col_wrap=2)
g.map(sns.histplot, "total_bill")
g = sns.FacetGrid(tips, col="time", hue="sex")
g.map(sns.scatterplot, "total_bill", "tip")
g.add_legend()
8.2 高级FacetGrid配置
g = sns.FacetGrid(
tips,
col="day",
height=4,
aspect=1.2,
sharex=True,
sharey=True,
palette="Set2"
)
g.map(sns.kdeplot, "total_bill", fill=True)
g.set_titles("星期: {col_name}")
g.set_axis_labels("消费金额", "密度")
g.tight_layout()
g = sns.FacetGrid(tips, col="day", row="sex")
g.map(sns.scatterplot, "total_bill", "tip", alpha=0.7)
g.map(sns.regplot, "total_bill", "tip",
scatter=False, color="red")
8.3 使用row和col参数
许多Seaborn高级绘图函数(如 relplot、displot、catplot、lmplot)的 row 和 col 参数内部就是通过FacetGrid实现的。
sns.relplot(
data=tips,
x="total_bill", y="tip",
hue="sex", style="smoker",
col="day", col_wrap=2
)
sns.displot(
data=penguins,
x="flipper_length_mm",
hue="species",
col="island",
kind="kde",
fill=True
)
g = sns.FacetGrid(tips, col="day", height=5, aspect=0.8)
g.map(sns.boxplot, "sex", "total_bill")
g.set_axis_labels("", "Total Bill ($)")
g.set_titles("Day: {col_name}")
g.tight_layout()
FacetGrid最佳实践
- 使用
col_wrap 控制列数,避免子图排布超出页面宽度
- 使用
sharex 和 sharey 控制坐标轴共享,便于比较不同面板
- 使用
set_titles() 自定义子图标题格式
- 使用
set_axis_labels() 统一设置坐标轴标签
- 数据量较小时优先使用
col 而非 row,便于横向比较
- 结合
map() 方法可以为每个面板绘制多种图形
九、实战案例:完整数据分析流程
以下是一个使用Seaborn进行完整探索性数据分析的实战案例,综合运用了本节讲解的多种图表类型和分析方法。
import seaborn as sns
import matplotlib.pyplot as plt
penguins = sns.load_dataset("penguins")
print(penguins.head())
print(penguins.describe())
sns.set_theme(style="whitegrid", palette="muted")
fig, axes = plt.subplots(1, 3, figsize=(15, 5))
sns.histplot(data=penguins, x="bill_length_mm", kde=True, ax=axes[0])
sns.histplot(data=penguins, x="bill_depth_mm", kde=True, ax=axes[1])
sns.histplot(data=penguins, x="flipper_length_mm", kde=True, ax=axes[2])
plt.tight_layout()
plt.show()
g = sns.relplot(
data=penguins,
x="bill_length_mm", y="bill_depth_mm",
hue="species", style="species",
size="body_mass_g", sizes=(30, 200),
col="island"
)
g.set_titles("{col_name}")
plt.show()
fig, axes = plt.subplots(2, 2, figsize=(14, 10))
sns.boxplot(data=penguins, x="species", y="bill_length_mm", ax=axes[0, 0])
sns.violinplot(data=penguins, x="species", y="flipper_length_mm", ax=axes[0, 1])
sns.barplot(data=penguins, x="species", y="body_mass_g", ax=axes[1, 0])
sns.countplot(data=penguins, x="species", hue="sex", ax=axes[1, 1])
plt.tight_layout()
plt.show()
sns.lmplot(
data=penguins,
x="bill_length_mm", y="bill_depth_mm",
hue="species", col="species",
height=4, aspect=1
)
plt.show()
plt.figure(figsize=(8, 6))
corr = penguins.select_dtypes(include=["number"]).corr()
sns.heatmap(corr, annot=True, cmap="coolwarm",
fmt=".2f", linewidths=0.5)
plt.title("企鹅数据集特征相关性矩阵")
plt.show()
十、常用图表速查表
| 图表类型 |
函数 |
数据要求 |
用途 |
| 直方图 |
histplot |
1个连续变量 |
展示数据分布形态 |
| 核密度图 |
kdeplot |
1-2个连续变量 |
平滑分布估计 |
| ECDF图 |
ecdfplot |
1个连续变量 |
累积分布比例 |
| 散点图 |
scatterplot |
2个连续变量 |
变量间关系 |
| 线图 |
lineplot |
1连续+1有序 |
趋势变化 |
| 箱线图 |
boxplot |
1分类+1连续 |
分组分布与异常值 |
| 小提琴图 |
violinplot |
1分类+1连续 |
分组分布形状 |
| 蜂群图 |
swarmplot |
1分类+1连续 |
展示所有数据点 |
| 柱状图 |
barplot |
1分类+1连续 |
均值比较 |
| 计数图 |
countplot |
1个分类变量 |
数量统计 |
| 回归图 |
lmplot/regplot |
2个连续变量 |
回归拟合 |
| 热力图 |
heatmap |
矩阵数据 |
相关性/热力分布 |
| 分面子图 |
FacetGrid |
多变量数据 |
多面板对比 |
十一、核心要点总结
Seaborn学习核心要点
- 设计哲学 — Seaborn以"美观且信息丰富"为核心目标,基于Matplotlib构建,提供更高层次的统计可视化接口
- 分布可视化 —
displot 统一接口支持 histogram/KDE/ECDF/rug 四种分布图,适应不同分析需求
- 关系可视化 —
relplot 统一管理散点图和线图,通过 hue/style/size 实现多维语义映射
- 分类可视化 —
catplot 提供9种分类图表,从小提琴图到蜂群图覆盖所有比较需求
- 回归分析 —
lmplot 和 regplot 支持线性/多项式回归,残差图辅助模型评估
- 主题系统 —
set_theme/set_style/set_palette 三级样式控制,实现图表的全局定制
- 多子图系统 — FacetGrid 和 col/row 参数天然支持分面分析,适合探索多变量数据
- 数据集集成 — 内置 tips/penguins/iris/fmri 等经典数据集,便于学习和演示
- 与Pandas深度集成 — 直接以 DataFrame 列名为参数,自动处理缺失值和分类数据
- 最佳实践 — 先使用 relplot/catplot/displot 等高级接口探索数据,再使用底层接口定制细节
十二、进一步学习与实践
学习路径建议
- 基础入门 — 掌握 displot / relplot / catplot 三大高级接口,熟悉基础参数
- 主题定制 — 学习 set_theme / set_style / set_palette 系统,构建个人图表风格
- 分面进阶 — 深入学习 FacetGrid 和 PairGrid,掌握多子图管理
- 回归与统计 — 掌握 lmplot / regplot 的统计含义和参数配置
- Matplotlib结合 — 学习用Matplotlib对Seaborn图表进行细节微调
- 实战项目 — 使用真实数据集完成完整的探索性数据分析流程
Seaborn版本演进
- v0.11 (2021) — 引入 displot / relplot 统一接口,重写底层架构
- v0.12 (2022) — 改进主题系统,增强对象接口
- v0.13 (2024) — 优化性能,改进配色方案,增强文档
- 建议始终使用最新版本,以获得最佳功能和性能
常见误区提醒
- Seaborn 不能替代 Matplotlib,而是补充和增强
- Seaborn的默认主题在某些出版场景下仍需手动调整
displot (v0.11+) 和 distplot (已弃用) 是不同的函数,不要混用
- 数据量大时(>10万条),考虑使用
histplot 而非 kdeplot 以提高性能
- FacetGrid在子图数量过多时(>20)会严重影响可视化效果
十三、完整参考资源
- 官方文档 — seaborn.pydata.org 提供完整API参考和示例画廊
- Seaborn示例画廊 — 官方示例页面展示了所有图表类型的最佳实践代码
- API速查 —
sns.* 函数列表可通过 dir(sns) 查看
- 调色板选择器 —
sns.color_palette() 配合 sns.palplot() 预览配色效果
- 数据集管理 —
sns.get_dataset_names() 列出所有可用内置数据集