Python之外的传说 – matplotlib

我试图在matplotlib的情节之外放置一个相当广泛的传奇.这个图例有很多条目,每个条目都可以很长(但我不确切知道多长时间).

显然,这很容易使用

legendHandle = plt.legend(loc = "center left",bBox_to_anchor = (1,0.5))

但问题是图例被窗户边缘切断了.我花了很长时间寻找解决方案.到目前为止我能找到的最好的事情是:

Box = ax.get_position()
ax.set_position([Box.x0,Box.y0,Box.width * 0.8,Box.height])
plt.legend(loc = "center left",0.5))

不幸的是,这并没有真正解决我的问题.由于应用于框宽的显式因子0.8,这仅适用于图形和图例宽度的一个特定组合.如果我调整图形窗口的大小,或者我的图例条目具有不同的长度,则它不起作用.

我只是不明白如何在图中放置一个图例是如此困难.我习惯了Matlab,就像它一样简单

legend('Location','eastoutside')

Python中是否有类似的东西我缺少?

解决方法

尝试了很多,这是我能想到的最好的:

from matplotlib.lines import Line2D
from matplotlib.gridspec import GridSpec
from enum import Enum

class Location(Enum):
    EastOutside = 1
    WestOutside = 2
    northOutside = 3
    SouthOutside = 4

class Legend:
    def __init__(self,figure,plotAxes,location: Location):
        self.figure = figure
        self.plotAxes = plotAxes
        self.location = location

        # Create a separate subplot for the legend. Actual location doesn't matter - will be modified anyway.
        self.legendAxes = figure.add_subplot(1,2,1)
        self.legendAxes.clear() # remove old lines
        self.legendAxes.set_axis_off()

        # Add all lines from the plot to the legend subplot
        for line in plotAxes.get_lines():
            legendLine = Line2D([],[])
            legendLine.update_from(line)
            self.legendAxes.add_line(legendLine)

        if self.location == Location.EastOutside:
            self.legend = self.legendAxes.legend(loc = "center left")
        elif self.location == Location.WestOutside:
            self.legend = self.legendAxes.legend(loc = "center right")
        elif self.location == Location.northOutside:
            self.legend = self.legendAxes.legend(loc = "lower center")
        elif self.location == Location.southOutside:
            self.legend = self.legendAxes.legend(loc = "upper center")
        else:
            raise Exception("UnkNown legend location.")

        self.UpdateSize()

        # Recalculate legend size if the size changes
        figure.canvas.mpl_connect('resize_event',lambda event: self.UpdateSize())

    def UpdateSize(self):
        self.figure.canvas.draw() # draw everything once in order to get correct legend size

        # Extract legend size in percentage of the figure width
        legendSize = self.legend.get_window_extent().inverse_transformed(self.figure.transfigure)
        legendWidth = legendSize.width
        legendHeight = legendSize.height

        # Update subplot such that it is only as large as the legend
        if self.location == Location.EastOutside:
            gridspec = GridSpec(1,width_ratios = [1 - legendWidth,legendWidth])
            legendLocation = 1
            plotLocation = 0
        elif self.location == Location.WestOutside:
            gridspec = GridSpec(1,width_ratios = [legendWidth,1 - legendWidth])
            legendLocation = 0
            plotLocation = 1
        elif self.location == Location.northOutside:
            gridspec = GridSpec(2,1,height_ratios = [legendHeight,1 - legendHeight])
            legendLocation = 0
            plotLocation = 1
        elif self.location == Location.southOutside:
            gridspec = GridSpec(2,height_ratios = [1 - legendHeight,legendHeight])
            legendLocation = 1
            plotLocation = 0
        else:
            raise Exception("UnkNown legend location.")

        self.legendAxes.set_position(gridspec[legendLocation].get_position(self.figure))
        self.legendAxes.set_subplotspec(gridspec[legendLocation]) # to make figure.tight_layout() work if that's desired

        self.plotAxes.set_position(gridspec[plotLocation].get_position(self.figure))
        self.plotAxes.set_subplotspec(gridspec[plotLocation]) # to make figure.tight_layout() work if that's desired

在我到目前为止测试的情况下,这使得图例或多或少都没有.用法是例如

import matplotlib.pyplot as plt

plt.ion()

figure = plt.figure()

plotAxes = figure.gca()

plotAxes.plot([1,3],[4,5,6],"b-",label = "Testaaaaaaaaaaaaaa 1")
plotAxes.plot([1,[6,4],"r-",label = "Test 2")

legend = Legend(figure,Location.EastOutside)

让我问一下我在评论中发布的问题……我将如何建议将其作为matplotlib开发人员的附加功能? (不是我的黑客,而是在图中有传说的本地方式)

相关文章

功能概要:(目前已实现功能)公共展示部分:1.网站首页展示...
大体上把Python中的数据类型分为如下几类: Number(数字) ...
开发之前第一步,就是构造整个的项目结构。这就好比作一幅画...
源码编译方式安装Apache首先下载Apache源码压缩包,地址为ht...
前面说完了此项目的创建及数据模型设计的过程。如果未看过,...
python中常用的写爬虫的库有urllib2、requests,对于大多数比...