1

我刚开始使用 Matplotlib,从 Matlab 切换。我在 Windows 7 上通过 python(x,y) 运行 Spyder。

我写了一个小脚本,它的工作是

  • 打开几个包含表格数据的 Excel 电子表格
  • 对于每张工作表,生成多个饼图 - 每个饼图汇总 Excel 中的一行数据
  • PdfPages使用后端在输出文档中的自己的页面上绘制每组饼图。

由于所有饼图共享相同的图例,我想在每张纸上只显示一个“共享”图例。我找到的解决方案如下所示:matplotlib - Legend in separate subplot 将每个饼图放在它自己的subplot中,然后在另一个窗格中生成一个“虚拟”饼图,生成一个图例,然后使用set_visible(False).

第一次循环迭代(即第一个 Excel 电子表格和第一页饼图)很好。然而,随后的循环产生了带有文本标签的图例,但没有彩色框。示例显示在以下 Imgur 链接中(抱歉,由于我是 Stackoverflow 的新手,所以我还不能发布图像)。http://i.imgur.com/0ssak1O.png

该问题似乎影响了PdfPages后端生成的输出,但影响默认的图形后端(TkAgg?不确定 Spyder 默认使用哪一个)。PDFfile.savefig()您可以通过注释掉和取消注释在下面的精简脚本中看到这一点plt.show()

因此,总而言之,这个问题似乎源于.set_visible()跨循环“记住”的方法......但它影响PdfPages后端,而不是图形后端。我完全困惑,但希望这篇文章对其他人有意义。任何帮助表示赞赏:-)

import xlrd, numpy as np, matplotlib.pyplot as plt
from matplotlib.backends.backend_pdf import PdfPages


PDFfile = PdfPages('output.pdf')


for i in range(4):

        pieData = [
                   [1, 2, 3, 4],
                   [5, 6, 7, 8],
                   [9, 0, 1, 2]]

        pieSliceLabels = ['A', 'B', 'C', 'D']
        pieLabels = ['1', '2', '3']

        # now, generate some pie plots

        plt.figure(0, figsize=(6,2))

        numPies = len(pieLabels)  

        for thisPie in range(numPies):
                ax = plt.subplot(1,4,1+thisPie)
                plt.title(pieLabels[thisPie])                
                fracs = pieData[thisPie]
                plt.pie(fracs)



        # Since all three pie plots share the same data labels, I'd rather just
        # generate a single legend that they all share.
        # The method I used comes from here:
        # https://stackoverflow.com/questions/11140311/matplotlib-legend-in-separate-subplot

        # First, generate a "dummy pie" containing same data as last pie.
        plt.subplot(1,4,4)
        DummyPie = plt.pie(fracs)

        # next, generate a big ol' legend
        plt.legend(pieSliceLabels, loc='center',prop={'size':'small'})

        # finally, hide the pie.
        for Pieces in DummyPie:
                for LittlePiece in Pieces:
                    LittlePiece.set_visible(False)



        # NOW, HERE'S WHERE IT GETS WEIRD...

        # Leave the following line uncommented:
        PDFfile.savefig()
        # ... and a PDF is generated where the legend colors are shown
        # properly on the first page, but not thereafter!

        # On the other hand.... comment out "PDF.savefig()" above, and
        # uncomment the following line:
        # plt.show()
        # ...and the figures will be generated onscreen, WITHOUT the legend
        # problem!!



PDFfile.close()
4

1 回答 1

0

奇怪的是它只显示在PdfPages后端,但这是因为你在没有清除它的情况下重复使用同一个图形对象。

最好每次都制作一个新人物。如果您要在 pdf 中包含大量页面,那么只使用一个图形可能更有意义,但每次都清除它(例如plt.clf()fig.clf())。

试着打电话:

plt.figure(figsize=(6,2))

代替:

plt.figure(0, figsize=(6,2))

此外,如果您不希望饼图看起来“被压扁”,请务必将子图的纵横比设置为 1 (ax.axis('equal')plt.axis('equal').


编辑:这是使用 matplotlib 的 OO 接口的示例。它使其中一些更容易跟踪,imo:

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

pie_data = [[1, 2, 3, 4],
            [5, 6, 7, 8],
            [9, 0, 1, 2]]
pie_slice_labels = ['A', 'B', 'C', 'D']
pie_labels = ['1', '2', '3']

PDFfile = PdfPages('output.pdf')

for i in range(4):
    fig, axes = plt.subplots(ncols=len(pie_labels) + 1, figsize=(6,2))

    for ax, data, label in zip(axes, pie_data, pie_labels):
        wedges, labels = ax.pie(data)
        ax.set(title=label, aspect=1)

    # Instead of creating a dummy pie, just use the artists from the last one.
    axes[-1].legend(wedges, pie_slice_labels, loc='center', fontsize='small')
    axes[-1].axis('off')
    # Alternately, you could do something like this to place the legend. If you
    # use this, you should remove the +1 from ncols above. 
    # fig.legend(wedges, pie_slice_labels, loc='center right', fontsize='small')
    # fig.subplots_adjust(right=0.8) # Make room for the legend.

    PDFfile.savefig()

PDFfile.close()
于 2013-02-01T13:01:52.457 回答