跳到主要内容

Seaborn 统计可视化

问题

Seaborn 相比 Matplotlib 有什么优势?如何用 Seaborn 做统计可视化和 EDA?

答案

Seaborn vs Matplotlib

维度MatplotlibSeaborn
定位通用绑图库统计可视化库
默认样式朴素美观
数据输入数组DataFrame 列名
统计功能自动计算均值、CI
分面支持需手动FacetGrid
学习曲线
一句话总结

Seaborn = Matplotlib + 更好的默认样式 + 统计计算 + DataFrame 友好

分布图

分布可视化
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

np.random.seed(42)
df = pd.DataFrame({
'age': np.concatenate([np.random.normal(28, 5, 500),
np.random.normal(35, 8, 500)]),
'group': ['新用户'] * 500 + ['老用户'] * 500,
'spend': np.random.lognormal(4, 1, 1000)
})

fig, axes = plt.subplots(1, 3, figsize=(15, 5))

# 1. 直方图 + KDE
sns.histplot(data=df, x='age', hue='group', kde=True, ax=axes[0])
axes[0].set_title('年龄分布')

# 2. 箱线图
sns.boxplot(data=df, x='group', y='spend', ax=axes[1])
axes[1].set_title('消费分布')

# 3. 小提琴图(箱线图 + 密度图)
sns.violinplot(data=df, x='group', y='age', inner='quartile', ax=axes[2])
axes[2].set_title('年龄分布(小提琴图)')

plt.tight_layout()
plt.show()

关系图

关系可视化
import seaborn as sns
import matplotlib.pyplot as plt

# 使用内置数据集
tips = sns.load_dataset('tips')

fig, axes = plt.subplots(1, 3, figsize=(15, 5))

# 1. 散点图 + 回归线
sns.regplot(data=tips, x='total_bill', y='tip', ax=axes[0],
scatter_kws={'alpha': 0.5})
axes[0].set_title('账单金额 vs 小费')

# 2. 分组散点图
sns.scatterplot(data=tips, x='total_bill', y='tip',
hue='time', style='smoker', ax=axes[1])
axes[1].set_title('按时间和吸烟状态分组')

# 3. 热力图(相关系数矩阵)
corr = tips[['total_bill', 'tip', 'size']].corr()
sns.heatmap(corr, annot=True, cmap='RdBu_r', center=0,
vmin=-1, vmax=1, ax=axes[2])
axes[2].set_title('相关系数矩阵')

plt.tight_layout()
plt.show()

分类对比图

分类数据可视化
import seaborn as sns
import matplotlib.pyplot as plt

tips = sns.load_dataset('tips')

fig, axes = plt.subplots(1, 3, figsize=(15, 5))

# 1. 柱状图(自动计算均值 + CI)
sns.barplot(data=tips, x='day', y='total_bill', hue='sex',
errorbar='ci', ax=axes[0])
axes[0].set_title('各天平均账单')

# 2. 计数图
sns.countplot(data=tips, x='day', hue='time', ax=axes[1])
axes[1].set_title('各天就餐人数')

# 3. 带状图(看每个数据点)
sns.stripplot(data=tips, x='day', y='total_bill', hue='time',
dodge=True, alpha=0.5, ax=axes[2])
axes[2].set_title('各天账单详情')

plt.tight_layout()
plt.show()

FacetGrid 分面图

分面图——按维度拆分
import seaborn as sns

tips = sns.load_dataset('tips')

# 按 time(行) × smoker(列) 创建分面网格
g = sns.FacetGrid(tips, row='time', col='smoker',
height=4, aspect=1.2)
g.map_dataframe(sns.scatterplot, x='total_bill', y='tip')
g.add_legend()
g.set_titles(row_template='{row_name}', col_template='{col_name}')
plt.show()

# 更简洁的写法:relplot / catplot / displot
sns.relplot(
data=tips,
x='total_bill', y='tip',
col='time', row='smoker',
kind='scatter', height=4
)
plt.show()

主题与调色板

Seaborn 主题设置
import seaborn as sns

# 内置主题:darkgrid, whitegrid, dark, white, ticks
sns.set_theme(style='whitegrid', font_scale=1.2)

# 调色板
# 定性:'Set2', 'Paired', 'tab10'
# 连续:'Blues', 'viridis', 'YlOrRd'
# 发散:'RdBu', 'coolwarm'

sns.set_palette('Set2')

# 自定义调色板
custom = ['#2196F3', '#4CAF50', '#FF9800', '#F44336']
sns.set_palette(custom)

常见面试问题

Q1: EDA 阶段通常画哪些图?

答案(标准 EDA 流程):

  1. 分布histplot / kdeplot 查看各数值列分布(是否偏态、有无异常值)
  2. 相关性heatmap 相关系数矩阵,快速发现变量关系
  3. 分组对比boxplot / barplot 按分类维度对比数值
  4. 缺失值heatmap 缺失值矩阵(msno 库)
  5. 散点图:重要变量对之间的 scatterplot

Q2: 箱线图怎么看?

答案

  • 中位线:中间的横线 = 中位数(Q2)
  • 箱体:Q1(25%)到 Q3(75%),箱体宽度 = IQR
  • 须线:延伸到 Q1-1.5×IQR 和 Q3+1.5×IQR 范围内
  • 离群点:超出须线的点 = 异常值
  • 比较多组箱线图时关注:中位数差异、分布宽窄、异常值多少

Q3: 什么时候用小提琴图替代箱线图?

答案

  • 箱线图:简洁,看中位数和四分位数够用
  • 小提琴图:能看到完整的分布形状(双峰、偏态等)
  • 数据有多峰分布时小提琴图信息更丰富
  • 汇报给非技术人员时箱线图更易理解

相关链接