Matplotlib 图的标注--annotate

图形标注

有时候我们画好了一幅图,比如柱状图,但是如何在每个柱子上面显示其具体的数据呢?简单的plot.bar()是无法解决这个问题的。今天就遇到了这个问题,发现annotate是一个提供标注的工具,可以解决此类问题。annotate的功能很强大,在图中加文本框,加箭头都可以。

实例

最近在做Titanic 数据分析,分类型变量的单变量分析一般需要画柱状图,在图上加上具体的数值再好不过了。

#定义柱状图显示函数:
def abs_rel_f(feature):

#生成频率的dataframe格式:
    abs_frequency=feature.value_counts()
    relative_frequency=feature.value_counts(normalize=True).round(3)*100
    abs_rel_f=pd.DataFrame({'Absolute Frequency':abs_frequency,'Relative Frequency(%)':relative_frequency})
    display(abs_rel_f) 
    
#绘制柱状图
#绝对频率柱状图:
    global ax,ax1 #声明全局变量,这样上面的绝对和相对频率注释函数才可以使用ax和ax1
    ax=abs_frequency.plot.bar(figsize=(18,7))
    abs_bar_labels()  # Displays bar labels in abs scale.
    plt.show()
#相对频率柱状图:
    ax1=relative_frequency.plot.bar(figsize=(18,7))
    pct_bar_labels()
    plt.show()

注意:

1 统计变量的频率,使用pandas的value_counts()函数

2 统计相对频率(即百分比),只需要value_counts( normalize=True) 计算百分比,元整的话要加 .round(n) ,小数点后保留n位

3 global 是声明全局变量,即ax和ax1不仅仅在函数内有效,所以函数外面的也可以调用ax、ax1

4 两个ax相当于两个画布,要全部显示的话,一个 plt.show( )不够,需要每一个ax下都加 plt.show( )

5 便是abs_bar_labels 和 pct_bar_labels,这两个便是两个柱状图的标注函数,如下:

设置标注函数 

# 定义相对频率柱状图的注释
def abs_bar_labels():
    font_size = 15
    plt.ylabel('Absolute Frequency', fontsize = font_size)
    plt.xticks(rotation =0, fontsize = font_size)
    plt.yticks([])
    
    # Set individual bar lebels in absolute number
    for x in ax.patches:
        ax.annotate(x.get_height(), 
        (x.get_x() + x.get_width()/2., x.get_height()),  ha = 'center', va = 'center',xytext = (0,7), 
        textcoords = 'offset points', fontsize = font_size, color = 'black')

# 定义相对频率柱状图的注释        
def pct_bar_labels():
    font_size = 15
    plt.ylabel('Relative Frequency (%)', fontsize = font_size)
    plt.xticks(rotation = 0, fontsize = font_size)
    plt.yticks([]) 
    
    # Set individual bar lebels in proportional scale
    for x in ax1.patches:
        ax1.annotate(str(x.get_height()) + '%', 
        (x.get_x() + x.get_width()/2., x.get_height()), ha = 'center', va = 'center', xytext = (0, 7), 
        textcoords = 'offset points', fontsize = font_size, color = 'black')

ax.annotate((x.get_height(), 
        (x.get_x() + x.get_width()/2., x.get_height()),  ha = 'center', va = 'center',xytext = (0,7), 
        textcoords = 'offset points', fontsize = font_size, color = 'black')

参数详解:ax.annotata(  (y, (x,y) ),ha, va, xytext, textcoords, fontsize, color ) 

y :  要标注的值或字符串。x.get_x() 即横坐标对应的纵坐标的值

(x, y): 被标注的点或区域。(x.get_x() + x.get_width()/2., x.get_height())即(横坐标值+柱的宽度,柱的高度)

ha va=' center'  点在注释的中心。ha 水平(right left center)放置、 va 垂直放置方式 ( top center baseline bottom )

xytext: 标注文本所处的坐标。( 0,7) 是相对坐标,x坐标移动为0, 纵坐标向上移动7

textcoords = 'offset points'   以上述被标注的点(x,y)为起点,是计算xytext 绝对坐标的起点

因为相对频率柱形图中,标注的数字要加' %',所以标注函数里y 那项变为字符串形式: str(x.get_height()) + '%'

结果如下:

参考:https://www.kaggle.com/eraaz1/a-comprehensive-guide-to-titanic-machine-learning/notebook

猜你喜欢

转载自blog.csdn.net/qq_43243022/article/details/83547728