可变大小图形的图例位置

Posted

技术标签:

【中文标题】可变大小图形的图例位置【英文标题】:Legend position for figures with variable size 【发布时间】:2021-07-01 14:31:47 【问题描述】:

我的绘图函数每年为不同大小的数据创建水平条。我必须更改每组子图的图形大小。 我需要将我的两个图例放在 x 轴标签下方每个图形的下中心。位置需要根据图形大小而变化并保持一致。所以对于所有制作的人物,图例看起来像这样figure。

找到我的数据框here 的 sn-p。我试图尽可能地简化代码,我知道情节缺少一些元素,但我只想得到我的问题的答案,而不是在这里创建一个完美的情节。我知道我可能需要为我的锚定边界框创建一个变量,但我不知道如何。这是我的代码:

def plot_bars(data,ax):
    """ Plots a single chart of work plan for a specific routeid
    data: dataframe with section length and year
    Returns: None"""
    ax.barh(df['year'], df['sec_len'] , left = df['sec_begin'])
    ax.set_yticklabels('')
def plot_fig(df):
    # Draw the plots
    ax_set = df[['routeid','num_bars']].drop_duplicates('routeid')
    route_set = ax_set['routeid'].values
    h_ratios = ax_set['num_bars'].values
    len_ratio = h_ratios.sum()/BARS_PER_PAGE # Global constant set to 40 based on experiencing 

    fig, axes = plt.subplots(len(route_set), 1, squeeze=False, sharex=True
                           , gridspec_kw='height_ratios':h_ratios
                           , figsize=(10.25,7.5*len_ratio))
    
    for i, r in enumerate(route_set):
            plot_bars(df[df['routeid']==r], axes[i,0])
    plt.xlabel('Section length')
    ## legends
    fig.legend(labels=['Legend2'], loc=8, bbox_to_anchor=(0.5, -0.45))

    fig.legend( labels=['Legend1'], loc = 8, bbox_to_anchor=(0.5, -0.3))

    ## Title
    fig.suptitle('title', fontsize=16, y=1)
    fig.subplots_adjust(hspace=0, top = 1-0.03/len_ratio)

for df in df_list:
    plot_fig(df)

问题是当图形大小发生变化时,图例会像这些图片一样移动:

here

here

【问题讨论】:

【参考方案1】:

我认为问题归结为相对于 xlabel 具有正确的相对位置,因此您需要使用 xlabel 的位置和轴的高度/宽度来计算 bbox_to_anchor 是正确的。像这样的:


fig, (ax, ax1) = plt.subplots(nrows=2, figsize=(5, 4), gridspec_kw='height_ratios':[4, 1])


ax.plot(range(10), range(10), label="myLabel")
ax.set_xlabel("xlabel")

x, y = ax.xaxis.get_label().get_position() # position of xlabel
h, w = ax.bbox.height, ax.bbox.width # height and width of the Axes

leg_pos = [x + 0 / w, y - 55 / h] # this needs to be adjusted according to your needs
fig.legend(loc="lower center", bbox_to_anchor=leg_pos, bbox_transform=ax.transAxes)

plt.show()

【讨论】:

因为需要两个图例,所以不能使用ax.legend。我相信一个轴只能有一个图例。我必须使用问题中所述的fig.legend,然后设置它的bbox_transform = ax1.transAxes。之后它完美地工作了。 @krm 请编辑您的答案,以便我将其设置为正确答案。 完成!如果您确实想在Axes 上使用多个图例,有一种方法:参见riptutorial.com/matplotlib/example/32429/…。但你的方式似乎肯定更好

以上是关于可变大小图形的图例位置的主要内容,如果未能解决你的问题,请参考以下文章

Python+matplotlib可视化设置图例4个精选案例

Python+matplotlib可视化设置图例4个精选案例

(完美解决)matplotlib图例(legend)如何自由设置其位置大小以及样式。

按面板右侧微调ggplot大小和图例位置

《R语言实战》自学笔记16-图形图例

echarts 定制legend内容,显示和位置