如何在 matplotlib 条形图上写入值而没有扭曲的数字 [英] How to write values over matplotlib bar charts without distorted figures

查看:52
本文介绍了如何在 matplotlib 条形图上写入值而没有扭曲的数字的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

注意

答案

这是修改后的代码,它产生不好的结果:

def plot_compare_bar(col1, col2, frame, fig_prefix=''):框架= frame.sort_values(by = col1)ind = np.arange(len(frame))宽度= 0.4无花果,ax = plt.subplots(figsize =(9,5))ax.barh(ind, frame[col1], width, color='red', label=col1)ax.barh(ind + width, frame[col2], width, color='blue', label=col2)ax.set(yticks=ind + 宽度,yticklabels=frame['类名'],ylim = [2 *宽度-1,len(frame)],title =(f'{fig_prefix} {col1}与{col2}评估结果'))对于 i, v in enumerate(frame[col1].values):ax.text(v + 3, i + .25, str(v), color='red', fontweight='bold')对于i,v中的enumerate(frame [col2] .values):ax.text(v + 3,i + .25,str(v),color ='blue',fontweight ='bold')ax.legend()

原始问题:

 将matplotlib.pyplot导入为plt将numpy导入为npdef plot_compare_bar(col1,col2,frame,fig_prefix =''):frame = frame.sort_values(by=col1)ind = np.arange(len(frame))宽度= 0.4无花果,ax = plt.subplots(figsize =(9,5))ax.barh(ind, frame[col1], width, color='red', label=col1)ax.barh(ind + width, frame[col2], width, color='blue', label=col2)ax.set(yticks = ind + width,yticklabels = frame ['Class Name'],ylim = [2 *宽度-1,len(frame)],title =(f'{fig_prefix} {col1} vs {col2} 评估结果'))ax.legend()

frame 是一个如下所示的 pandas DataFrame :

 类名 平均精度 实际检测 真阳性 假阳性 组合2棕榈树91.152760 1379 1428 1292 141 14335红绿灯71.026533 1269 1036 948 88 10363 路灯 63.871910 995 848 727 121 8480 汽车 57.535491 3153 1955 1881 104 19851 路牌 56.925982 1109 704 658 46 7046 行人 55.243564 1418 887 835 73 90813 路块 52.182602 363 215 203 14 2174 小型货车 51.786659 68 41 38 3 4111总线36.805556 43 18 16 2 189垃圾桶14.444444 90 13 13 0 1310自行车5.882353 17 1 1 0 18 标志 5.000000 124 10 7 3 107 消火栓 1.923077 52 1 1 0 112皮卡车0.000000 20 0 0 0 014 货车 0.000000 4 0 0 0 015摩托车0.000000 3 0 0 0 0

我在上面定义的函数产生如下图:

我需要在其旁边写上每个小节的值,如下所示:

如何修改上面的功能来做到这一点.

解决方案

您不应该对文本进行硬编码.相反,尝试从补丁中提取值:

  def plot_compare_bar(col1,col2,frame,fig_prefix =''):frame = frame.sort_values(by=col1)ind = np.arange(len(frame))宽度= 0.4无花果,ax = plt.subplots(figsize =(10,10))ax.barh(ind, frame[col1], width, color='red', label=col1)ax.barh(ind + width,frame [col2],width,color ='blue',label = col2)ax.set(yticks = ind + width,yticklabels = frame ['Class Name'],ylim = [2 *宽度-1,len(frame)],title =(f'{fig_prefix} {col1} vs {col2} 评估结果'))#这里注释对于ax.patches中的补丁:# 从补丁中提取信息pw = patch.get_width()_,y = patch.get_xy()颜色= patch.get_facecolor()ax.text(pw + 3,y + width/2,str(pw),color = color,verticalalignment ='center')ax.legend(loc='右下')

输出:

NOTE

The answers here produce a distorted figure; here is the bad result:

Here is the modified code that produces the bad result:

def plot_compare_bar(col1, col2, frame, fig_prefix=''):
    frame = frame.sort_values(by=col1)
    ind = np.arange(len(frame))
    width = 0.4
    fig, ax = plt.subplots(figsize=(9, 5))
    ax.barh(ind, frame[col1], width, color='red', label=col1)
    ax.barh(ind + width, frame[col2], width, color='blue', label=col2)
    ax.set(
        yticks=ind + width, yticklabels=frame['Class Name'],
        ylim=[2 * width - 1, len(frame)], title=(
            f'{fig_prefix} {col1} vs {col2} evaluation results'))
    for i, v in enumerate(frame[col1].values):
        ax.text(v + 3, i + .25, str(v), color='red', fontweight='bold')
    for i, v in enumerate(frame[col2].values):
        ax.text(v + 3, i + .25, str(v), color='blue', fontweight='bold')
    ax.legend()

The original question:

import matplotlib.pyplot as plt
import numpy as np


def plot_compare_bar(col1, col2, frame, fig_prefix=''):
    frame = frame.sort_values(by=col1)
    ind = np.arange(len(frame))
    width = 0.4
    fig, ax = plt.subplots(figsize=(9, 5))
    ax.barh(ind, frame[col1], width, color='red', label=col1)
    ax.barh(ind + width, frame[col2], width, color='blue', label=col2)
    ax.set(
        yticks=ind + width, yticklabels=frame['Class Name'],
        ylim=[2 * width - 1, len(frame)], title=(
            f'{fig_prefix} {col1} vs {col2} evaluation results'))
    ax.legend()

frame is a pandas DataFrame that looks like the following:

        Class Name  Average Precision  Actual  Detections  True Positives  False Positives  Combined
2        Palm Tree          91.152760    1379        1428            1292              141      1433
5   Traffic Lights          71.026533    1269        1036             948               88      1036
3      Street Lamp          63.871910     995         848             727              121       848
0              Car          57.535491    3153        1955            1881              104      1985
1      Street Sign          56.925982    1109         704             658               46       704
6       Pedestrian          55.243564    1418         887             835               73       908
13      Road Block          52.182602     363         215             203               14       217
4          Minivan          51.786659      68          41              38                3        41
11             Bus          36.805556      43          18              16                2        18
9        Trash Can          14.444444      90          13              13                0        13
10         Bicycle           5.882353      17           1               1                0         1
8             Flag           5.000000     124          10               7                3        10
7     Fire Hydrant           1.923077      52           1               1                0         1
12    Pickup Truck           0.000000      20           0               0                0         0
14  Delivery Truck           0.000000       4           0               0                0         0
15      Motorcycle           0.000000       3           0               0                0         0

The function I defined above, produces the following plot:

I need every bar's value written next to it which might look like this:

How to modify the function above to do it.

解决方案

You should not hard-coded the text. Instead, try to extract the values from patches:

def plot_compare_bar(col1, col2, frame, fig_prefix=''):
    frame = frame.sort_values(by=col1)
    ind = np.arange(len(frame))
    width = 0.4
    fig, ax = plt.subplots(figsize=(10,10))
    ax.barh(ind, frame[col1], width, color='red', label=col1)
    ax.barh(ind + width, frame[col2], width, color='blue', label=col2)
    ax.set(
        yticks=ind + width, yticklabels=frame['Class Name'],
        ylim=[2 * width - 1, len(frame)], title=(
            f'{fig_prefix} {col1} vs {col2} evaluation results'))

    # annotation here
    for patch in ax.patches:
        # extract information from patch
        pw = patch.get_width()
        _,y = patch.get_xy()
        color = patch.get_facecolor()

        ax.text(pw + 3, y + width/2, str(pw), 
                color=color,verticalalignment='center')

    ax.legend(loc='lower right')

Output:

这篇关于如何在 matplotlib 条形图上写入值而没有扭曲的数字的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆