阅读以下文章,我设法将一个传奇放在情节之外。
代码:
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')
pyplot.show()
显示正确的情节,外面有一个图例。但是当我将其保存为fig.savefig()
的文件时,图例会被截断。
一些Google搜索显示了我的解决方法,例如将bbox_extra_artists=[leg.legendPatch]
或bbox_extra_artists=[leg]
添加到savefig()
,但都没有效果。
这样做的正确方法是什么? Matplotlib版本为0.99.3。
感谢。
答案 0 :(得分:24)
问题在于,当您动态绘制时,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')
答案 1 :(得分: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])
答案 2 :(得分:0)
如果所有其他方法都失败了,我使用Inkscape的边界框功能来处理matplotlib输出中我称之为持久性错误的内容。如果您正在运行GNU / Linux,只需保存Matplotlib为PDF格式提供的内容,然后将其发送到以下内容
def tightBoundingBoxInkscape(pdffile,use_xvfb=True):
"""Makes POSIX-specific OS calls. Preferably, have xvfb installed, to avoid any GUI popping up in the background. If it fails anyway, could always resort to use_xvfb=False, which will allow some GUIs to show as they carry out the task
pdffile: the path for a PDF file, without its extension
"""
usexvfb='xvfb-run '*use_xvfb
import os
assert not pdffile.endswith('.pdf')
os.system("""
inkscape -f %(FN)s.pdf -l %(FN)s_tmp.svg
inkscape -f %(FN)s_tmp.svg --verb=FitCanvasToDrawing \
--verb=FileSave \
--verb=FileQuit
inkscape -f %(FN)s_tmp.svg -A %(FN)s-tightbb.pdf
"""%{'FN':pdffile}