使用面向对象接口的matplotlib绘图与seaborn

133 投票
1 回答
120854 浏览
提问于 2025-04-18 08:08

我个人非常喜欢用面向对象的方式来使用 matplotlib

f, axarr = plt.subplots(2, sharex=True)
axarr[0].plot(...)
axarr[1].plot(...)

这样可以更方便地管理多个图形和子图。

问题是:如何用这种方式来使用 seaborn 呢?或者,怎么把 这个例子改成面向对象的风格?怎么告诉 seaborn 的绘图函数,比如 lmplot,它应该绘制到哪个 FigureAxes 上呢?

1 个回答

294

这要看你使用的是哪个seaborn的函数。

seaborn中的绘图函数大致可以分为两种类型:

  • “坐标轴级”函数,比如 regplotboxplotkdeplot 等等
  • “图形级”函数,比如 relplotcatplotdisplotpairplotjointplot 以及一两个其他的

第一组函数的特点是需要一个明确的 ax 参数,并且返回一个 Axes 对象。正如这个名字所暗示的,你可以通过传递你的 Axes 来以“面向对象”的方式使用它们:

f, (ax1, ax2) = plt.subplots(2)
sns.regplot(x, y, ax=ax1)
sns.kdeplot(x, ax=ax2)

坐标轴级函数只会在一个 Axes 上绘图,不会对图形做其他的修改,所以它们可以在一个面向对象的matplotlib脚本中完美共存。

第二组函数(图形级)则是因为生成的图可能包含多个坐标轴,并且这些坐标轴总是以“有意义”的方式组织在一起。这意味着这些函数需要完全控制图形,所以你不能把一个 lmplot 绘制到已经存在的图上。调用这些函数时,总是会初始化一个图形,并为你要绘制的特定图形进行设置。

不过,一旦你调用了 lmplot,它会返回一个 FacetGrid 类型的对象。这个对象有一些方法可以操作生成的图,并且了解图的结构。它还可以通过 FacetGrid.figFacetGrid.axes 参数访问底层的图形和坐标轴数组。jointplot 函数也很相似,但它使用的是 JointGrid 对象。因此,你仍然可以在面向对象的上下文中使用这些函数,但所有的自定义设置必须在你调用函数之后进行。

撰写回答