【问题标题】:How to show values inside the bars of a bargraph?如何在条形图的条内显示值?
【发布时间】:2017-11-13 11:11:21
【问题描述】:

我有一个这样的数据框:

                 platform     count
release_year        
         1996    PlayStation   138
         1997    PlayStation   170
         1998    PlayStation   155
         1999    PC            243...

现在我想在各个条形图中使用平台名称绘制水平条形图,使其看起来像这样:

我该怎么做?

【问题讨论】:

    标签: python pandas matplotlib


    【解决方案1】:

    不确定您是否希望它以 百分比 %计数 本身的形式出现。这由你决定。 但是首先使用以下方法将您的数据框转换为列表:

    count = df["count"].tolist()
    platform = df["platform"].tolist()
    

    我不会专注于此。您可以从

    中找到一些相关帮助

    Dataframe to list 1

    Dataframe to list 2

    一旦你得到下面的列表,

    count = ['138','170','155','243','232']
    platform =['PlayStation','PlayStation','PlayStation','PC','PlayStation']
    

    注意:以上两个将是您在条形图中的文本标签

    完整代码如下:

    import matplotlib.pyplot as plt
    from numpy.random import rand
    from numpy import arange
    
    count = ['138','170','155','243','232']
    platform =['PlayStation','PlayStation','PlayStation','PC','PlayStation']
    def autolabel(rects):
    # attach some text labels
        for ii,rect in enumerate(rects):
            width = int(rect.get_width())
    
            height = rect.get_height()
            print(height,width)
            yloc1=rect.get_y() + height /2.0
            yloc2=rect.get_y() + height /2.0
            if (width <= 5):
                # Shift the text to the right side of the right edge
                xloc1 = width + 1
                yloc2=yloc2+0.3
                # Black against white background
                clr = 'black'
                align = 'left'
            else:
                # Shift the text to the left side of the right edge
                xloc1 = 0.98*width
                # White on blue
                clr = 'white'
                align = 'right'
            yloc1=rect.get_y() + height /2.0
            print(xloc1,yloc1,yloc2)
            ax.text(xloc1,yloc1, '%s'% (count[ii]),horizontalalignment=align,
                             verticalalignment='center',color=clr,weight='bold',
                             clip_on=True)
            ax.text(5,yloc2, '%s'% (platform[ii]),horizontalalignment='left',
                             verticalalignment='center',color=clr,weight='bold',
                             clip_on=True)
    
    
    val = [138,170,155,243,232]
    print(val)# the bar lengths or count in your case
    pos = [ 1996 , 1997,  1998,  1999,  2000]    # the bar centers on the y axis
    print(pos)
    
    fig = plt.figure()
    ax = fig.add_subplot(111)
    rects = ax.barh(pos,val, align='center',height=0.4)
    print(rects)
    autolabel(rects)
    ax.set_ylabel('Year')
    ax.set_xlabel('Count')
    ax.set_title('horizontal bar chart')
    ax.grid(False)
    plt.savefig("horizontal.png")
    plt.show()
    

    您将非常感兴趣的部分:

    def autolabel(rects):
        # attach some text labels
            for ii,rect in enumerate(rects):
    
                width =  rect.get_width()
    
                height = rect.get_height()
    
                yloc1=rect.get_y() + height /2.0
                yloc2=rect.get_y() + height /2.0
                if (width <= 5):
                    # Shift the text to the right side of the right edge
                    xloc1 = width + 1
                    yloc2=yloc2+0.3
                    # Black against white background
                    clr = 'black'
                    align = 'left'
                else:
                    # Shift the text to the left side of the right edge
                    xloc1 = 0.98*width
                    # White on blue
                    clr = 'white'
                    align = 'right'
                yloc1=rect.get_y() + height /2.0
    
                ax.text(xloc1,yloc1, '%s'% (count[ii]),horizontalalignment=align,
                                 verticalalignment='center',color=clr,weight='bold',
                                 clip_on=True)
                ax.text(5,yloc2, '%s'% (platform[ii]),horizontalalignment='left',
                                 verticalalignment='center',color=clr,weight='bold',
                                 clip_on=True)
    

    1) ii 变量来自枚举值 0 到 5。用于迭代我们的列表 countplatform

    2) 为什么函数中有 if/else 语句?那是在宽度太小的情况下。假设从 val = [138,170,155,243,232] 获得的第一个宽度减少到 5 即 val = [5,170,155,243,232] 在这种情况下输出将是。

    我们所做的基本上是为 ax.text() 函数提供 xloc(x 坐标)和 yloc(y 坐标)值。

    ax.text(xloc1,yloc1, '%s'% (count[ii]),horizontalalignment=align,
                             verticalalignment='center',color=clr,weight='bold',
                             clip_on=True)
            ax.text(5,yloc2, '%s'% (platform[ii]),horizontalalignment='left',
                             verticalalignment='center',color=clr,weight='bold',
                             clip_on=True)
    

    功能参数

    文本(x, y, s, fontdict=None, withdash=False, **kwargs)

    x, y : 数据坐标

    s : 字符串,其他两个是可选的。

    如果宽度

    如果您更改这些值并查看输出如何变化以更好地理解它,那将是最好的

    更新:如果您不希望轴显示在输出中,就像您附加的图像中一样,您可以简单地输入ax.axis("off")

    【讨论】:

      【解决方案2】:

      找到每个平台的百分比后,输入data.csv 文件如下:

      Platform,Percent
      Nintendo,34
      PC,16
      Playstation,28
      Xbox,22
      

      这是代码:

      import pandas as pd
      import matplotlib.pyplot as plt
      
      df = pd.read_csv("data.csv", index_col=0)
      df.plot(kind="barh", legend=False, width=0.8)
      for i, (p, pr) in enumerate(zip(df.index, df["Percent"])):
          plt.text(s=p, x=1, y=i, color="w", verticalalignment="center", size=18)
          plt.text(s=str(pr)+"%", x=pr-5, y=i, color="w",
                   verticalalignment="center", horizontalalignment="left", size=18)
      plt.axis("off")
      # xticks & yticks have empty lists to reduce white space in plot
      plt.xticks([])
      plt.yticks([])
      plt.tight_layout()
      plt.savefig("data.png")
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-09-21
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多