Matplotlib savefig与情节外的传奇

nib*_*shi 34 python matplotlib legend

阅读下面的文章,我设法将一个传奇放在外面.

码:

import matplotlib.pyplot as pyplot

x = [0, 1, 2, 3, 4]
y = [xx*xx for xx in x]

fig = pyplot.figure()
ax  = fig.add_subplot(111)

box = ax.get_position()
ax.set_position([box.x0, box.y0, box.width*0.8, box.height])

ax.plot(x, y)
leg = ax.legend(['abc'], loc = 'center left', bbox_to_anchor = (1.0, 0.5))
#pyplot.show()

fig.savefig('aaa.png', bbox_inches='tight')
Run Code Online (Sandbox Code Playgroud)

pyplot.show()显示正确的情节,外面有一个图例.但是当我将其保存为文件时fig.savefig(),图例会被截断.

一些谷歌搜索显示我作为变通方法添加这样bbox_extra_artists=[leg.legendPatch]bbox_extra_artists=[leg]savefig(),但既不工作.

这样做的正确方法是什么?Matplotlib版本为0.99.3.

谢谢.

Oz1*_*123 25

问题是,当您动态绘制时,会matplotlib自动确定边框以适合所有对象.保存文件时,事情不会自动完成,因此您需要指定图形的大小,然后指定轴对象的边界框.以下是更正代码的方法:

import matplotlib.pyplot as pyplot

x = [0, 1, 2, 3, 4]
y = [xx*xx for xx in x]

fig = pyplot.figure(figsize=(3,3))
ax  = fig.add_subplot(111)

#box = ax.get_position()
#ax.set_position([0.3, 0.4, box.width*0.3, box.height])
# you can set the position manually, with setting left,buttom, witdh, hight of the axis
# object
ax.set_position([0.1,0.1,0.5,0.8])
ax.plot(x, y)
leg = ax.legend(['abc'], loc = 'center left', bbox_to_anchor = (1.0, 0.5))

fig.savefig('aaa.png')
Run Code Online (Sandbox Code Playgroud)

  • 我知道matplotlib喜欢宣传所有东西都在用户的控制之下,但是传说中的这一切都太好了.如果我把传说放在外面,我显然希望它仍然可见.窗口应该只是缩放以适应而不是创建这个巨大的重新缩放麻烦.至少应该有一个默认的True选项来控制这种自动缩放行为.迫使用户通过一系列荒谬的重新渲染来尝试以控制的名义获得缩放数字,从而完成相反的操作. (45认同)
  • 您可以将其添加为功能请求,顺便说一句,您使用的是旧版本... (2认同)

tim*_*-oh 12

对于大多数情况,一个简单的修复案例是修改命令plt.savefig()

plt.savefig('your_figure.png', bbox_inches='tight')

这个解决方案已经在问题下面的评论中建议,但我忽略了这些,并在GitHub上的 matplotlib issues 中找到了它。为未阅读顶部评论的其他人保留此答案。

  • 为我工作,比上面简单得多! (3认同)

Nin*_*ing 11

虽然这种方法适用于图例,但是当有多个子图并且我们想要一个整体图例时,它似乎不能与figlegend一起使用.当savefig时,figlegend仍会被裁剪.我刚刚粘贴了我的临时解决方案,以防有人遇到这种情况.

import matplotlib.pyplot as plt

para = {
    ## this parameter will indicate the position of
    ## subplot within figure, but will not be shown
    ## if using bbox_inches='tight' when saving
    'figure.subplot.top': 0.5
}
#plt.rcParams.update(para)

fig = plt.figure()

ax=fig.add_subplot(221)
## only needed when what to manually control
## subplot ration
#ax.set_position([0.1,0.6,0.5, 0.4])
ax.plot([1,1,1])


ax=fig.add_subplot(222)
#ax.set_position([0.7,0.6,0.5, 0.4])
ax.plot([2,2,2])

ax=fig.add_subplot(223)
#ax.set_position([0.1,0.1,0.5, 0.4])
ax.plot([3,3,3])


ax=fig.add_subplot(224)
#ax.set_position([0.7,0.1,0.5, 0.4])
p1, = ax.plot([4,4,4])
p2, = ax.plot([2,3,2])

## figlegend does not work fine with tight bbox
## the legend always get cropped by this option
## even add bbox extra will not help
## had to use legend, and manually adjust it to
## arbitary position such as (0.3, 2.5)

## http://matplotlib.org/users/tight_layout_guide.html
## according to this link, tight layout is only
## an experimental feature, might not support figlegend

#lgd = plt.figlend(
lgd = plt.legend(
    [p1,p2],
    ['a', 'b'],
    ## by default, legend anchor to axis, but can
    ## also be anchored to arbitary position
    ## positions within [1,1] would be within the figure
    ## all numbers are ratio by default

    bbox_to_anchor=(-0.1, 2.5),

    ## loc indicates the position within the figure
    ## it is defined consistent to the same Matlab function 
    loc='center',

    ncol=2
    #mode="expand",
    #borderaxespad=0.
    )



#plt.show()

plt.savefig('temp.png', bbox_inches='tight')#, bbox_extra_artist=[lgd])
Run Code Online (Sandbox Code Playgroud)