【问题标题】:Showing legend under matplotlib plot with varying number of plots在 matplotlib 图下显示图例,图例数量不同
【发布时间】:2018-05-12 09:15:11
【问题描述】:

我正在开发一个程序,该程序允许用户在轴上放置不同数量的图。我需要显示图例,而且情节标签很长,所以我认为最好在情节下显示这个。当我以前这样做的时候,我总是把情节缩小一点,把图例放在情节下面。现在有不同数量的图,这并不那么简单,因为我找不到一个很好的公式来确定将图缩小多少以及将图例放多远,这样它就不会被切断或重叠轴。

我编写了一个示例代码来演示我目前正在做的事情,这很难看。我目前正在检查图中有多少项目,并尝试手动优化轴收缩和图例偏移参数,然后做了一个大的if 循环以使用手动优化的值。它们没有针对此示例代码进行优化,但我认为它演示了我在做什么。

import matplotlib.pyplot as plt
import numpy as np

def find_scales(legendData):
        leg_len = len(legendData)
        if leg_len == 0:
            height_scale = 1
            legend_offset = 0
        elif leg_len == 1:
            height_scale = 0.96
            legend_offset = -0.18
        elif leg_len == 2:
            height_scale = 0.95
            legend_offset = -0.25
        elif leg_len == 3:
            height_scale = 0.94
            legend_offset = -0.35
        elif leg_len == 4:
            height_scale = 0.93
            legend_offset = -0.45
        elif leg_len == 5:
            height_scale = 0.93
            legend_offset = -0.57
        elif leg_len == 6:
            height_scale = 0.93
            legend_offset = -0.68
        elif leg_len == 7:
            height_scale = 0.93
            legend_offset = -0.82
        elif leg_len == 8:
            height_scale = 0.93
            legend_offset = -0.98
        elif leg_len == 9:
            height_scale = 0.92
            legend_offset = -1.3
        elif leg_len == 10:
            height_scale = 0.92
            legend_offset = -1.53
        else:
            height_scale = 0.92
            legend_offset = -1.8
        return height_scale, legend_offset

num_plots = 3
x_range = np.arange(10)

fig,ax = plt.subplots()

for i in range(num_plots):
    ax.plot(x_range, np.random.rand(10))

legend_labels = ['a','b','c','d','e','f','g','h','i','j'][:num_plots]

box = ax.get_position()

height_scale, legend_offset = find_scales(legend_labels)

ax.set_position([box.x0, box.y0 + box.height * (1-height_scale), #left, bottom, width, height
             box.width, box.height * height_scale])

ax.legend(legend_labels, loc=3, bbox_to_anchor=(0,legend_offset), borderaxespad=0.)

plt.show()

我希望有更好的方法来做到这一点。我希望图例位于轴下方。我不能让图例与轴或 x 标签重叠。我不能因为太低和不合身而让传说被切断。有没有办法让轴和图例自动调整大小以适应图形?

【问题讨论】:

  • 您(几乎)线性缩放height_scalelegend_offset 作为leg_len 的函数)。因此,只需编写一个为您计算它们的函数并丢弃所有 if/elif 块。
  • 我猜○this question 的答案是你想要的(它只是把图例放在上面而不是下面)。
  • @PaulH 我花时间试图找到一个缩放函数,但它似乎比线性缩放函数更复杂,这就是我需要具体计算每个案例的原因。
  • @wwii 这是我工作的帖子。它没有解决图例中项目数量可变的问题。

标签: python matplotlib


【解决方案1】:

一种纠正坐标轴位置的方法,使图例有足够的空间显示在这个问题的答案中:Creating figure with exact size and no padding (and legend outside the axes)

对于位于底部的图例,解决方案要简单得多。本质上,您只需要从轴高度中减去图例高度,然后将轴移动到顶部的图例高度。

import matplotlib.pyplot as plt 

fig = plt.figure(figsize = [3.5,2]) 
ax = fig.add_subplot(111)
ax.set_title('title')
ax.set_ylabel('y label')
ax.set_xlabel('x label')
ax.plot([1,2,3], marker="o", label="quantity 1")
ax.plot([2,1.7,1.2], marker="s", label="quantity 2")

def legend(ax, x0=0.5,y0=0, pad=0.5,**kwargs):
    otrans = ax.figure.transFigure
    t = ax.legend(bbox_to_anchor=(x0,y0), loc=8, bbox_transform=otrans,**kwargs)
    ax.figure.tight_layout(pad=pad)
    ax.figure.canvas.draw()
    tbox = t.get_window_extent().transformed( ax.figure.transFigure.inverted() )
    bbox = ax.get_position()
    ax.set_position([bbox.x0, bbox.y0+tbox.height,bbox.width, bbox.height-tbox.height]) 

legend(ax,y0=0, borderaxespad=0.2)

plt.savefig(__file__+'.pdf')
plt.show()

【讨论】:

    猜你喜欢
    • 2020-12-09
    • 2016-12-29
    • 1970-01-01
    • 1970-01-01
    • 2015-05-24
    • 2021-03-27
    • 2023-01-18
    • 2020-02-05
    • 1970-01-01
    相关资源
    最近更新 更多