行莫
行莫
发布于 2025-11-22 / 2 阅读
0
0

Seaborn 图形绘制详解

Seaborn 图形绘制详解

引言

Seaborn 是一个基于 Matplotlib 的 Python 数据可视化库,专注于统计图表绘制。它提供了更高级的接口、更美观的默认样式,以及更强大的统计功能。Seaborn 特别适合数据科学和统计分析场景,能够轻松创建信息丰富且美观的可视化图表。

本教程将系统地讲解 Seaborn 的图形绘制功能,每个概念都配有可直接运行的代码示例。

学习建议:

  • 阅读每个示例代码
  • 复制代码到 Python 解释器或 IDE 中运行
  • 尝试修改代码,观察结果变化
  • 完成每个部分的练习

前置要求:

  • 基本了解 Python、NumPy、Pandas
  • 安装了 seaborn、matplotlib、pandas、numpy 库

安装依赖:

pip install seaborn matplotlib pandas numpy

第一部分:Seaborn 基础

1. 什么是 Seaborn?

Seaborn 的主要特点:

  • 美观的默认样式:提供多种内置主题和调色板
  • 统计功能集成:内置统计估计和误差条
  • 高级抽象:简化复杂图表的创建
  • 与 Pandas 集成:直接使用 DataFrame 数据
  • 多面板图表:轻松创建分面图

2. 导入和基本设置

import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

# 设置中文字体(解决中文显示问题)
plt.rcParams['font.sans-serif'] = ['SimHei']  # Windows
# plt.rcParams['font.sans-serif'] = ['Arial Unicode MS']  # Mac
plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题

# 设置 Seaborn 样式
sns.set_style("whitegrid")  # 可选:darkgrid, whitegrid, dark, white, ticks
sns.set_palette("husl")     # 设置调色板

# 设置图表大小
plt.rcParams['figure.figsize'] = (10, 6)

# 创建示例数据
np.random.seed(42)
df = pd.DataFrame({
    'x': np.random.randn(100),
    'y': np.random.randn(100),
    'category': np.random.choice(['A', 'B', 'C'], 100)
})

print(df.head())

运行测试:

# 复制以下代码到 Python 解释器运行
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

# 设置样式
sns.set_style("whitegrid")
sns.set_palette("husl")

# 创建简单测试数据
data = {
    '类别': ['A', 'B', 'C', 'D'],
    '数值': [10, 20, 15, 25]
}
df = pd.DataFrame(data)

# 绘制简单柱状图
sns.barplot(data=df, x='类别', y='数值')
plt.title('测试图表')
plt.show()

3. Seaborn 样式和主题

Seaborn 提供了多种内置样式和调色板。

import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np

# 可用的样式
styles = ['darkgrid', 'whitegrid', 'dark', 'white', 'ticks']

# 演示不同样式
fig, axes = plt.subplots(1, 5, figsize=(20, 4))
for idx, style in enumerate(styles):
    sns.set_style(style)
    x = np.linspace(0, 10, 100)
    y = np.sin(x)
    axes[idx].plot(x, y)
    axes[idx].set_title(style)
    axes[idx].grid(True)

plt.tight_layout()
plt.show()

# 设置回默认样式
sns.set_style("whitegrid")

运行测试:

# 复制以下代码到 Python 解释器运行
import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np

# 设置样式
sns.set_style("whitegrid")

# 查看可用的调色板
print("内置调色板:")
print(sns.color_palette("husl", 8))
print(sns.color_palette("Set2", 8))

# 设置调色板
sns.set_palette("Set2")

# 创建示例图表
data = np.random.randn(100)
sns.histplot(data, kde=True)
plt.title('使用 Set2 调色板')
plt.show()

第二部分:分布图(Distribution Plots)

1. 直方图(histplot)

histplot 用于绘制单变量分布。

import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

# 设置样式
sns.set_style("whitegrid")

# 创建数据
np.random.seed(42)
data = np.random.normal(100, 15, 1000)
df = pd.DataFrame({'数值': data})

# 基本直方图
sns.histplot(data=df, x='数值', bins=30)
plt.title('数据分布直方图')
plt.xlabel('数值')
plt.ylabel('频数')
plt.show()

运行测试:

# 复制以下代码到 Python 解释器运行
import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np

sns.set_style("whitegrid")

# 创建正态分布数据
np.random.seed(42)
data = np.random.normal(0, 1, 1000)

# 绘制直方图,添加密度曲线
sns.histplot(data, bins=30, kde=True, stat='density')
plt.title('正态分布直方图(带密度曲线)')
plt.xlabel('值')
plt.ylabel('密度')
plt.show()

分组直方图:

import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

sns.set_style("whitegrid")

# 创建分组数据
np.random.seed(42)
df = pd.DataFrame({
    '数值': np.concatenate([
        np.random.normal(50, 10, 500),
        np.random.normal(70, 15, 500)
    ]),
    '组别': ['组A'] * 500 + ['组B'] * 500
})

# 分组直方图
sns.histplot(data=df, x='数值', hue='组别', bins=30, alpha=0.7)
plt.title('分组直方图')
plt.xlabel('数值')
plt.ylabel('频数')
plt.legend()
plt.show()

运行测试:

# 复制以下代码到 Python 解释器运行
import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

sns.set_style("whitegrid")

# 创建学生成绩数据
np.random.seed(42)
df = pd.DataFrame({
    '成绩': np.random.normal(75, 10, 200),
    '班级': np.random.choice(['一班', '二班', '三班'], 200)
})

# 堆叠直方图
sns.histplot(data=df, x='成绩', hue='班级', multiple='stack', bins=20)
plt.title('各班级成绩分布(堆叠)')
plt.xlabel('成绩')
plt.ylabel('学生数')
plt.show()

2. 核密度估计图(kdeplot)

KDE 图展示数据的概率密度分布。

import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

sns.set_style("whitegrid")

# 创建数据
np.random.seed(42)
data1 = np.random.normal(0, 1, 1000)
data2 = np.random.normal(2, 1.5, 1000)

# 绘制 KDE 图
sns.kdeplot(data=data1, label='分布1', fill=True)
sns.kdeplot(data=data2, label='分布2', fill=True)
plt.title('核密度估计图')
plt.xlabel('值')
plt.ylabel('密度')
plt.legend()
plt.show()

运行测试:

# 复制以下代码到 Python 解释器运行
import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

sns.set_style("whitegrid")

# 创建多组数据
np.random.seed(42)
df = pd.DataFrame({
    '值': np.concatenate([
        np.random.normal(50, 10, 500),
        np.random.normal(70, 15, 500),
        np.random.normal(60, 12, 500)
    ]),
    '类别': ['A'] * 500 + ['B'] * 500 + ['C'] * 500
})

# 分组 KDE 图
sns.kdeplot(data=df, x='值', hue='类别', fill=True, alpha=0.6)
plt.title('多组数据密度分布')
plt.xlabel('值')
plt.ylabel('密度')
plt.show()

3. 分布图(displot)

displot 是更灵活的分布图函数,可以创建多种分布可视化。

import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np

sns.set_style("whitegrid")

# 创建数据
np.random.seed(42)
data = np.random.normal(100, 15, 1000)

# 使用 displot 创建直方图
sns.displot(data, kind='hist', bins=30, kde=True)
plt.title('使用 displot 创建的分布图')
plt.show()

运行测试:

# 复制以下代码到 Python 解释器运行
import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

sns.set_style("whitegrid")

# 创建分组数据
np.random.seed(42)
df = pd.DataFrame({
    '数值': np.random.normal(50, 10, 600),
    '组别': np.random.choice(['组A', '组B', '组C'], 600)
})

# 创建分面分布图
sns.displot(data=df, x='数值', hue='组别', kind='kde', fill=True)
plt.title('分组密度分布图')
plt.show()

4. 联合分布图(jointplot)

jointplot 用于展示两个变量的联合分布。

import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

sns.set_style("whitegrid")

# 创建相关数据
np.random.seed(42)
x = np.random.randn(500)
y = 2 * x + np.random.randn(500) * 0.5
df = pd.DataFrame({'X': x, 'Y': y})

# 基本联合分布图
sns.jointplot(data=df, x='X', y='Y', kind='scatter')
plt.suptitle('联合分布图(散点图)', y=1.02)
plt.show()

运行测试:

# 复制以下代码到 Python 解释器运行
import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

sns.set_style("whitegrid")

# 创建数据
np.random.seed(42)
df = pd.DataFrame({
    '广告投入': np.random.uniform(1000, 10000, 200),
    '销售额': np.random.uniform(5000, 50000, 200)
})

# 带回归线的联合分布图
sns.jointplot(data=df, x='广告投入', y='销售额', kind='reg')
plt.suptitle('广告投入与销售额关系', y=1.02)
plt.show()

不同类型的联合分布图:

import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

sns.set_style("whitegrid")

np.random.seed(42)
df = pd.DataFrame({
    'X': np.random.randn(300),
    'Y': np.random.randn(300)
})

# 六边形图(适合大数据集)
sns.jointplot(data=df, x='X', y='Y', kind='hex')
plt.suptitle('六边形联合分布图', y=1.02)
plt.show()

# KDE 联合分布图
sns.jointplot(data=df, x='X', y='Y', kind='kde', fill=True)
plt.suptitle('KDE 联合分布图', y=1.02)
plt.show()

运行测试:

# 复制以下代码到 Python 解释器运行
import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

sns.set_style("whitegrid")

# 创建学生数据
np.random.seed(42)
df = pd.DataFrame({
    '数学': np.random.normal(75, 10, 200),
    '英语': np.random.normal(80, 12, 200)
})

# 带直方图的联合分布图
sns.jointplot(data=df, x='数学', y='英语', kind='hist', bins=20)
plt.suptitle('数学与英语成绩联合分布', y=1.02)
plt.show()

5. 配对图(pairplot)

pairplot 用于展示数据集中多个变量之间的成对关系。

import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

sns.set_style("whitegrid")

# 创建多变量数据
np.random.seed(42)
df = pd.DataFrame({
    '变量A': np.random.randn(100),
    '变量B': np.random.randn(100),
    '变量C': np.random.randn(100),
    '类别': np.random.choice(['X', 'Y'], 100)
})

# 基本配对图
sns.pairplot(df, hue='类别')
plt.suptitle('配对图', y=1.02)
plt.show()

运行测试:

# 复制以下代码到 Python 解释器运行
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

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

# 创建配对图
sns.pairplot(iris, hue='species', diag_kind='kde')
plt.suptitle('鸢尾花数据集配对图', y=1.02)
plt.show()

第三部分:关系图(Relational Plots)

1. 散点图(scatterplot)

scatterplot 用于展示两个连续变量之间的关系。

import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

sns.set_style("whitegrid")

# 创建数据
np.random.seed(42)
df = pd.DataFrame({
    'X': np.random.randn(200),
    'Y': np.random.randn(200),
    '类别': np.random.choice(['A', 'B', 'C'], 200),
    '大小': np.random.randint(10, 100, 200)
})

# 基本散点图
sns.scatterplot(data=df, x='X', y='Y')
plt.title('基本散点图')
plt.show()

运行测试:

# 复制以下代码到 Python 解释器运行
import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

sns.set_style("whitegrid")

# 创建销售数据
np.random.seed(42)
df = pd.DataFrame({
    '广告投入': np.random.uniform(1000, 10000, 150),
    '销售额': np.random.uniform(5000, 50000, 150),
    '产品类型': np.random.choice(['类型A', '类型B', '类型C'], 150)
})

# 分组散点图
sns.scatterplot(data=df, x='广告投入', y='销售额', hue='产品类型', s=100)
plt.title('广告投入与销售额关系(按产品类型分组)')
plt.xlabel('广告投入(元)')
plt.ylabel('销售额(元)')
plt.show()

使用大小和样式:

import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

sns.set_style("whitegrid")

np.random.seed(42)
df = pd.DataFrame({
    'X': np.random.randn(150),
    'Y': np.random.randn(150),
    '类别': np.random.choice(['A', 'B'], 150),
    '大小': np.random.randint(20, 200, 150),
    '样式': np.random.choice(['圆形', '方形'], 150)
})

# 使用大小和样式
sns.scatterplot(data=df, x='X', y='Y', 
                hue='类别', size='大小', style='样式', sizes=(50, 300))
plt.title('多维度散点图')
plt.show()

运行测试:

# 复制以下代码到 Python 解释器运行
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd

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

# 创建散点图
sns.scatterplot(data=tips, x='total_bill', y='tip', hue='time', size='size')
plt.title('小费与账单金额关系')
plt.xlabel('账单金额(美元)')
plt.ylabel('小费(美元)')
plt.show()

2. 线图(lineplot)

lineplot 用于展示连续变量随另一个变量的变化趋势。

import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

sns.set_style("whitegrid")

# 创建时间序列数据
dates = pd.date_range('2024-01-01', periods=30, freq='D')
df = pd.DataFrame({
    '日期': dates,
    '销售额': np.random.randint(1000, 5000, 30).cumsum(),
    '类别': np.random.choice(['产品A', '产品B'], 30)
})

# 基本线图
sns.lineplot(data=df, x='日期', y='销售额')
plt.title('销售额趋势')
plt.xticks(rotation=45)
plt.show()

运行测试:

# 复制以下代码到 Python 解释器运行
import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

sns.set_style("whitegrid")

# 创建数据
x = np.linspace(0, 10, 100)
df = pd.DataFrame({
    'X': np.tile(x, 3),
    'Y': np.concatenate([np.sin(x), np.cos(x), np.sin(x) * np.cos(x)]),
    '函数': ['sin(x)'] * 100 + ['cos(x)'] * 100 + ['sin(x)cos(x)'] * 100
})

# 分组线图
sns.lineplot(data=df, x='X', y='Y', hue='函数', style='函数', markers=True)
plt.title('三角函数图像')
plt.xlabel('x')
plt.ylabel('y')
plt.legend()
plt.show()

带误差带的线图:

import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

sns.set_style("whitegrid")

# 创建带误差的数据
np.random.seed(42)
x = np.arange(10)
y = np.random.randn(10, 5).mean(axis=1)
y_err = np.random.randn(10, 5).std(axis=1)

df = pd.DataFrame({
    'X': x,
    'Y': y,
    '误差': y_err
})

# 带误差带的线图
sns.lineplot(data=df, x='X', y='Y', err_style='band', ci=95)
plt.title('带误差带的线图')
plt.show()

运行测试:

# 复制以下代码到 Python 解释器运行
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd

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

# 创建线图
sns.lineplot(data=fmri, x='timepoint', y='signal', hue='event', style='region')
plt.title('fMRI 信号变化')
plt.xlabel('时间点')
plt.ylabel('信号强度')
plt.show()

3. 关系图(relplot)

relplot 是更灵活的关系图函数,可以创建散点图和线图的分面版本。

import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

sns.set_style("whitegrid")

# 创建数据
np.random.seed(42)
df = pd.DataFrame({
    'X': np.random.randn(200),
    'Y': np.random.randn(200),
    '类别': np.random.choice(['A', 'B'], 200),
    '分组': np.random.choice(['组1', '组2'], 200)
})

# 创建分面关系图
sns.relplot(data=df, x='X', y='Y', hue='类别', col='分组', kind='scatter')
plt.suptitle('分面散点图', y=1.02)
plt.show()

运行测试:

# 复制以下代码到 Python 解释器运行
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd

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

# 创建分面关系图
sns.relplot(data=tips, x='total_bill', y='tip', 
           hue='smoker', col='time', row='day', kind='scatter')
plt.suptitle('小费数据分析', y=1.02)
plt.show()

第四部分:分类图(Categorical Plots)

1. 柱状图(barplot)

barplot 用于展示分类变量的统计信息。

import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

sns.set_style("whitegrid")

# 创建数据
df = pd.DataFrame({
    '类别': ['A', 'B', 'C', 'D', 'E'],
    '数值': [10, 20, 15, 25, 18]
})

# 基本柱状图
sns.barplot(data=df, x='类别', y='数值')
plt.title('分类柱状图')
plt.show()

运行测试:

# 复制以下代码到 Python 解释器运行
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd

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

# 创建分组柱状图
sns.barplot(data=tips, x='day', y='total_bill', hue='sex')
plt.title('每日账单金额(按性别分组)')
plt.xlabel('星期')
plt.ylabel('账单金额(美元)')
plt.show()

带误差条的柱状图:

import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

sns.set_style("whitegrid")

# 创建多组数据
np.random.seed(42)
df = pd.DataFrame({
    '类别': ['A', 'B', 'C'] * 20,
    '数值': np.random.normal(50, 10, 60),
    '分组': ['组1', '组2'] * 30
})

# 分组柱状图,自动计算误差条
sns.barplot(data=df, x='类别', y='数值', hue='分组', ci='sd')
plt.title('分组柱状图(带标准差误差条)')
plt.show()

运行测试:

# 复制以下代码到 Python 解释器运行
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd

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

# 创建柱状图
sns.barplot(data=titanic, x='class', y='survived', hue='sex')
plt.title('泰坦尼克号生存率(按船舱等级和性别)')
plt.xlabel('船舱等级')
plt.ylabel('生存率')
plt.show()

2. 计数图(countplot)

countplot 用于统计分类变量的频数。

import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

sns.set_style("whitegrid")

# 创建分类数据
np.random.seed(42)
df = pd.DataFrame({
    '类别': np.random.choice(['A', 'B', 'C', 'D'], 200)
})

# 基本计数图
sns.countplot(data=df, x='类别')
plt.title('类别计数图')
plt.xlabel('类别')
plt.ylabel('计数')
plt.show()

运行测试:

# 复制以下代码到 Python 解释器运行
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd

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

# 创建分组计数图
sns.countplot(data=titanic, x='class', hue='survived')
plt.title('泰坦尼克号乘客分布(按生存状态)')
plt.xlabel('船舱等级')
plt.ylabel('人数')
plt.legend(title='生存状态', labels=['未生存', '生存'])
plt.show()

3. 箱线图(boxplot)

boxplot 用于展示数据的分布、中位数、四分位数和异常值。

import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

sns.set_style("whitegrid")

# 创建数据
np.random.seed(42)
df = pd.DataFrame({
    '数值': np.random.normal(50, 15, 200),
    '类别': np.random.choice(['A', 'B', 'C'], 200)
})

# 基本箱线图
sns.boxplot(data=df, x='类别', y='数值')
plt.title('分组箱线图')
plt.show()

运行测试:

# 复制以下代码到 Python 解释器运行
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd

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

# 创建分组箱线图
sns.boxplot(data=tips, x='day', y='total_bill', hue='smoker')
plt.title('每日账单金额分布(按是否吸烟分组)')
plt.xlabel('星期')
plt.ylabel('账单金额(美元)')
plt.show()

4. 小提琴图(violinplot)

violinplot 结合了箱线图和核密度估计,展示数据分布形状。

import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

sns.set_style("whitegrid")

# 创建数据
np.random.seed(42)
df = pd.DataFrame({
    '数值': np.concatenate([
        np.random.normal(50, 10, 100),
        np.random.normal(70, 15, 100),
        np.random.normal(60, 12, 100)
    ]),
    '类别': ['A'] * 100 + ['B'] * 100 + ['C'] * 100
})

# 基本小提琴图
sns.violinplot(data=df, x='类别', y='数值')
plt.title('分组小提琴图')
plt.show()

运行测试:

# 复制以下代码到 Python 解释器运行
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd

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

# 创建小提琴图
sns.violinplot(data=tips, x='day', y='total_bill', hue='time', split=True)
plt.title('每日账单金额分布(小提琴图)')
plt.xlabel('星期')
plt.ylabel('账单金额(美元)')
plt.show()

5. 带状图(stripplot)和蜂群图(swarmplot)

import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

sns.set_style("whitegrid")

# 创建数据
np.random.seed(42)
df = pd.DataFrame({
    '数值': np.random.normal(50, 10, 150),
    '类别': np.random.choice(['A', 'B', 'C'], 150)
})

# 带状图
sns.stripplot(data=df, x='类别', y='数值', jitter=True)
plt.title('带状图')
plt.show()

# 蜂群图
sns.swarmplot(data=df, x='类别', y='数值')
plt.title('蜂群图')
plt.show()

运行测试:

# 复制以下代码到 Python 解释器运行
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd

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

# 结合箱线图和蜂群图
sns.boxplot(data=tips, x='day', y='total_bill', color='lightgray')
sns.swarmplot(data=tips, x='day', y='total_bill', color='black', size=3)
plt.title('每日账单金额分布(箱线图+蜂群图)')
plt.xlabel('星期')
plt.ylabel('账单金额(美元)')
plt.show()

6. 分类图(catplot)

catplot 是灵活的分类图函数,可以创建多种分类图的分面版本。

import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd

sns.set_style("whitegrid")

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

# 创建分面分类图
sns.catplot(data=tips, x='day', y='total_bill', 
           kind='box', col='time', hue='smoker')
plt.suptitle('分类图(分面)', y=1.02)
plt.show()

运行测试:

# 复制以下代码到 Python 解释器运行
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd

tips = sns.load_dataset('tips')

# 创建多种类型的分类图
sns.catplot(data=tips, x='day', y='total_bill', 
           kind='violin', col='time', row='smoker')
plt.suptitle('分面小提琴图', y=1.02)
plt.show()

第五部分:回归图(Regression Plots)

1. 回归图(regplot)

regplot 用于绘制散点图并拟合回归线。

import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

sns.set_style("whitegrid")

# 创建相关数据
np.random.seed(42)
x = np.random.randn(100)
y = 2 * x + np.random.randn(100) * 0.5
df = pd.DataFrame({'X': x, 'Y': y})

# 基本回归图
sns.regplot(data=df, x='X', y='Y')
plt.title('回归图')
plt.show()

运行测试:

# 复制以下代码到 Python 解释器运行
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd

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

# 创建回归图
sns.regplot(data=tips, x='total_bill', y='tip', 
           scatter_kws={'alpha': 0.5}, 
           line_kws={'color': 'red'})
plt.title('账单金额与小费关系(带回归线)')
plt.xlabel('账单金额(美元)')
plt.ylabel('小费(美元)')
plt.show()

多项式回归:

import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

sns.set_style("whitegrid")

# 创建非线性数据
np.random.seed(42)
x = np.linspace(-3, 3, 100)
y = x**2 + np.random.randn(100) * 0.5
df = pd.DataFrame({'X': x, 'Y': y})

# 多项式回归
sns.regplot(data=df, x='X', y='Y', order=2, ci=None)
plt.title('多项式回归(2次)')
plt.show()

运行测试:

# 复制以下代码到 Python 解释器运行
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd

tips = sns.load_dataset('tips')

# 带置信区间的回归图
sns.regplot(data=tips, x='total_bill', y='tip', 
           ci=95,  # 95% 置信区间
           scatter_kws={'s': 50, 'alpha': 0.6})
plt.title('回归图(带95%置信区间)')
plt.xlabel('账单金额(美元)')
plt.ylabel('小费(美元)')
plt.show()

2. 回归图(lmplot)

lmplot 是更灵活的回归图函数,支持分面。

import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd

sns.set_style("whitegrid")

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

# 基本回归图
sns.lmplot(data=tips, x='total_bill', y='tip', hue='smoker')
plt.title('回归图(按是否吸烟分组)')
plt.show()

运行测试:

# 复制以下代码到 Python 解释器运行
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd

tips = sns.load_dataset('tips')

# 分面回归图
sns.lmplot(data=tips, x='total_bill', y='tip', 
          col='time', row='smoker', hue='sex')
plt.suptitle('分面回归图', y=1.02)
plt.show()

第六部分:矩阵图(Matrix Plots)

1. 热力图(heatmap)

heatmap 用于展示矩阵数据的颜色编码。

import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

sns.set_style("whitegrid")

# 创建矩阵数据
np.random.seed(42)
data = np.random.randn(10, 10)
df = pd.DataFrame(data)

# 基本热力图
sns.heatmap(df, annot=True, fmt='.2f', cmap='coolwarm')
plt.title('热力图')
plt.show()

运行测试:

# 复制以下代码到 Python 解释器运行
import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

sns.set_style("whitegrid")

# 创建相关矩阵
np.random.seed(42)
data = np.random.randn(100, 5)
df = pd.DataFrame(data, columns=['A', 'B', 'C', 'D', 'E'])
corr = df.corr()

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

更复杂的热力图:

import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

sns.set_style("whitegrid")

# 创建时间序列数据
dates = pd.date_range('2024-01-01', periods=12, freq='M')
categories = ['产品A', '产品B', '产品C', '产品D']
np.random.seed(42)
data = np.random.randint(1000, 5000, (12, 4))
df = pd.DataFrame(data, index=dates, columns=categories)

# 创建热力图
sns.heatmap(df.T, annot=True, fmt='d', cmap='YlOrRd', 
           cbar_kws={'label': '销售额'})
plt.title('月度产品销售热力图')
plt.xlabel('月份')
plt.ylabel('产品')
plt.xticks(rotation=45)
plt.yticks(rotation=0)
plt.tight_layout()
plt.show()

运行测试:

# 复制以下代码到 Python 解释器运行
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

# 创建航班数据
flights = sns.load_dataset('flights')
flights_pivot = flights.pivot(index='month', columns='year', values='passengers')

# 创建热力图
sns.heatmap(flights_pivot, annot=True, fmt='d', cmap='YlGnBu', 
           cbar_kws={'label': '乘客数'})
plt.title('航班乘客数热力图')
plt.xlabel('年份')
plt.ylabel('月份')
plt.tight_layout()
plt.show()

2. 聚类图(clustermap)

clustermap 创建层次聚类的热力图。

import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

sns.set_style("whitegrid")

# 创建数据
np.random.seed(42)
data = np.random.randn(20, 10)
df = pd.DataFrame(data)

# 聚类图
sns.clustermap(df, cmap='coolwarm', figsize=(10, 8))
plt.suptitle('聚类热力图', y=1.02)
plt.show()

运行测试:

# 复制以下代码到 Python 解释器运行
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd

# 使用内置数据集
iris = sns.load_dataset('iris')
iris_numeric = iris.drop('species', axis=1)

# 创建聚类图
sns.clustermap(iris_numeric.T, cmap='viridis', figsize=(8, 6))
plt.suptitle('鸢尾花数据聚类图', y=1.02)
plt.show()

第七部分:多面板图(Multi-plot Grids)

1. 分面网格(FacetGrid)

FacetGrid 用于创建多面板图表。

import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd

sns.set_style("whitegrid")

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

# 创建分面网格
g = sns.FacetGrid(tips, col='time', row='smoker', hue='sex')
g.map(plt.scatter, 'total_bill', 'tip')
g.add_legend()
plt.suptitle('分面散点图', y=1.02)
plt.show()

运行测试:

# 复制以下代码到 Python 解释器运行
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd

tips = sns.load_dataset('tips')

# 创建分面网格,使用不同的绘图函数
g = sns.FacetGrid(tips, col='day', hue='time')
g.map(sns.histplot, 'total_bill', kde=True)
g.add_legend()
plt.suptitle('每日账单金额分布', y=1.02)
plt.show()

2. 配对网格(PairGrid)

PairGrid 用于创建配对图的自定义版本。

import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd

sns.set_style("whitegrid")

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

# 创建配对网格
g = sns.PairGrid(iris, hue='species')
g.map_diag(sns.histplot)
g.map_upper(sns.scatterplot)
g.map_lower(sns.kdeplot)
g.add_legend()
plt.suptitle('自定义配对图', y=1.02)
plt.show()

运行测试:

# 复制以下代码到 Python 解释器运行
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd

iris = sns.load_dataset('iris')

# 创建配对网格
g = sns.PairGrid(iris, hue='species', vars=['sepal_length', 'sepal_width', 'petal_length', 'petal_width'])
g.map_diag(sns.histplot, kde=True)
g.map_offdiag(sns.scatterplot)
g.add_legend()
plt.suptitle('鸢尾花数据配对图', y=1.02)
plt.show()

第八部分:高级功能和自定义

1. 自定义调色板

import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

sns.set_style("whitegrid")

# 创建自定义调色板
custom_palette = sns.color_palette("husl", 8)
sns.palplot(custom_palette)
plt.title('自定义调色板')
plt.show()

# 使用自定义颜色
colors = ['#FF6B6B', '#4ECDC4', '#45B7D1', '#FFA07A']
sns.set_palette(colors)

# 创建图表
df = pd.DataFrame({
    '类别': ['A', 'B', 'C', 'D'],
    '数值': [10, 20, 15, 25]
})
sns.barplot(data=df, x='类别', y='数值')
plt.title('使用自定义调色板')
plt.show()

运行测试:

# 复制以下代码到 Python 解释器运行
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd

# 查看所有内置调色板
print("内置调色板:")
print(sns.palettes.SEABORN_PALETTES)

# 创建自定义调色板
my_palette = sns.color_palette("Set2", 5)
sns.palplot(my_palette)
plt.title('Set2 调色板(5种颜色)')
plt.show()

2. 图表保存

import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd

sns.set_style("whitegrid")

# 创建图表
tips = sns.load_dataset('tips')
sns.scatterplot(data=tips, x='total_bill', y='tip')
plt.title('小费与账单金额关系')

# 保存图表
plt.savefig('seaborn_chart.png', dpi=300, bbox_inches='tight')
plt.savefig('seaborn_chart.pdf', bbox_inches='tight')
plt.savefig('seaborn_chart.svg', bbox_inches='tight')

plt.show()

运行测试:

# 复制以下代码到 Python 解释器运行
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd

sns.set_style("whitegrid")

# 创建图表
iris = sns.load_dataset('iris')
sns.pairplot(iris, hue='species')

# 保存图表(取消注释以保存)
# plt.savefig('iris_pairplot.png', dpi=300, bbox_inches='tight')
# print('图表已保存')

plt.show()

3. 组合多个图表

import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

sns.set_style("whitegrid")

# 创建数据
np.random.seed(42)
df = pd.DataFrame({
    'X': np.random.randn(200),
    'Y': np.random.randn(200),
    '类别': np.random.choice(['A', 'B', 'C'], 200)
})

# 创建多面板图表
fig, axes = plt.subplots(2, 2, figsize=(15, 12))

# 子图1:散点图
sns.scatterplot(data=df, x='X', y='Y', hue='类别', ax=axes[0, 0])
axes[0, 0].set_title('散点图')

# 子图2:直方图
sns.histplot(data=df, x='X', hue='类别', ax=axes[0, 1])
axes[0, 1].set_title('X 分布直方图')

# 子图3:箱线图
sns.boxplot(data=df, x='类别', y='Y', ax=axes[1, 0])
axes[1, 0].set_title('Y 值箱线图')

# 子图4:密度图
sns.kdeplot(data=df, x='Y', hue='类别', fill=True, ax=axes[1, 1])
axes[1, 1].set_title('Y 分布密度图')

plt.suptitle('综合数据分析', fontsize=16, fontweight='bold')
plt.tight_layout()
plt.show()

运行测试:

# 复制以下代码到 Python 解释器运行
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd

sns.set_style("whitegrid")

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

# 创建综合图表
fig, axes = plt.subplots(2, 2, figsize=(15, 12))

# 散点图
sns.scatterplot(data=tips, x='total_bill', y='tip', hue='time', ax=axes[0, 0])
axes[0, 0].set_title('账单与小费关系')

# 柱状图
sns.barplot(data=tips, x='day', y='total_bill', ax=axes[0, 1])
axes[0, 1].set_title('每日平均账单')

# 箱线图
sns.boxplot(data=tips, x='day', y='tip', hue='smoker', ax=axes[1, 0])
axes[1, 0].set_title('每日小费分布')

# 直方图
sns.histplot(data=tips, x='total_bill', kde=True, ax=axes[1, 1])
axes[1, 1].set_title('账单金额分布')

plt.suptitle('小费数据分析报告', fontsize=16, fontweight='bold')
plt.tight_layout()
plt.show()

第九部分:实际应用案例

案例 1:电商数据分析

import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

sns.set_style("whitegrid")
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

# 创建电商数据
np.random.seed(42)
dates = pd.date_range('2024-01-01', periods=90, freq='D')
df = pd.DataFrame({
    '日期': dates,
    '销售额': np.random.randint(10000, 50000, 90),
    '订单数': np.random.randint(100, 500, 90),
    '访客数': np.random.randint(1000, 5000, 90),
    '产品类别': np.random.choice(['电子产品', '服装', '食品', '图书'], 90),
    '渠道': np.random.choice(['线上', '线下'], 90)
})

# 计算转化率
df['转化率'] = (df['订单数'] / df['访客数'] * 100).round(2)

# 创建综合分析图表
fig, axes = plt.subplots(2, 3, figsize=(18, 12))

# 1. 销售额趋势
sns.lineplot(data=df, x='日期', y='销售额', ax=axes[0, 0])
axes[0, 0].set_title('销售额趋势', fontsize=14, fontweight='bold')
axes[0, 0].tick_params(axis='x', rotation=45)

# 2. 产品类别销售额对比
sns.barplot(data=df, x='产品类别', y='销售额', ax=axes[0, 1])
axes[0, 1].set_title('各产品类别销售额', fontsize=14, fontweight='bold')
axes[0, 1].tick_params(axis='x', rotation=45)

# 3. 渠道对比
sns.boxplot(data=df, x='渠道', y='销售额', ax=axes[0, 2])
axes[0, 2].set_title('渠道销售额分布', fontsize=14, fontweight='bold')

# 4. 转化率分布
sns.histplot(data=df, x='转化率', kde=True, ax=axes[1, 0])
axes[1, 0].set_title('转化率分布', fontsize=14, fontweight='bold')

# 5. 访客数与订单数关系
sns.scatterplot(data=df, x='访客数', y='订单数', hue='渠道', ax=axes[1, 1])
axes[1, 1].set_title('访客数与订单数关系', fontsize=14, fontweight='bold')

# 6. 产品类别转化率对比
sns.violinplot(data=df, x='产品类别', y='转化率', ax=axes[1, 2])
axes[1, 2].set_title('各产品类别转化率分布', fontsize=14, fontweight='bold')
axes[1, 2].tick_params(axis='x', rotation=45)

plt.suptitle('电商数据分析报告', fontsize=18, fontweight='bold', y=0.995)
plt.tight_layout()
plt.show()

运行测试:

# 复制以下代码到 Python 解释器运行
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

sns.set_style("whitegrid")
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

# 创建简化数据
np.random.seed(42)
df = pd.DataFrame({
    '月份': ['1月', '2月', '3月', '4月', '5月', '6月'],
    '销售额': np.random.randint(100000, 500000, 6),
    '产品类别': ['电子产品', '服装', '食品', '图书', '电子产品', '服装']
})

# 创建图表
fig, axes = plt.subplots(1, 2, figsize=(14, 6))

sns.barplot(data=df, x='月份', y='销售额', ax=axes[0])
axes[0].set_title('月度销售额')
axes[0].tick_params(axis='x', rotation=0)

sns.barplot(data=df, x='产品类别', y='销售额', ax=axes[1])
axes[1].set_title('产品类别销售额')
axes[1].tick_params(axis='x', rotation=45)

plt.tight_layout()
plt.show()

案例 2:用户行为分析

import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

sns.set_style("whitegrid")
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

# 创建用户行为数据
np.random.seed(42)
hours = list(range(24))
df = pd.DataFrame({
    '小时': hours * 7,
    '访问量': np.random.randint(100, 1000, 168),
    '注册数': np.random.randint(10, 100, 168),
    '购买数': np.random.randint(5, 50, 168),
    '星期': ['周一'] * 24 + ['周二'] * 24 + ['周三'] * 24 + ['周四'] * 24 + 
           ['周五'] * 24 + ['周六'] * 24 + ['周日'] * 24
})

# 计算转化率
df['注册转化率'] = (df['注册数'] / df['访问量'] * 100).round(2)
df['购买转化率'] = (df['购买数'] / df['访问量'] * 100).round(2)

# 创建分析图表
fig, axes = plt.subplots(2, 2, figsize=(16, 12))

# 1. 24小时访问量趋势
hourly_avg = df.groupby('小时')['访问量'].mean().reset_index()
sns.lineplot(data=hourly_avg, x='小时', y='访问量', marker='o', ax=axes[0, 0])
axes[0, 0].set_title('24小时平均访问量趋势', fontsize=14, fontweight='bold')
axes[0, 0].set_xlabel('小时')
axes[0, 0].set_ylabel('访问量')
axes[0, 0].grid(True, alpha=0.3)

# 2. 各星期访问量对比
sns.boxplot(data=df, x='星期', y='访问量', ax=axes[0, 1])
axes[0, 1].set_title('各星期访问量分布', fontsize=14, fontweight='bold')
axes[0, 1].tick_params(axis='x', rotation=45)

# 3. 转化率对比
df_melted = df.melt(id_vars=['小时'], 
                    value_vars=['注册转化率', '购买转化率'],
                    var_name='转化类型', value_name='转化率')
sns.lineplot(data=df_melted, x='小时', y='转化率', hue='转化类型', ax=axes[1, 0])
axes[1, 0].set_title('转化率趋势对比', fontsize=14, fontweight='bold')
axes[1, 0].set_xlabel('小时')
axes[1, 0].set_ylabel('转化率(%)')

# 4. 访问量与注册数关系
sns.scatterplot(data=df, x='访问量', y='注册数', hue='星期', ax=axes[1, 1], alpha=0.6)
axes[1, 1].set_title('访问量与注册数关系', fontsize=14, fontweight='bold')
axes[1, 1].set_xlabel('访问量')
axes[1, 1].set_ylabel('注册数')

plt.suptitle('用户行为数据分析', fontsize=18, fontweight='bold')
plt.tight_layout()
plt.show()

运行测试:

# 复制以下代码到 Python 解释器运行
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

sns.set_style("whitegrid")

# 创建简化数据
np.random.seed(42)
df = pd.DataFrame({
    '小时': list(range(24)),
    '访问量': np.random.randint(100, 1000, 24),
    '注册数': np.random.randint(10, 100, 24)
})

# 创建图表
fig, axes = plt.subplots(1, 2, figsize=(14, 6))

sns.lineplot(data=df, x='小时', y='访问量', marker='o', ax=axes[0])
axes[0].set_title('24小时访问量趋势')
axes[0].grid(True, alpha=0.3)

sns.scatterplot(data=df, x='访问量', y='注册数', ax=axes[1])
axes[1].set_title('访问量与注册数关系')
axes[1].grid(True, alpha=0.3)

plt.tight_layout()
plt.show()

第十部分:常见问题和技巧

1. 处理大数据集

import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

sns.set_style("whitegrid")

# 创建大数据集
np.random.seed(42)
large_df = pd.DataFrame({
    'X': np.random.randn(10000),
    'Y': np.random.randn(10000),
    '类别': np.random.choice(['A', 'B', 'C'], 10000)
})

# 方法1:使用 alpha 透明度
sns.scatterplot(data=large_df, x='X', y='Y', hue='类别', alpha=0.1, s=10)
plt.title('大数据集散点图(使用透明度)')
plt.show()

# 方法2:采样
sample_df = large_df.sample(n=1000)
sns.scatterplot(data=sample_df, x='X', y='Y', hue='类别')
plt.title('采样后的散点图')
plt.show()

运行测试:

# 复制以下代码到 Python 解释器运行
import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

sns.set_style("whitegrid")

# 创建较大数据集
np.random.seed(42)
df = pd.DataFrame({
    '值': np.random.normal(50, 10, 5000),
    '类别': np.random.choice(['A', 'B', 'C'], 5000)
})

# 使用直方图处理大数据
sns.histplot(data=df, x='值', hue='类别', bins=50, alpha=0.6)
plt.title('大数据集直方图')
plt.show()

2. 自定义样式和主题

import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

# 设置自定义样式
sns.set_style("whitegrid", {
    'axes.edgecolor': '0.8',
    'axes.linewidth': 1.2,
    'grid.color': '0.9',
    'grid.linewidth': 0.8
})

# 设置自定义调色板
sns.set_palette("husl")

# 设置图表大小
sns.set_context("paper", font_scale=1.2)

# 创建图表
df = pd.DataFrame({
    '类别': ['A', 'B', 'C', 'D'],
    '数值': [10, 20, 15, 25]
})

sns.barplot(data=df, x='类别', y='数值')
plt.title('自定义样式图表')
plt.show()

运行测试:

# 复制以下代码到 Python 解释器运行
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd

# 尝试不同的上下文设置
contexts = ['paper', 'notebook', 'talk', 'poster']

for context in contexts:
    sns.set_context(context)
    df = pd.DataFrame({'类别': ['A', 'B', 'C'], '数值': [10, 20, 15]})
    sns.barplot(data=df, x='类别', y='数值')
    plt.title(f'上下文:{context}')
    plt.show()
    break  # 只显示第一个作为示例

3. 导出高质量图表

import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd

sns.set_style("whitegrid")

# 创建图表
tips = sns.load_dataset('tips')
sns.scatterplot(data=tips, x='total_bill', y='tip')
plt.title('高质量图表示例')

# 保存为不同格式和分辨率
plt.savefig('chart_high_res.png', dpi=300, bbox_inches='tight', 
           facecolor='white', edgecolor='none')
plt.savefig('chart_vector.svg', bbox_inches='tight')
plt.savefig('chart_pdf.pdf', bbox_inches='tight')

plt.show()

总结

通过本教程,我们系统地学习了 Seaborn 图形绘制的各个方面:

  1. 基础设置:样式、主题、调色板
  2. 分布图:直方图、KDE 图、联合分布图、配对图
  3. 关系图:散点图、线图、关系图
  4. 分类图:柱状图、计数图、箱线图、小提琴图
  5. 回归图:回归图、线性模型图
  6. 矩阵图:热力图、聚类图
  7. 多面板图:分面网格、配对网格
  8. 高级功能:自定义调色板、图表组合、数据导出

关键要点:

  • Seaborn 提供了美观的默认样式和统计功能
  • 与 Pandas 无缝集成,使用 DataFrame 数据
  • 支持多种图表类型和分面功能
  • 适合数据科学和统计分析场景

下一步学习:

  • Matplotlib 高级功能:更精细的控制
  • Plotly:交互式图表
  • Bokeh:Web 交互式可视化
  • 数据科学项目:综合应用各种可视化工具

记住:数据可视化是数据分析的重要工具,多实践才能掌握!


参考资料


评论