将多个 seaborn 图保存到一个 pdf 文件中

Save multiple seaborn plots into one pdf file

目前我正在学习如何使用 matplotlibseaborn,它背后的概念对我来说似乎很陌生。人们会期望 sns.countplot 函数到 return 一个具有 .plot().save() 函数的对象,这样就可以在不同的函数中处理绘图。 相反,似乎每次调用 sns.countplot 都会覆盖前一个对象(参见 MWE)。

因此,一方面 如果有人可以提供 matplotlibseaborn 界面的解释(或者有一些很好的 doku 链接),我们将不胜感激。由于我阅读的所有 doku 都没有太大帮助。

另一方面,我有一个函数可以 return 绘制一些图,我想将其保存为一个 .pdf 文件,每页一个图。我发现这个类似 但无法以某种方式复制代码以使我的 MWE 工作。

from matplotlib.backends.backend_pdf import PdfPages
import seaborn as sns


def generate_plots():

    penguins = sns.load_dataset("penguins")

    countplot_sex = sns.countplot(y='sex', data=penguins)
    countplot_species = sns.countplot(y='species', data=penguins)
    countplot_island = sns.countplot(y='island', data=penguins)

    # As showes
    # print(countplot_sex) -> AxesSubplot(0.125,0.11;0.775x0.77)
    # print(countplot_species) -> AxesSubplot(0.125,0.11;0.775x0.77)
    # print(countplot_island) -> AxesSubplot(0.125,0.11;0.775x0.77)
    # All three variables contain the same object

    return(countplot_sex, countplot_species, countplot_island)


def plots2pdf(plots, fname):  # from: 
    pp = PdfPages('multipage.pdf')

    for plot in plots:
        pass
        # TODO save plot
        # Does not work: plot.savefig(pp, format='pdf')

    pp.savefig()
    pp.close()


def main():
    plots2pdf(generate_plots(), 'multipage.pdf')


if __name__ == '__main__':
    main()

我的想法是拥有一个有点像样的软件架构,其中一个函数生成图,另一个函数保存它们。

问题是默认情况下,sns.countplot 将在当前的 matplotlib Axes 实例上进行绘图。来自 docs:

ax matplotlib Axes, optional

Axes object to draw the plot onto, otherwise uses the current Axes.

一个解决方案是定义一个小函数来创建新图形和 Axes 实例,然后将其传递给 sns.countplot,以确保它绘制在新图形上并且不会覆盖之前的图形。这就是我在下面的示例中显示的内容。另一种方法是只创建 3 个图形和轴,然后自己将每个图形和轴传递给 sns.countplot 函数。

然后在您的 plots2pdf 函数中,您可以遍历轴,并在保存时将它们的图形实例传递给 PdfPages 实例。 (注意:由于您在 generate_plots 函数中创建图形,因此另一种方法是 return 来自该函数的图形实例,然后您准备好将它们传递给 pp.savefig 函数,但我是这样做的,所以你的函数的输出保持不变。

from matplotlib.backends.backend_pdf import PdfPages
import seaborn as sns
import matplotlib.pyplot as plt

def generate_plots():

    penguins = sns.load_dataset("penguins")

    def my_countplot(y, data):
        fig, ax = plt.subplots()
        sns.countplot(y=y, data=data)
        return ax

    countplot_sex = my_countplot(y='sex', data=penguins)
    countplot_species = my_countplot(y='species', data=penguins)
    countplot_island = my_countplot(y='island', data=penguins)

    return(countplot_sex, countplot_species, countplot_island)


def plots2pdf(plots, fname):

    with PdfPages(fname) as pp:

        for plot in plots:

           pp.savefig(plot.figure)

def main():
    plots2pdf(generate_plots(), 'multipage.pdf')


if __name__ == '__main__':
    main()

生成的多页pdf截图: