云计算百科
云计算领域专业知识百科平台

【Seaborn 学习笔记】P1. 散点图 scatterplot、折线图 lineplot、关系图 relplot

matplotlib 画图,seaborn 画变量关系

seaborn 本质上是在 matplotlib 的画布上画图,均使用 plt.show() 来显示绘制的图像


安装 Seaborn

使用 pip 安装:

pip install seaborn

注意: Seaborn 依赖 pandas + matplotlib + numpy,安装 seaborn 时会一并安装这些依赖


在 Python 中导入 Seaborn 库

导入并取别名为 sns:

import seaborn as sns


加载 Seaborn 内置数据集

Seaborn 拥有内置数据集,可以直接加载,返回 DataFrame 类型的数据集

1. 查看内置数据集

import seaborn as sns
dataset_names = sns.get_dataset_names()
print(dataset_names)

返回如下结果:

['anagrams', 'anscombe', 'attention', 'brain_networks', 'car_crashes', 'diamonds', 'dots', 'dowjones', 'exercise', 'flights', 'fmri', 'geyser', 'glue', 'healthexp', 'iris', 'mpg', 'penguins', 'planets', 'seaice', 'taxis', 'tips', 'titanic']

2. 加载数据集

返回的是 pandas 的 DataFrame 数据类型

import seaborn as sns

# 例如加载 iris 数据集
df = sns.load_dataset('iris') # 返回 DataFrame 数据类型

# 查看前五条记录
print(df.head())

结果如下:

   sepal_length  sepal_width  petal_length  petal_width species
0           5.1          3.5           1.4          0.2  setosa
1           4.9          3.0           1.4          0.2  setosa
2           4.7          3.2           1.3          0.2  setosa
3           4.6          3.1           1.5          0.2  setosa
4           5.0          3.6           1.4          0.2  setosa


散点图绘制 sns.scatterplot

sns.scatterplot(
data=df, # 数据
x='横轴变量特征', # 横轴变量
y='纵轴变量特征', # 纵轴变量
hue='颜色分组特征', # 按该列映射颜色
style='形状分组特征', # 按该列映射标记形状
size='点大小映射特征', # 按该列映射点的大小
s=60, # 固定点大小(若同时使用 size 参数,s 将被忽略,推荐二选一)
alpha=0.7, # 透明度
ax=ax # 指定子图
)

每条记录对应一个点

seaborn 的 sns.scatterplot 相比 matplotlib 的 plt.scatter 多了三个关键统计语义:

  • hue:分组,指定一个特征给 hue,对于不同的该特征,绘制的点映射不同颜色
  • style:点的样式,指定一个特征给 style,对于不同的该特征,绘制的点会使用不同的样式。用于区分第二分类维度
  • size:点的大小,指定一个特征给 size,若一条记录的该特征越大,绘制的点也就越大
  • 示例

    绘制 penguins 数据集中企鹅的鳍长(flipper_length_mm)关于体重(body_mass_g)的散点图。首先加载数据集:

    import seaborn as sns

    # 加载数据集
    df = sns.load_dataset('penguins')
    df.head()

    peguins 数据集形如:

    1. 绘制一个普通的散点图

    # 绘制散点图
    sns.scatterplot(data=df, x='flipper_length_mm', y='body_mass_g')
    # seaborn 在绘图前会调用 dropna(),自动删除 x / y / hue / style / size 中含有 NaN 的行

    plt.show() # 使用 mpl 来显示图片 -> sns 在 mpl 的画布上画图,由 mpl 来显示图片

    绘图结果如下:

    2. 加入参数 hue,对指定特征不同的记录在画图时映射不同的颜色

    # 加入分类变量 hue
    sns.scatterplot(
    data=df,
    x='flipper_length_mm',
    y='body_mass_g',
    hue='species' # 将对每个点根据其 species 标注不同颜色
    )
    # 根据 hue 映射颜色
    # seaborn 会自动生成 legend

    plt.show()

    绘图结果如下:

    3. 加入参数 style,对指定特征不同的记录在画图时使用不同的点的样式

    # 再加入点的样式 style
    sns.scatterplot(
    data=df,
    x='flipper_length_mm',
    y='body_mass_g',
    hue='species', # 将对每个点根据其 species 标注不同颜色
    style='sex' # 将对每个点根据其 sex 选择不同的点的样式
    )
    # 根据 style 选择不同标记
    # 适合在 hue 的基础上进行二次分类的情形

    plt.show()

    绘图结果如下:


    使用 Axes 对象精细化控制

    Seaborn 的大部分绘图函数都会返回一个 matplotlib.axes.Axes 对象,因此不需要显示创建画布就可以拿到绘图后的 Axes,并通过这个 Axes 对绘制的图形进行精细化控制。

    Axes 对象有关方法

    方法功能
    ax.set_title('标题') 标题

    ax.set_xlabel('x轴标签')

    ax.set_ylabel('y轴标签')

    坐标轴标签

    ax.set_xlim(left=…, right=…)

    ax.set_ylim(bottom=…, top=…)

    坐标轴范围

    ax.set_xticks(x值的序列)

    ax.set_yticks(y值的序列)

    刻度

    ax.legend(title='图例标题', loc='best')

    loc 表示图例的位置,还可为 :

    1. 最佳位置:'best',自动选最不挡数据的位置(已逐步被弃用,建议显式指定位置)

    2. 四个角与四条边中间:'upper', 'lower', 'center' 与 'left', 'right', 'center' 的组合(中间用空格隔开),例如 'upper center' 表示上方居中

    3. 坐标系正中间:'center',容易挡住数据

    图例

    ax.grid(True)        # x、y轴网格线

    ax.grid(True, axis='x')        # 仅 x 轴网格线

    ax.grid(True, axis='y')        # 仅 y 轴网格线

    网格

    ax.axhline()

    ax.axvline()

    参考线

    ax.text()

    ax.annotate()

    文本

    ax.spines[]        # 用字典形式对某边框进行操作

    包括边框显示与隐藏、粗细、颜色等

    # 隐藏上、右边框

    for spine in ['top', 'right']:

            ax.spines[spine].set_visible(False)

    边框

     1. 示例

    import seaborn as sns
    import matplotlib as mpl
    import matplotlib.pyplot as plt

    df = sns.load_dataset('penguins')
    df.head()

    mpl.rcParams['font.family'] = 'SimHei'
    mpl.rcParams['font.size'] = 15

    # 这里将返回的 Axes 对象存变量 ax
    ax = sns.scatterplot(
    data=df,
    x='flipper_length_mm',
    y='body_mass_g',
    hue='species'
    )

    # 添加 x、y 轴标签
    ax.set_xlabel('鳍长 (mm)')
    ax.set_ylabel('体重 (g)')

    ax.legend(title='物种') # 修改图例标题
    ax.grid(True) # 网格线

    plt.show()

    绘图结果如下:

    2. 图例外置

    若图例在图中会遮挡数据,可以使用 ax.legend() 方法将其放在图的外面

    要配合 plt.tight_layout() 使用,否则图例可能会跑出画布

    ax.legend(
    title='图例标题',
    bbox_to_anchor=(x坐标, y坐标), # 对齐坐标,(0, 0) 表示 ax 的左下角,(1, 1) 表示 ax 的右上角
    loc='对齐方式' # 指定图例的哪个角或边中点与该坐标对齐
    )

    例如:

    将图例放在图的右侧常用写法:

    ax.legend(
    title='图例标题',
    bbox_to_anchor=(1.02, 1), # 对齐坐标,(1.02, 1),表示图的右上角往右0.02距离的点
    loc='upper left' # 指定图例的左上角与 (1.02, 1) 点对齐
    )

    结果形如:

    使用 tight_layout(rect=…) 为图例预留空间:

    例如:

    在右侧预留图例空间

    # rect=[左边距, 底边距, 右边距, 上边距],使用 figure 坐标系(0–1),指定一个矩形区域
    # tight_layout 仅在 rect 指定的矩形区域内排布子图
    plt.tight_layout(rect=(0, 0, 0.82, 1)) # 右侧留 18% 空间给图例,防止 tight_layout 将其裁掉


    散点图练习

    1. 使用 penguins 数据集,x 轴为喙长(bill_length_mm),y 轴为喙深(bill_depth_mm)并且按 species 映射颜色画出散点图,加上合适的标题和轴标签,画在子图1

    2. 在 1 的基础上用 sex 区分性别,画在子图2

    (图例放在图的右侧中部)

    # 本人思路,仅供参考
    import seaborn as sns
    import matplotlib as mpl
    import matplotlib.pyplot as plt

    df = sns.load_dataset('penguins')
    df.head()

    mpl.rcParams['font.family'] = 'SimHei'
    mpl.rcParams['font.size'] = 15

    # 使用 2×1 的垂直布局,便于对比“仅按种类着色”与“按种类+性别区分”的差异
    fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(12, 14), dpi=100) # 同时获得画布 fig 与两幅子图 ax1, ax2

    # 子图1
    sns.scatterplot(
    data=df,
    x='bill_length_mm',
    y='bill_depth_mm',
    hue='species',
    ax=ax1
    )
    ax1.set_title('喙长-喙深 对比图')
    ax1.set_xlabel('喙长 (mm)')
    ax1.set_ylabel('喙深 (mm)')
    # 将图例放到图的右侧
    ax1.legend(
    title='物种',
    loc='upper left', # 图例的左上角
    bbox_to_anchor=(1.02, 1) # 对齐到 ax1 的右侧
    )

    # 子图2
    sns.scatterplot(
    data=df,
    x='bill_length_mm',
    y='bill_depth_mm',
    hue='species',
    style='sex',
    ax=ax2
    )
    ax2.set_title('喙长-喙深 对比图')
    ax2.set_xlabel('喙长 (mm)')
    ax2.set_ylabel('喙深 (mm)')
    # 将图例放到图的右侧中部
    ax2.legend(
    title='物种 / 性别',
    loc='upper left', # 图例的左上角
    bbox_to_anchor=(1.02, 1) # 对齐到 ax2 的右侧
    )

    plt.tight_layout(rect=(0, 0, 0.82, 1))
    plt.show()

    绘图结果如下:


    折线图绘制 sns.lineplot

    sns.lineplot(
    data=df, # 数据
    x='横轴变量特征', # 横轴变量
    y='纵轴变量特征', # 纵轴变量
    hue='颜色分组特征', # 按该列映射颜色
    style='线型分组特征', # 按该列映射线型
    markers=True, # 是否显示点
    dashes=False, # False:所有分组均为实线,True:不同分组使用不同虚线样式(Seaborn 默认行为),也可传入列表或字典自定义虚线
    estimator='mean', # 对同一 x 下的多个 y 求均值(默认值,可省略),lineplot 默认会对相同 x 值对应的多个 y 值进行聚合
    errorbar=None, # None / 'sd' / ('pi', 95)
    ax=ax # 指定子图
    )

    绘制折线图时,若不指定 errorbar=None,则默认自动生成置信区间(CI)

    示例

    绘制 flights 数据集中乘客数量随年份的变化趋势:

    (1)子图1:手动聚合,计算各年份所有月份的乘客数均值,绘制折线图

    (2)子图2:直接使用原始数据绘制 lineplot,由 Seaborn 自动对同一 year下的多个观测值进行聚合,并显示默认的 95% 置信区间

    (3)子图3:同上,但使用 errorbar=None 关闭置信区间

    (4)子图4:以 month 为分组变量(hue='month'),在同一坐标系中绘制多条折线,展示不同月份的年度变化趋势

    flights 数据集形如:

            

    绘图结果如下:


    折线图练习

    tips 数据集形如:

    使用 tips 数据集,绘制折线图,体现午餐(Lunch)和晚餐(Dinner)的平均账单金额在一周内的变化趋势

    要求:

    (1)x 轴:day(星期几) 、y 轴:total_bill 的平均值

    (2)中文标题 + 中文轴标签

    (3)图例放在图外右侧

    (4)关闭置信区间(因为天数很少,CI 不稳定)

    (5)用散点图标出折线节点(mean 聚合点)

    # 本人思路,仅供参考
    import seaborn as sns
    import matplotlib.pyplot as plt
    import matplotlib as mpl

    df = sns.load_dataset('tips')
    print(df.head())

    mpl.rcParams['font.family'] = 'SimHei'
    mpl.rcParams['font.size'] = 15

    fig, ax = plt.subplots(figsize=(8, 6), dpi=100)

    sns.lineplot(
    data=df,
    x='day',
    y='total_bill',
    hue='time',
    errorbar=None,
    ax=ax
    )

    agg1 = (
    df.groupby(['day', 'time'], observed=True)['total_bill'] # observed=True 仅保留数据中实际出现的组合;observed=False:分组中若某项不存在,则显示 NaN
    .mean()
    .reset_index()
    )
    print(agg1)

    sns.scatterplot(
    data=agg1,
    x='day',
    y='total_bill',
    hue='time',
    legend=False # 不显示图例
    )

    ax.set_xlabel('星期')
    ax.set_ylabel('订单总额平均值')
    ax.set_title('订单总额平均值随星期变化图')
    ax.legend(
    title='用餐时段',
    bbox_to_anchor=(1.02, 1),
    loc='upper left'
    )

    plt.tight_layout(rect=(0, 0, 0.82, 1))
    plt.show()

    绘图结果如下:


    灰度显示

    绘图时加入如下参数进行灰度显示:

    palette='gray', # 去色

    配合 style 可以在不使用颜色的情况下,通过标记形状(散点图)或线型(折线图)区分不同类别

    常用于黑白打印、学术期刊及灰度显示场景


    关系图 sns.relplot

    relplot(关系图,Relational Plot)用于在图中展示变量之间的关系,可通过 kind 参数切换为散点图或折线图

  • kind='scatter' -> scatterplot 散点图(默认)
  • kind='line' -> lineplot 折线图
  • 基础参数:

    sns.relplot(
    data=df, # 数据
    x='横轴变量', # 横轴
    y='纵轴变量', # 纵轴
    hue='颜色分组特征', # 颜色区分
    style='样式分组特征', # 标记 / 线型区分
    size='大小映射特征', # 点大小映射(散点图)
    markers=True, # 是否显示点(折线图)
    dashes=False, # 是否使用不同虚线
    kind='scatter', # 'scatter' 或 'line'
    )

    分面

    sns.relplot(
    '''
    其余参数
    '''
    col='按列分面特征', # 按列分面
    col_wrap=… # 一行最多的子图数量
    row='按行分面特征', # 按行分面
    )

    1. col, row 分列/分行

    指定 col 或 row 为某一特征,则会按该特征的每个取值生成一个子图:

  • col 控制横向排列(分列)
  • row 控制纵向排列(分行)
  • 适合在多子图中对比不同组别的数据分布与关系

    2. col_wrap 指定一行最多的子图数量

    col_wrap 指定一行最多的子图数量(最大分列数),配合 col 使用

    在仅指定 col、不指定 row 的情况下才可使用 col_wrap

    示例

    tips 数据集形如:

    使用 tips 数据集,用 relplot 绘图:

    (1)分面:x 轴为星期(day)、y 轴为账单金额(total_bill) 的平均值,按性别(sex)分列,按smoker(是否吸烟)分行,绘制折线图,关闭置信区间

    import seaborn as sns
    import matplotlib.pyplot as plt
    import matplotlib as mpl

    df = sns.load_dataset('tips')
    print(df.head())

    mpl.rcParams['font.family'] = 'SimHei'
    mpl.rcParams['font.size'] = 15

    sns.relplot(
    data=df,
    x='day',
    y='total_bill',
    kind='line',
    hue='time',
    col='sex', # 按 'sex' 分列
    row='smoker', # 按 'smoker' 分行
    errorbar=None
    )

    plt.show()

    绘图结果如下:

    (2)分面:x 轴为账单金额(total_bill)、y 轴为小费(tips),绘制散点图,根据性别(sex)映射不同颜色,根据小费(tips)的多少映射点的大小,按星期(day)分列,设置每行子图数最多为 2

    import seaborn as sns
    import matplotlib.pyplot as plt
    import matplotlib as mpl

    df = sns.load_dataset('tips')
    print(df.head())

    mpl.rcParams['font.family'] = 'SimHei'
    mpl.rcParams['font.size'] = 15

    sns.relplot(
    data=df,
    x='total_bill',
    y='tip',
    kind='scatter',
    hue='sex',
    size='tip',
    col='day',
    col_wrap=2 # 每行最多两幅子图
    )

    plt.show()

    绘图结果如下:


    relplot 与 scatterplot, lineplot 的关系

    此前的 scatterplot 与 lineplot 为 Axes-level 的,画在一个 Axes 上,而 relplot 为 Figure-level 的,画在一整个 Figure 上,返回一个 FacetGrid(分面图)对象,自动 legend、自动分面、自动管理布局

    赞(0)
    未经允许不得转载:网硕互联帮助中心 » 【Seaborn 学习笔记】P1. 散点图 scatterplot、折线图 lineplot、关系图 relplot
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!