Python 为什么我的matplotlib故事情节总是被删掉?

Python 为什么我的matplotlib故事情节总是被删掉?,python,python-2.7,matplotlib,Python,Python 2.7,Matplotlib,我正在寻找一种编程方式,将图例添加到我的matplotlib绘图的外部,以便在将图形保存到svg文件时不会对其进行裁剪。在以下示例中,您将看到x轴标签以及图例在生成的svg图片中被裁剪: import matplotlib import matplotlib.backends.backend_svg fig = matplotlib.figure.Figure(figsize=(8,2)) subplot = fig.add_axes([0.1, 0.2, 0.8, 0.75], xlabel

我正在寻找一种编程方式,将图例添加到我的
matplotlib
绘图的外部,以便在将图形保存到svg文件时不会对其进行裁剪。在以下示例中,您将看到x轴标签以及图例在生成的svg图片中被裁剪:

import matplotlib
import matplotlib.backends.backend_svg

fig = matplotlib.figure.Figure(figsize=(8,2))
subplot = fig.add_axes([0.1, 0.2, 0.8, 0.75], xlabel='x_label')

Sig_1, = subplot.plot([1,2,3], [1,2,3])
Sig_2, = subplot.plot([1,2,3], [4,5,6])

legend = subplot.legend([Sig_1, Sig_2], ['y_label_1', 'y_label_2'],loc='upper right',borderpad=0.06,handletextpad=0.1,handlelength=1.5,bbox_to_anchor=(1.0, 1.235),frameon=False,columnspacing=1.0,ncol=2)

fig.set_canvas(matplotlib.backends.backend_svg.FigureCanvasSVG(fig))
fig.savefig('C:\plot.svg')
fig.clear()

理想情况下,我希望创建绘图,然后通过某种方法扩展画布,而不裁剪现有空白,以使绘图更紧凑。只有画布的那些区域会被延伸,否则会导致裁剪元素,如外部图例或轴标签我唯一的限制是不能使用
pyplot

当然,我可以调整图例属性,直到找到一个配置,该配置可能正好适用于该绘图。但我希望有一个通用的方法来解决任何类型的情节


非常感谢您的回答。

bbox\u inches='tight'
传递到
savefig()
不起作用吗

import matplotlib
import matplotlib.backends.backend_svg

fig = matplotlib.figure.Figure(figsize=(8,2))
subplot = fig.add_axes([0.1, 0.2, 0.8, 0.75], xlabel='x_label')

Sig_1, = subplot.plot([1,2,3], [1,2,3])
Sig_2, = subplot.plot([1,2,3], [4,5,6])

legend = subplot.legend([Sig_1, Sig_2], ['y_label_1', 'y_label_2'],loc='upper right',borderpad=0.06,handletextpad=0.1,handlelength=1.5,bbox_to_anchor=(1.0, 1.235),frameon=False,columnspacing=1.0,ncol=2)

fig.set_canvas(matplotlib.backends.backend_svg.FigureCanvasSVG(fig))
fig.savefig('C:\plot.jpg', bbox_inches='tight')
fig.clear()

如果我理解正确,您希望将
的“紧”选项限制为仅展开图形,而不是裁剪图形。由于没有此类预定义选项,您需要首先计算紧框,并仅使用其中小于/大于地物范围的值

import matplotlib.figure
from matplotlib.backends.backend_agg import FigureCanvasAgg
from matplotlib.transforms import Bbox

fig = matplotlib.figure.Figure(figsize=(8,2))
subplot = fig.add_axes([0.1, 0.2, 0.8, 0.75], xlabel='x_label')

Sig_1, = subplot.plot([1,2,3], [1,2,3])
Sig_2, = subplot.plot([1,2,3], [4,5,6])

legend = subplot.legend([Sig_1, Sig_2], ['y_label_1', 'y_label_2'],
                        loc='upper right',borderpad=0.06,handletextpad=0.1,
                        handlelength=1.5,bbox_to_anchor=(1.0, 1.235),
                        frameon=False,columnspacing=1.0,ncol=2)

canvas = FigureCanvasAgg(fig)

fig.canvas.draw()
renderer = fig._cachedRenderer
tightbox = fig.get_tightbbox(renderer)
w,h = fig.get_size_inches()
bbox = Bbox.from_extents(min(tightbox.x0,0), min(tightbox.y0,0),
                         max(tightbox.x1,w), max(tightbox.y1,h))

fig.savefig('cropplot.png', bbox_inches=bbox, facecolor="#fff9e3")

在这里,我将图形背景设置为彩色,以便很好地看到边界。 还请注意,我用通常的agg画布替换了svg画布,因为否则就没有可用的渲染器

以下代码适用于较旧版本的
matplotlib
。它将保持图形宽度不变,并且仅在垂直方向上展开图形

import matplotlib.figure
from matplotlib.backends.backend_agg import FigureCanvasAgg

def CreateTightBbox(fig):
    from matplotlib.transforms import Affine2D, Bbox, TransformedBbox
    from matplotlib import rcParams

    w,h = fig.get_size_inches()
    renderer = fig._cachedRenderer
    bbox_artists = fig.get_default_bbox_extra_artists()
    bbox_filtered = []

    for a in bbox_artists:
        bbox = a.get_window_extent(renderer)
        if a.get_clip_on():
            clip_box = a.get_clip_box()
            if clip_box is not None:
                bbox = Bbox.intersection(bbox, clip_box)
            clip_path = a.get_clip_path()
            if clip_path is not None and bbox is not None:
                clip_path = clip_path.get_fully_transformed_path()
                bbox = Bbox.intersection(bbox, clip_path.get_extents())
        if bbox is not None and (bbox.width != 0 or bbox.height != 0):
            bbox_filtered.append(bbox)

    if bbox_filtered:
        _bbox = Bbox.union(bbox_filtered)
        trans = Affine2D().scale(1.0 / fig.dpi)
        bbox_extra = TransformedBbox(_bbox, trans)
        bbox_inches = Bbox.union([fig.bbox_inches, bbox_extra])

    pad = rcParams['savefig.pad_inches']
    bbox_inches = bbox_inches.padded(pad)
    bbox = Bbox.from_extents(0, min(bbox_inches.y0,0), w, max(bbox_inches.y1,h))

    return bbox


#create the figure
fig = matplotlib.figure.Figure(figsize=(8,2))
subplot = fig.add_axes([0.1, 0.2, 0.8, 0.75], xlabel='x_label')

Sig_1, = subplot.plot([1,2,3], [1,2,3])
Sig_2, = subplot.plot([1,2,3], [4,5,6])

legend = subplot.legend([Sig_1, Sig_2], ['y_label_1', 'y_label_2'],
                        loc='upper right',borderpad=0.06,handletextpad=0.1,
                        handlelength=1.5,bbox_to_anchor=(1.0, 1.235),
                        frameon=False,columnspacing=1.0,ncol=2)

#set the canvas
canvas = FigureCanvasAgg(fig)
fig.canvas.draw()
w,h = fig.get_size_inches()

#create tight bbox
bbox = CreateTightBbox(fig)

#print bbox
fig.savefig('cropplot.png', bbox_inches=bbox, facecolor="#fff9e3")

我也使用了这些紧密()选项,但它们的行为并不总是如预期的那样(例如,更改了黑框的尺寸)。当我以前遇到类似问题时,这个答案对我有帮助:不幸的是,这个答案依赖于pyplot。
子图。legend()吗
不使用
bbox\u to\u锚定
参数?此解决方案运行良好。它不会更改内容的维度,而是放大画布。这正是问题所要问的。非常感谢。看起来已经很有希望了。但是如果我运行你的代码,传奇就不再可见了。这很不幸。显示的图像是通过代码直接创建的。您正在使用哪个matplotlib版本?如何运行代码?我使用的是2.0.2版,并使用PyScripter运行代码。我将在一天中切换系统,并测试不同的环境。奇怪。如果我使用的是matplotlib 1.5.3,那么代码生成的绘图看起来与我问题中的绘图完全相同(只有黄色背景)。因此,对于不同的matplotlib版本,代码的行为似乎有所不同。因此,我使用matplotlib 2.2.3和3.0.0对代码进行了测试,效果良好。您是否有机会更新matplotlib,或者希望我为这些旧版本找到解决方案?