【问题标题】:Left and Right alignment in pyplot legend [duplicate]pyplot图例中的左右对齐[重复]
【发布时间】:2020-10-13 09:26:24
【问题描述】:

在我的情节图例中,我还想在“正常”图例旁边显示函数的(最佳)值。

我目前的尝试:

我是这样编码的:

for j, pol in enumerate(pols):
        val = vidics[1][pol]
        axis[1,i].axhline(val, label=f'{pol_label[j]}: {val:.1f}', color='r', linestyle = st[j])
    
sns.lineplot(x= 'variable',y='value',data=pd.DataFrame(r_FI_3).melt(), label = f'FI: {score_FI_3:.1f}', ax=axis[1,i])
sns.lineplot(x= 'variable',y='value',data=pd.DataFrame(r_PO_3).melt(), label = f'PO: {score_PO_3:.1f}', ax=axis[1,i])

for 循环创建水平线。 sns 线创建蓝色和橙色线。

我想要的是分数(图例中的值)是右对齐的。 通过在 fstrings 中添加空格来手动执行此操作是不可行的,因为我已经在一个循环中填充了许多这些小图。我尝试在 fstring 中添加空格/填充,例如第二个 sns 行的以下标签:

label = f'{"PO": < 10}: {score_PO_3:.1f}'

在字符串长度为 10 之前添加空格(我认为?)。我想如果我对所有字符串都这样做,右边会对齐,但由于字符串中并非所有字符都具有相同的宽度,这也不起作用并且看起来很丑。

有什么想法吗?

另外,一个更大的代码,供参考:

pols = ['optimal', 'preventive', 'corrective']
pol_label = ['VIoptm', 'VIprev', 'VIcorr']
vidics = [vi2, vi3, vi4]

labels = ['4', '5', '6', '7']

dics2_PO = [s4_PO_2, s5_PO_2, s6_PO_2, s7_PO_2]
dics2_FI = [s4_FI_2, s5_FI_2, s6_FI_2, s7_FI_2]

dics3_PO = [s4_PO_3, s5_PO_3, s6_PO_3, s7_PO_3]
dics3_FI = [s4_FI_3, s5_FI_3, s6_FI_3, s7_FI_3]

dics4_PO = [s4_PO_4, s5_PO_4, s6_PO_4, s7_PO_4]
dics4_FI = [s4_FI_4, s5_FI_4, s6_FI_4, s7_FI_4]

figlabel = [['a', 'b', 'c', 'd'], ['e', 'f', 'g', 'h'], ['i', 'j', 'k','l']]

fig, axis = plt.subplots(3,4, figsize=(17,10))

st = ['-', '-.' , ':']

for i in range(4):
    # 2 comp
    dic2FI = dics2_FI[i]
    dic2PO = dics2_PO[i]
    
    r_FI_2 = dic2FI['ar']
    r_PO_2 = dic2PO['ar']
    
    t_PO_2 = np.array(dic2PO['t']).sum()
    
    best_r_FI = np.array(dic2FI['best_r'])
    best_r_PO = np.array(dic2PO['best_r'])
    
    score_FI_2 = best_r_FI.mean()
    score_PO_2 = best_r_PO.mean()
    
    sd_FI_2 = best_r_FI.std()
    sd_PO_2 = best_r_PO.std()
    
    print(f'2comp, agent {labels[i]} FI : {score_FI_2:.1f} +- {sd_FI_2:.1f} ')
    print(f'2comp, agent {labels[i]} PO : {score_PO_2:.1f} +- {sd_PO_2:.1f} ')
    print(f'2comp, agent {labels[i]} PO , time: {t_PO_2:.0f}')
    
    for j, pol in enumerate(pols):
        val = vidics[0][pol]
        axis[0,i].axhline(val, label=f'{pol_label[j]}: {val:.1f}', color='r', linestyle = st[j])
    
    sns.lineplot(x= 'variable',y='value',data=pd.DataFrame(r_FI_2).melt(), label = f'FI: {score_FI_2:.1f}', ax=axis[0,i])
    sns.lineplot(x= 'variable',y='value',data=pd.DataFrame(r_PO_2).melt(), label = f'PO: {score_PO_2:.1f}', ax=axis[0,i])
    
    axis[0,i].set_ylim((-30,-8))
    axis[0,i].legend(loc='lower right')
    axis[0,i].set_xlabel('Training Iterations')
    axis[0,i].set_xticks([4,9])
    axis[0,i].set_xticklabels(['50k', '100k'])
    axis[0,i].set_title(f'{figlabel[0][i]}) 2 comp, agent {labels[i]}')
    if i==0:
        axis[0,i].set_ylabel('Average Reward')
    else:
        axis[0,i].set_ylabel('')
            

    
    # 3 comp
    dic3FI = dics3_FI[i]
    dic3PO = dics3_PO[i]
    
    r_FI_3 = dic3FI['ar']
    r_PO_3 = dic3PO['ar']
    
    t_PO_3 = np.array(dic3PO['t']).sum()
    
    best_r_FI = np.array(dic3FI['best_r'])
    best_r_PO = np.array(dic3PO['best_r'])
    
    score_FI_3 = best_r_FI.mean()
    score_PO_3 = best_r_PO.mean()
    
    sd_FI_3 = best_r_FI.std()
    sd_PO_3 = best_r_PO.std()
    
    print(f'3comp, agent {labels[i]} FI : {score_FI_3:.1f} +- {sd_FI_3:.1f} ')
    print(f'3comp, agent {labels[i]} PO : {score_PO_3:.1f} +- {sd_PO_3:.1f} ')
    print(f'3comp, agent {labels[i]} PO , time: {t_PO_3:.0f}')
    
    for j, pol in enumerate(pols):
        val = vidics[1][pol]
        axis[1,i].axhline(val, label=f'{pol_label[j]}: {val:.1f}', color='r', linestyle = st[j])
    
    sns.lineplot(x= 'variable',y='value',data=pd.DataFrame(r_FI_3).melt(), label = f'FI: {score_FI_3:.1f}', ax=axis[1,i])
    sns.lineplot(x= 'variable',y='value',data=pd.DataFrame(r_PO_3).melt(), label = f'PO: {score_PO_3:.1f}', ax=axis[1,i])
    
    axis[1,i].set_ylim((-60,-15))
    axis[1,i].legend(loc='lower right')
    axis[1,i].set_xlabel('Training Iterations')
    axis[1,i].set_xticks([4,9])
    axis[1,i].set_xticklabels(['100k', '200k'])
    axis[1,i].set_title(f'{figlabel[1][i]}) 3 comp, agent {labels[i]}')
    if i==0:
        axis[1,i].set_ylabel('Average Reward')
    else:
        axis[1,i].set_ylabel('')
   
    
    
     # 4 comp
    dic4FI = dics4_FI[i]
    dic4PO = dics4_PO[i]
    
    r_FI_4 = dic4FI['ar']
    r_PO_4 = dic4PO['ar']
    
    t_PO_4 = np.array(dic4PO['t']).sum()
    
    best_r_FI = np.array(dic4FI['best_r'])
    best_r_PO = np.array(dic4PO['best_r'])
    
    score_FI_4 = best_r_FI.mean()
    score_PO_4 = best_r_PO.mean()
    
    sd_FI_4 = best_r_FI.std()
    sd_PO_4 = best_r_PO.std()
    
    print(f'4comp, agent {labels[i]} FI : {score_FI_4:.1f} +- {sd_FI_4:.1f} ')
    print(f'4comp, agent {labels[i]} PO : {score_PO_4:.1f} +- {sd_PO_4:.1f} ')
    print(f'4comp, agent {labels[i]} PO , time: {t_PO_4:.0f}')
    
    for j, pol in enumerate(pols):
        val = vidics[2][pol]
        axis[2,i].axhline(val, label=f'{pol_label[j]}: {val:.1f}', color='r', linestyle = st[j])
    
    sns.lineplot(x= 'variable',y='value',data=pd.DataFrame(r_FI_4).melt(), label = f'FI: {score_FI_4:.1f}', ax=axis[2,i])
    sns.lineplot(x= 'variable',y='value',data=pd.DataFrame(r_PO_4).melt(), label = f'PO: {score_PO_4:.1f}', ax=axis[2,i])
    
    axis[2,i].set_ylim((-70,-20))
    axis[2,i].legend(loc='lower right')
    axis[2,i].set_xlabel('Training Iterations')
    axis[2,i].set_xticks([4,9])
    axis[2,i].set_xticklabels(['200k', '400k'])
    axis[2,i].set_title(f'{figlabel[2][i]}) 4 comp, agent {labels[i]}')
    if i==0:
        axis[2,i].set_ylabel('Average Reward')
    else:
        axis[2,i].set_ylabel('')
    
   
    
    plt.tight_layout()

创建下图:

【问题讨论】:

    标签: python matplotlib legend


    【解决方案1】:

    看看你在哪里分配标签值:

    label=f'{pol_label[j]}: {val:.1f}'
    

    在这种格式中,所有内容都是左对齐的。它与例如:

    print('{:<2}: {:<8}'.format(*['label','value']))
    

    这意味着'左对齐所有内容,但让第一个单词的可用空格为 2(从左数),第二个单词的空格为 8'

    为了解决这个问题,我会尝试保持第一个单词左对齐,但第二个单词右对齐,给定适当的可用空间。在上面的行中,只需更改第二个符号,可能还有空格:

     print('{:<2}: {:>8}'.format(*['label','value']))
    

    实现(输出):

    label:      value
    

    (标签左对齐,值右对齐)

    reference

    【讨论】:

    • 请注意,这仅适用于等宽字体,它看起来不如标准比例字体。
    猜你喜欢
    • 1970-01-01
    • 2018-08-01
    • 2020-01-03
    • 2020-07-09
    • 1970-01-01
    • 2018-01-24
    • 2012-10-13
    • 2022-07-15
    • 1970-01-01
    相关资源
    最近更新 更多