保存PDF时的Matplotlib线宽

8
我有一个图形,其中一些非常精细的特征对线宽很敏感。我想将此图形保存为PDF,以便易于打印(即接收方不会进行缩放,只需Command+P即可)。但不幸的是,当我设置figsize=(8.5,11)以正确调整PDF的大小以供打印时,matplotlib会选择非常粗的默认线宽和文本大小,这会破坏图表(图例太大,条形图中的线条重叠)。如果我设置figsize=(17,22),在将PDF缩放50%以进行打印后,我会获得非常可行的默认线宽和文本大小。这是我一直在使用的解决方案,但由于政策的原因,该解决方案已变得无法使用,而且我真的不想每次更改时都在illustrator中缩放PDF。
如果我可以使用位图,那么通过将figsize设置为(17,22)并将dpi设置为目标dpi的一半,就可以实现所需的结果,但是对于PDFs而言,这样做行不通,因为dpi参数似乎被忽略了。我想要一个PDF,它:
  • 看起来像boxes_good.png(大小受限,线条细,文字小)
  • 尺寸为8.5x11英寸(或打印效果相同)
  • 可以在illustrator中编辑(不是位图包装的pdf)
  • 我不禁怀疑,在保存为PDF时,有一种简单的方法可以执行“双倍大小,半dpi”的技巧,但是我放弃了尝试使其工作,并开始尝试直接操纵线宽和文字大小。我成功地修改了文字大小,但没有修改线宽。下面是我尝试过的内容记录:
    # Tried:
    # fig.set_size_inches(17,22)
    # fig.savefig('boxes.pdf', dpi=100,150,300)
    #   dpi parameter has no effect on linewidth, text size, or the PDF's dimensions
    # 'markerscale=.5' on plt.legend and pax.legend
    #   no effect
    # mp.rcParams['font.size']=8
    #   worked! made text smaller, now for linewidth...
    # mp.rcParams['lines.linewidth']=5
    #   no effect
    # fig.set_linewidth(5)
    #   no effect
    # pax.axhline(linewidth=5)
    #   only changes x axis not box surrounding subplot
    # fig.set_size_inches(8.5,11) immediately before plt.savefig('boxes.pdf')
    #   identical results to calling plt.figure(figsize=(8.5,11)) in the first place
    
    # I tried passing plt.figure(figsize=(17,22)) and swapping it to 8.5x11 using
    # fig.set_size_inches right before saving, but the lines were thick and the text
    # was large in the PDF, exactly as if I had set figsize=(8.5,11) to begin with
    

    这是源代码文件(我已将图表精简到必要的部分,因此显而易见的样式解决方法可能不可行)。
    import numpy as np
    import matplotlib as mp
    import matplotlib.pyplot as plt
    
    x = np.arange(200)
    bottom_red_bar = -np.random.random(200)
    bottom_black_bar = np.random.random(200) * bottom_red_bar
    
    fig = plt.figure()
    for subplotnum in [1,2,3]:
        pax = plt.subplot(310+subplotnum)
        pax.set_ylim([-1,1])
        bot_rb = pax.bar(x,         bottom_red_bar,1,color='r')
        bot_bb = pax.bar(x+(1-.3)/2,bottom_black_bar,.3,color='k')
        pax.legend([bot_rb,bot_bb],['Filler Text 1','Filler Text 2'],loc=4)
    
    fig.set_size_inches(8.5,11)
    fig.savefig('boxes_bad.png',dpi=300)  # Lines are too thick
    
    fig.set_size_inches(17,22)
    fig.savefig('boxes_good.png',dpi=150)  # Lines are just right
    
    fig.set_size_inches(8.5,11)
    plt.savefig('boxes.pdf')  # Lines are too thick
    
    fig.set_size_inches(17,22) # Lines are just right
    plt.savefig('boxes.pdf')   # but the PDF needs scaling before printing
    

    我需要一种方法来调整整个图形的线宽,或者一种方法让matplotlib保存pdf时使用与figsize不同的尺寸元数据。有什么建议吗?

    2个回答

    9

    谢谢 Marius,我会在获得所需的15个声望值后立即点赞。虽然您的 rcParams 没有完全符合我的需求,但是 rcParams 是正确的查找位置,因此我通过 rcParams.keys() 列出了包含“linewidth”的 rcParams:

    >>> [s for s in mp.rcParams.keys() if 'linewidth' in s]
    ['axes.linewidth', 'grid.linewidth', 'lines.linewidth', 'patch.linewidth']
    

    经过一些实验,我匹配了每个参数所控制的内容:
    mp.rcParams['axes.linewidth']:整个图形周围的正方形(不是刻度线,也不是y=0线)
    mp.rcParams['grid.linewidth']:没有测试,可能是网格线宽度
    mp.rcParams['lines.linewidth']:使用pyplot.plot制作的折线图的宽度
    mp.rcParams['patch.linewidth']:包括pyplot.bar图的条形、图例以及条形图的图例标签的矩形轮廓线的宽度
    mp.rcParams['xtick.minor.width']:小刻度线的线宽(yticks类似)
    mp.rcParams['xtick.major.width']:大刻度线的线宽(yticks类似)

    我最终采用的特定解决方案是:

    mp.rcParams['axes.linewidth'] = .5
    mp.rcParams['lines.linewidth'] = .5
    mp.rcParams['patch.linewidth'] = .5
    

    7
    我建议您通过rcParams(或您的matplotlibrc文件)调整参数,例如linewidth:
    # mp.rcParams['figure.figsize'] = fig_size  # set figure size
    mp.rcParams['font.size'] = font_size
    mp.rcParams['axes.labelsize'] = font_size
    mp.rcParams['axes.linewidth'] = font_size / 12.
    mp.rcParams['axes.titlesize'] = font_size
    mp.rcParams['legend.fontsize'] = font_size
    mp.rcParams['xtick.labelsize'] = font_size
    mp.rcParams['ytick.labelsize'] = font_size
    

    我通常使用标准的figure.figsize,大小为(8,6),并在轴对象中使用线宽为字体大小的1/12(例如,当我将图表包括在双栏论文中时,font_size=16)。请记住,矢量图形并不意味着所有线条和字母在缩放时始终具有相同的大小。这意味着您可以进行缩放而不会失去质量或清晰度(粗略地说)。

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接