github star gitee star atomgit star PyPI Downloads AI 编程 AI 交流群

大家好,我是正在实战各种AI项目的程序员晚枫。

今天学习Seaborn,这是基于Matplotlib的统计数据可视化库。

如果说Matplotlib是"画笔",那Seaborn就是"模板"。用更少的代码,就能做出专业级的统计图表。


为什么选择Seaborn?

Matplotlib vs Seaborn

特性MatplotlibSeaborn
代码量较多简洁
默认样式朴素美观
统计功能需手动计算内置统计
适用场景精细控制快速探索

最佳实践:日常分析用Seaborn快速出图,汇报时再用Matplotlib精细调整。


安装与导入

1
pip install seaborn
1
2
3
4
5
6
7
8
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

# 设置样式
sns.set_style('whitegrid') # whitegrid, darkgrid, white, dark, ticks
sns.set_palette('husl') # 配色方案

1. 分布图(Distribution Plot)

直方图 + KDE

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 生成数据
data = np.random.normal(100, 15, 1000)

# 方式1:distplot(旧版,已弃用)
# sns.distplot(data)

# 方式2:histplot(推荐)
sns.histplot(data, kde=True, bins=30, color='skyblue')
plt.title('数据分布')
plt.show()

# 方式3:kdeplot(仅密度曲线)
sns.kdeplot(data, fill=True, color='coral')
plt.title('密度分布')
plt.show()

箱线图(Box Plot)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 准备数据
df = pd.DataFrame({
'部门': ['技术']*50 + ['销售']*50 + ['人事']*50,
'薪资': np.concatenate([
np.random.normal(15000, 3000, 50),
np.random.normal(12000, 4000, 50),
np.random.normal(10000, 2000, 50)
])
})

# 箱线图
sns.boxplot(data=df, x='部门', y='薪资', palette='Set2')
plt.title('各部门薪资分布')
plt.show()

# 小提琴图(箱线图升级版)
sns.violinplot(data=df, x='部门', y='薪资', palette='Set3')
plt.title('各部门薪资分布(含密度)')
plt.show()

2. 散点图与回归

基础散点图

1
2
3
4
5
6
7
8
9
10
11
12
13
# 生成数据
np.random.seed(42)
df = pd.DataFrame({
'广告投入': np.random.randint(50, 200, 100),
'销售额': np.random.randint(100, 500, 100)
})
df['销售额'] = df['广告投入'] * 2 + np.random.normal(0, 30, 100)

# 散点图
sns.scatterplot(data=df, x='广告投入', y='销售额',
size='销售额', sizes=(20, 200), alpha=0.6)
plt.title('广告投入 vs 销售额')
plt.show()

带回归线的散点图

1
2
3
4
5
6
7
8
9
10
# 自动拟合回归线
sns.regplot(data=df, x='广告投入', y='销售额',
scatter_kws={'alpha':0.5},
line_kws={'color':'red'})
plt.title('相关性分析')
plt.show()

# 多项式回归
sns.regplot(data=df, x='广告投入', y='销售额', order=2)
plt.show()

3. 分类数据可视化

柱状图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
df = pd.DataFrame({
'月份': ['1月', '2月', '3月', '4月', '5月'] * 3,
'产品': ['A']*5 + ['B']*5 + ['C']*5,
'销量': [120, 150, 180, 140, 200] +
[80, 90, 110, 130, 150] +
[60, 70, 85, 95, 110]
})

# 分组柱状图
sns.barplot(data=df, x='月份', y='销量', hue='产品', palette='viridis')
plt.title('各产品月度销量')
plt.legend(title='产品')
plt.show()

# 水平柱状图
sns.barplot(data=df, y='月份', x='销量', hue='产品', orient='h')
plt.show()

计数图

1
2
3
4
5
6
7
8
9
# 自动生成计数
df = pd.DataFrame({
'类别': np.random.choice(['A', 'B', 'C'], 200),
'组别': np.random.choice(['X', 'Y'], 200)
})

sns.countplot(data=df, x='类别', hue='组别', palette='pastel')
plt.title('各类别数量统计')
plt.show()

4. 热力图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 相关性矩阵
np.random.seed(42)
df = pd.DataFrame(np.random.randn(100, 5), columns=['A', 'B', 'C', 'D', 'E'])
corr = df.corr()

# 绘制热力图
plt.figure(figsize=(8, 6))
sns.heatmap(corr, annot=True, fmt='.2f', cmap='RdYlBu_r',
center=0, square=True, linewidths=0.5)
plt.title('变量相关性热力图')
plt.show()

# 带聚类的热力图
sns.clustermap(corr, annot=True, cmap='coolwarm', center=0)
plt.show()

5. 多变量关系图

Pairplot(成对关系图)

1
2
3
4
5
6
7
8
9
10
11
# Iris数据集
iris = sns.load_dataset('iris')

# 所有数值变量的两两关系
sns.pairplot(iris, hue='species', palette='Set2', diag_kind='kde')
plt.suptitle('鸢尾花数据集特征关系', y=1.02)
plt.show()

# 只选部分变量
sns.pairplot(iris, vars=['sepal_length', 'sepal_width'], hue='species')
plt.show()

Jointplot(联合分布图)

1
2
3
4
5
6
7
8
9
# 两个变量的联合分布
sns.jointplot(data=iris, x='sepal_length', y='sepal_width',
hue='species', kind='scatter')
plt.show()

# 带核密度估计
sns.jointplot(data=iris, x='sepal_length', y='petal_length',
kind='kde', fill=True)
plt.show()

6. 分面网格(FacetGrid)

1
2
3
4
5
6
7
8
9
10
11
12
13
# 创建复杂的多子图布局
df = pd.DataFrame({
'x': np.random.randn(200),
'y': np.random.randn(200),
'category': np.random.choice(['A', 'B'], 200),
'group': np.random.choice(['X', 'Y'], 200)
})

g = sns.FacetGrid(df, col='category', row='group', height=3, aspect=1.2)
g.map(sns.scatterplot, 'x', 'y', alpha=0.6)
g.add_legend()
plt.suptitle('分面散点图', y=1.02)
plt.show()

7. 主题与样式定制

1
2
3
4
5
6
7
8
9
10
# 预设主题
sns.set_theme(style='darkgrid', palette='muted', font_scale=1.2)

# 自定义颜色
custom_palette = sns.color_palette("coolwarm", 7)
sns.set_palette(custom_palette)

# 中文显示
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

实战:完整的数据探索报告

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

# 生成销售数据
np.random.seed(42)
df = pd.DataFrame({
'日期': pd.date_range('2024-01-01', periods=365, freq='D'),
'销售额': np.random.normal(5000, 1000, 365) + np.linspace(0, 2000, 365),
'客户数': np.random.poisson(50, 365),
'客单价': np.random.normal(100, 20, 365),
'地区': np.random.choice(['华北', '华东', '华南', '西南'], 365),
'渠道': np.random.choice(['线上', '线下'], 365, p=[0.6, 0.4])
})

# 创建大图
fig = plt.figure(figsize=(16, 12))

# 1. 销售额趋势
ax1 = plt.subplot(2, 3, 1)
df_monthly = df.groupby(df['日期'].dt.to_period('M'))['销售额'].sum()
df_monthly.plot(kind='line', ax=ax1, marker='o')
ax1.set_title('月度销售额趋势')
ax1.grid(True, alpha=0.3)

# 2. 地区对比
ax2 = plt.subplot(2, 3, 2)
sns.boxplot(data=df, x='地区', y='销售额', ax=ax2, palette='Set2')
ax2.set_title('各地区销售额分布')

# 3. 渠道占比
ax3 = plt.subplot(2, 3, 3)
channel_sales = df.groupby('渠道')['销售额'].sum()
ax3.pie(channel_sales, labels=channel_sales.index, autopct='%1.1f%%',
colors=['skyblue', 'lightcoral'])
ax3.set_title('销售渠道占比')

# 4. 销售额分布
ax4 = plt.subplot(2, 3, 4)
sns.histplot(df['销售额'], kde=True, ax=ax4, color='green')
ax4.set_title('销售额分布')

# 5. 相关性热力图
ax5 = plt.subplot(2, 3, 5)
corr_data = df[['销售额', '客户数', '客单价']].corr()
sns.heatmap(corr_data, annot=True, cmap='RdYlBu_r', ax=ax5, center=0)
ax5.set_title('指标相关性')

# 6. 散点图
ax6 = plt.subplot(2, 3, 6)
sns.scatterplot(data=df, x='客户数', y='销售额', hue='渠道', ax=ax6, alpha=0.6)
ax6.set_title('客户数 vs 销售额')

plt.suptitle('2024年销售数据分析报告', fontsize=16, fontweight='bold', y=0.98)
plt.tight_layout(rect=[0, 0, 1, 0.96])
plt.savefig('sales_analysis_report.png', dpi=300, bbox_inches='tight')
plt.show()

print("分析报告已生成!")

性能对比:Seaborn vs Matplotlib

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

df = pd.DataFrame({
'category': np.random.choice(['A', 'B', 'C'], 1000),
'value': np.random.randn(1000)
})

# Matplotlib箱线图:需要手动计算
fig, ax = plt.subplots()
data_by_group = [df[df['category']==c]['value'].values for c in ['A', 'B', 'C']]
ax.boxplot(data_by_group, labels=['A', 'B', 'C'])

# Seaborn箱线图:一行搞定,还自动加了颜色和图例
sns.boxplot(data=df, x='category', y='value')

进阶用法

分面图(FacetGrid)

1
2
3
4
# 按维度自动拆分图表
g = sns.FacetGrid(df, col='city', row='year', height=3, aspect=1.2)
g.map(sns.histplot, 'value', bins=20)
g.add_legend()

联合分布图

1
2
3
# 同时看两个变量的分布和相关性
sns.jointplot(data=df, x='income', y='spending',
hue='segment', kind='kde') # 或 kind='scatter', 'hex', 'reg'

热力图高级用法

1
2
3
4
5
6
# 相关性热力图
corr = df.corr()
mask = np.triu(np.ones_like(corr, dtype=bool)) # 只显示下半三角
sns.heatmap(corr, mask=mask, annot=True, fmt='.2f',
cmap='RdYlBu_r', center=0,
square=True, linewidths=0.5)

避坑指南

❌ 坑1:Seaborn中文显示

1
2
3
4
# Seaborn底层是Matplotlib,同样需要设置中文字体
sns.set(font='Arial Unicode MS') # Mac
# 或
plt.rcParams['font.sans-serif'] = ['SimHei'] # Windows

❌ 坑2:大样本散点图卡顿

1
2
3
4
5
6
7
8
9
10
# 10万点散点图很卡
# 解决方案1:降低透明度
sns.scatterplot(data=df, x='x', y='y', alpha=0.1)

# 解决方案2:用hexbin
sns.jointplot(data=df, x='x', y='y', kind='hex')

# 解决方案3:采样
sample = df.sample(5000)
sns.scatterplot(data=sample, x='x', y='y')

实战案例:电商用户行为可视化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

plt.rcParams['font.sans-serif'] = ['Arial Unicode MS']
plt.rcParams['axes.unicode_minus'] = False

np.random.seed(42)
n = 5000
df = pd.DataFrame({
'age': np.random.randint(18, 65, n),
'income': np.random.exponential(10000, n).clip(3000, 50000),
'spending': np.random.exponential(5000, n).clip(100, 30000),
'segment': np.random.choice(['高价值', '潜力', '普通', '流失'], n, p=[0.1, 0.2, 0.5, 0.2]),
'city': np.random.choice(['北京', '上海', '广州', '深圳'], n)
})

fig, axes = plt.subplots(2, 2, figsize=(14, 12))

# 1. 收入分布
sns.histplot(data=df, x='income', hue='segment', kde=True, ax=axes[0,0])
axes[0,0].set_title('各客群收入分布')

# 2. 收入vs消费
sns.scatterplot(data=df, x='income', y='spending', hue='segment',
alpha=0.5, ax=axes[0,1])
axes[0,1].set_title('收入与消费关系')

# 3. 各城市客群分布
sns.countplot(data=df, x='city', hue='segment', ax=axes[1,0])
axes[1,0].set_title('各城市客群分布')

# 4. 年龄vs消费箱线图
sns.boxplot(data=df, x='segment', y='age', ax=axes[1,1])
axes[1,1].set_title('各客群年龄分布')

plt.tight_layout()
plt.savefig('user_analysis.png', dpi=150)

Seaborn配色方案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 内置主题
sns.set_theme(style='whitegrid') # 白色网格
sns.set_theme(style='darkgrid') # 深色网格
sns.set_theme(style='white') # 白色
sns.set_theme(style='dark') # 深色
sns.set_theme(style='ticks') # 带刻度

# 调色板
palette = sns.color_palette('Set2') # 分类色板
palette = sns.color_palette('Blues') # 连续色板
palette = sns.color_palette('RdBu') # 发散色板
palette = sns.color_palette('husl', 8) # 均匀色相

# 自定义调色板
my_palette = ['#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4']
sns.set_palette(my_palette)

Seaborn + Pandas快速探索

1
2
3
4
5
6
7
8
9
10
# 一行代码探索性分析
# 数值列两两关系
sns.pairplot(df, hue='category', diag_kind='kde')

# 单列分布 + 分组
sns.displot(data=df, x='value', hue='group', kind='kde', fill=True)

# 多维度关系
sns.relplot(data=df, x='x', y='y', hue='category', size='value',
col='group', row='year', height=3)

Seaborn图表选择指南

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
你想展示什么?
├── 单变量分布
│ ├── 直方图:sns.histplot()
│ ├── 核密度图:sns.kdeplot()
│ ├── 箱线图:sns.boxplot()
│ └── 小提琴图:sns.violinplot()
├── 两变量关系
│ ├── 散点图:sns.scatterplot()
│ ├── 回归图:sns.regplot()
│ └── 联合分布:sns.jointplot()
├── 分类对比
│ ├── 柱状图:sns.barplot()
│ ├── 计数图:sns.countplot()
│ └── 点图:sns.pointplot()
├── 多变量关系
│ ├── 配对图:sns.pairplot()
│ ├── 热力图:sns.heatmap()
│ └── 分面图:sns.FacetGrid()
└── 时间趋势
└── 折线图:sns.lineplot()

Seaborn一键探索数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 一行代码完成探索性分析
import seaborn as sns

# 加载示例数据
df = sns.load_dataset('tips')

# 数值变量关系
sns.pairplot(df, hue='time', diag_kind='kde')

# 分类变量vs数值变量
sns.catplot(data=df, x='day', y='total_bill', hue='sex', kind='box', height=5, aspect=1.5)

# 多维度分析
g = sns.FacetGrid(df, col='time', row='smoker', height=3)
g.map(sns.histplot, 'total_bill')

Seaborn vs Matplotlib选择指南

1
2
3
4
5
6
7
8
9
你的需求是什么?
├── 快速探索数据分布 → Seaborn(一行代码出图)
├── 精细控制图表细节 → Matplotlib(灵活但代码多)
├── 统计分析可视化 → Seaborn(内置统计功能)
├── 自定义复杂布局 → Matplotlib(手动控制)
├── 美观默认样式 → Seaborn(开箱即用)
└── 品牌定制风格 → Matplotlib(完全自定义)

推荐:先用Seaborn快速探索,再用Matplotlib精细调整

Seaborn常用模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import seaborn as sns
import matplotlib.pyplot as plt

# 设置风格
sns.set_theme(style='whitegrid', font='Arial Unicode MS')

# 模板1:分类变量vs数值变量
fig, axes = plt.subplots(1, 3, figsize=(18, 5))
sns.barplot(data=df, x='category', y='value', ax=axes[0]) # 均值+置信区间
sns.boxplot(data=df, x='category', y='value', ax=axes[1]) # 分布概况
sns.violinplot(data=df, x='category', y='value', ax=axes[2]) # 分布+密度

# 模板2:两变量关系
fig, axes = plt.subplots(1, 3, figsize=(18, 5))
sns.scatterplot(data=df, x='x', y='y', hue='group', ax=axes[0])
sns.regplot(data=df, x='x', y='y', ax=axes[1]) # 带回归线
sns.kdeplot(data=df, x='x', y='y', fill=True, ax=axes[2]) # 等高线

# 模板3:多变量关系
sns.pairplot(df, hue='category', height=2.5) # 配对图
sns.heatmap(df.corr(), annot=True, cmap='RdYlBu_r') # 相关性

下节预告

下一课我们将学习Pandas内置绘图,用最简单的方式快速出图。

👉 继续阅读:Pandas内置绘图-最简捷的可视化方式


💬 加入学习交流群

扫码加入Python学习交流群,和数千名同学一起进步:

👉 点击加入交流群

群里不定期分享:

  • 数据分析实战案例
  • Python学习资料
  • 求职面试经验
  • 行业最新动态

推荐:AI Python数据分析实战营

🎁 限时福利:送《利用Python进行数据分析》实体书

👉 点击了解详情


课程导航

上一篇: Matplotlib进阶-专业图表美化技巧

下一篇: Pandas内置绘图-最简捷的可视化方式


PS:Seaborn让统计可视化变得简单。日常分析用它,效率提升不止一倍。



📚 推荐教材

主教材《Excel+Python 飞速搞定数据分析与处理(图灵出品)》

💬 联系我

平台账号/链接
微信扫码加好友
微博@程序员晚枫
知乎@程序员晚枫
抖音@程序员晚枫
小红书@程序员晚枫
B 站Python 自动化办公社区

主营业务:AI 编程培训、企业内训、技术咨询

🎓 AI 编程实战课程

想系统学习 AI 编程?程序员晚枫的 AI 编程实战课 帮你从零上手!