pythonic生物人

灵活的使用seaborn,先掰扯axes-level和figure-level关系

为了、更灵活的使用 《保姆级seaborn教程》 ,本章节详细介绍seaborn的两大类绘图函数的异同 (教程中风格也类似) :
  • 坐标轴级别(axes-level)绘图函数
  • 图形级别(figure-level)绘图函数
节选自教程 👉 嫌Matplotlib繁琐?试试Seaborn!

6.1 axes-level绘图函数

axes-level绘图函数是将数据绘制在matplotlib.pyplot.Axes对象上,此类函数可以直接使用matplotlib rcParams中的参数。

例如,使用章节3.2.2 penguins数据集,直方图展示不同“企鹅的种类”的"喙长 (毫米)"分布关系时,可直接使用axes-level绘图函数histplot,

import seaborn as sns
import pandas as pd
import matplotlib as mpl

penguins = pd.read_csv(
    './sns_data/penguins.csv')  #使用pandas读取章节3.2.2 penguins数据集数据

g = sns.histplot(
    data=penguins,  #使用axes-level函数histplot
    x="喙长 (毫米)",
    hue="企鹅的种类",
    palette=["#006a8e", "#b1283a", "#a8a6a7"],
    multiple="stack")
print(type(g))

其中,g是一个matplotlib.pyplot.Axes对象(见上方红色箭头)。更多axes-level绘图函数,如下图中蓝色框子后的函数,例如,scatterplot、lineplot、stripplot、swarmplot等函数。

6.2 figure-level绘图函数

figure-level绘图函数将数据绘制在seaborn.axisgrid.FacetGrid对象上,此类函数拥有区别于matplotlib rcParams中的参数,每个figure-level绘图函数都提供了统一的axes-level接口。

例如,6.1章节的图也可以使用figure-level绘图函数displot,只需要指定kind="hist",

g = sns.displot(
    data=penguins,  ##使用figure-level函数displot
    x="喙长 (毫米)",
    hue="企鹅的种类",
    multiple="stack",
    palette=["#006a8e", "#b1283a", "#a8a6a7"],
    kind="hist")  #kind="hist"等价于axes-level函数histplot
print(type(g))

其中,g是一个seaborn.axisgrid.FacetGrid对象(见上方红色箭头)。更多figure-level绘图函数,如下图中蓝色框子内的jointplot、relplot、displot等。

6.3 figure-level、axes-level比较

大部分情况下,figure-level和axes-level函数功能非常相似,但也存在一些差异,例如,figure-level中图例被放置在图形之外,axes-level中则将图例被放置在图形之内(注意比较6.1章节和6.2章节)。

下文详细介绍figure-level和axes-level的差异。

  • 6.3.1 figure-level多子图

figure-level最擅长多子图(subplot)绘制。例如,6.1章节和6.2章节中的堆叠直方图不容易直观看出每一种企鹅的“喙长 (毫米)”分布,解决该问题,可以尝试多子图,每一种企鹅绘制一个“喙长 (毫米)”分布直方图,figure-level函数一行代码实现多子图,

sns.displot(
    data=penguins,
    x="喙长 (毫米)",
    hue="企鹅的种类",  #按照"企鹅的种类"绘制子图
    col="企鹅的种类",  #图形按照"企鹅的种类"按行绘制
    palette=["#006a8e", "#b1283a", "#a8a6a7"])

虽然figure-level多子图绘制很便捷,但是,如果想单独设置某个子图就不够灵活,例如,

sns.displot(
    data=penguins,
    x="喙长 (毫米)",
    hue="企鹅的种类",
    col="企鹅的种类",
    binwidth=10,  #设置柱子的宽度
    palette=["#006a8e", "#b1283a", "#a8a6a7"])

binwidth可以高效设置所有子图的bin宽度,并不能设置某一个子图。

  • 6.3.2 axes-level多子图个性化

axes-level也可以绘制多子图,需要通过参数ax指定子图,seaborn内部调用matplotlib.pyplot.gca()激活当前子图为需要绘图的对象,例如,

import matplotlib.pyplot as plt

fig, axs = plt.subplots(  #subplots添加3个子图
    1,3,figsize=(8, 4),
    gridspec_kw=dict(width_ratios=[1, 1, 1]))

colormaps = ["#006a8e", "#b1283a", "#a8a6a7"]
for i, species in enumerate(penguins['企鹅的种类'].unique()):
    data = penguins[penguins['企鹅的种类'] == species]
    sns.histplot(
        data=data,
        x='喙长 (毫米)',
        ax=axs[i],  # 参数ax激活当前子图axs[i]为需要绘图的对象
        color=colormaps[i])
    axs[i].set_title("企鹅的种类=%s" % species)

plt.tight_layout() 

效果类似figure-level绘制多子图,但是,axes-level代码量大大增加。相比于figure-level,axes-level更擅长每个子图的个性化,例如,

import matplotlib.pyplot as plt

f, axs = plt.subplots(  #subplots添加两个子图
    1,
    2,
    figsize=(8, 4),
    gridspec_kw=dict(width_ratios=[4, 3]))

sns.scatterplot(data=penguins,
                x="喙深 (毫米)",
                y="喙长 (毫米)",
                palette=["#006a8e", "#b1283a", "#a8a6a7"],
                hue="企鹅的种类",
                ax=axs[0])  #参数ax激活当前子图axs[0]为需要绘图的对象
sns.histplot(data=penguins,
             x="企鹅的种类",
             hue="企鹅的种类",
             palette=["#006a8e", "#b1283a", "#a8a6a7"],
             shrink=.8,
             alpha=.8,
             legend=False,
             ax=axs[1])  #参数ax激活当前子图axs[1]为需要绘图的对象
f.tight_layout()
  • 6.3.3 figure-level全局个性化

figure-level拥有很多区别于matplotlib rcParams中的有用参数,这些参数seaborn独有,从全局设置图形,全局个性化是在seaborn.axisgrid.FacetGrid对象上设置。例如,修改多个子图x坐标轴上的标签,

import seaborn as sns
import pandas as pd
import matplotlib as mpl

g = sns.displot(
    data=penguins,
    x="喙长 (毫米)",  #修改前,多个子图x坐标轴上的标签取x变量名
    hue="企鹅的种类",
    col="企鹅的种类",
    palette=["#006a8e", "#b1283a", "#a8a6a7"])

修改前,多个子图x坐标轴上的标签取x变量名“喙长 (毫米)”。

一行代码修改多个子图x坐标轴上的标签“喙长 (mm)”,更多全局设置函数见后文。figure-level也可以调用axes-level个性化图形,例如,

import seaborn as sns
import pandas as pd
import matplotlib as mpl
 
g = sns.relplot(data=tips, x="消费金额 ($)", y="小费金额 ($)", color="#b1283a")

#调用axes-level方法matplotlib.lines._AxLine添加趋势线
g.ax.axline(xy1=(10, 2), slope=.2, color="#006a8e", dashes=(5, 2))
  • 6.3.4 figure-level设置图形大小

axes-level设置图形的大小同matplotlib中figzie参数,例如,

# 第一张图代码
import matplotlib.pyplot as plt

f, ax = plt.subplots(figsize=(6, 4))  #figsize设置整个图形宽6、高4

# 第二张图代码
f, ax = plt.subplots(1, 2, figsize=(6, 4))  #两个子图均分整个图形大小

效果如下,

figure-level设置图形的大小同axes-level存在巨大差异,通过height设置每个图形高度,通过height * aspect设置每个图形宽度,例如,

# 第一张图代码
sns.FacetGrid(data=penguins, height=3, aspect=1)

# 第二张图代码
sns.FacetGrid(data=penguins, height=3, aspect=1, col='性别')  #设置每个子图大小
sns.FacetGrid(
    data=penguins,
    col='性别',
    height=3,  #通过height设置每个子图高度
    aspect=0.75)  #通过height * aspect设置每个图形宽度
  • 6.4 figure-level、axes-level小结

figure-level和axes-level在简单图形上,效果几乎一样;figure-level会生成更清晰、简洁的图形,在多子图、全局统一设置方面优势明显;axes-level在需要绘制多个子图,且每个子图上绘制不同图形时优势明显。

如何加入学习 《保姆级seaborn教程》

👇加入学习 ( 收费、 务必备注:169 )

✅解锁获取 5大权限:
  • 代码(复制即可运行)
  • 在线教程文档(方便后续更新)
  • 依赖数据(免费下载)
  • 交流群
  • 后续更新