如何在水平条形图的末端正确对齐注释?

时间:2020-08-18 23:30:37

标签: python matplotlib

我正在尝试正确对齐正在制作的条形图中的数字和百分比,以使它们恰好位于每个条形之后,但是这样做有些麻烦。我希望:“数字(%percentage)”恰好在每个小节之后(之间的间隔很小)。但是,现在在高位(Top 200、400)的情况下,数字和百分比已经比最低位(Top1-50)向前移动了更多。因此,当我尝试移动它们时,底部的缺少顶部的后面,导致外观不太美观。有办法解决这个问题吗?

代码:

import matplotlib
    import matplotlib.pyplot as plt
    import numpy as np
    plt.rcParams.update(plt.rcParamsDefault)
    
    labels = ["Top1", "Top3", "Top5", "Top10", "Top20", "Top50", "Top100", "Top200", "Top400"]
    native_shape_1000=[38, 42, 44, 48, 52, 57, 61, 66, 68] #Native pose (restr. to shapes & it0 1000)
    native_pocket_1000=[43, 51, 51,57,60,64,67,68,69] #Native pose (restr. to pocket residues)
    
    x = np.arange(len(native_shape_1000))  # the label locations
    width = 0.4  
    fig, axes = plt.subplots(2,2, figsize=(12,8), sharey= False, sharex=False)
    axes= axes.flatten()
    rects1=axes[0].barh(x - width/2, native_shape_1000, width, label=' Restraints to rank 1 \n pocket shapes;\n it0 = 1000')
    rects2=axes[0].barh(x + width/2, native_pocket_1000, width, label=' Restraints to rank 1 \n pocket residues;\n it0 = 1000')
    
    axes[0].set_xlim(xmin=0, xmax=102)
    axes[0].set_xticks([x for x in range(0,103,10)])
    axes[0].set_yticks(x)
    axes[0].set_yticklabels(labels)
    axes[0].legend(loc=4, prop={'size': 8})
    
    
    def autolabel(rects, axes):
    
        for rect in rects:
            width = rect.get_width()
            perc=int(round(width/102*100))
            axes.annotate(f'{width} ({perc}%) ',
                          xy=(width, rect.get_y()+ rect.get_height()), 
                          xytext=(0,0),
                          textcoords="offset points",
                          ha='left', va='bottom')
    
    autolabel(rects1, axes[0])
    # autolabel(rects2)
    # autolabel rects3,4 etc.
    # fig.tight_layout()
    
    plt.show()

enter image description here

1 个答案:

答案 0 :(得分:3)

  • rect.get_y() + rect.get_height() / 2看到rect.get_height()需要除以2。
  • 更改为va='center_baseline'并添加fontsize=8
def autolabel(rects, axes):
    for rect in rects:
        width = rect.get_width()
        perc=int(round(width/102*100))
        axes.annotate(f'{width} ({perc}%)',
                      xy=(width, rect.get_y() + rect.get_height() / 2), 
                      xytext=(0, 0),
                      textcoords="offset points",
                      ha='left', va='center_baseline', fontsize=8)


autolabel(rects1, axes[0])
autolabel(rects2, axes[0])

enter image description here