如何绘制带有注释的水平堆积条 [英] How to plot a horizontal stacked bar with annotations

查看:102
本文介绍了如何绘制带有注释的水平堆积条的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  • 我将离散分布的示例用作 matplotlib 上的水平条形图示例

    选项 2:'Ward' 作为 y 轴

    • 使用

      • I used the example for Discrete distribution as horizontal bar chart example on matplotlib Discrete distribution as horizontal bar chart to create a chart showing share of the vote in Shropshire elections 2017.

      • However, because I did not know how to manipulate the data I had to manually enter my data in the program which is clearly down to my own ignorance.

      • I have the relevant data in a CSV file and can therefore load it as a dataframe.

        • The CSV has a row for each ward, of which there are 63 and columns for the % vote for each party (Tory, LD, Labour, Green, Indep) so 5 substantive columns.
      • I wanted advice as to how to change the form of the data so it resembles the input for this chart.

      • I am not sure what it is but seems possibly a dictionary type with key and value:

      My data reads in part:

      import pandas as pd
      import matplotlib.pyplot as plt
      
      category_names = ['Labour', 'LD', 'Indep', 'Green', 'Tory']
      results = {'Abbey': [16, 56, 4,0, 24],
                 'Albrighton': [0, 0, 32, 0, 68],
                 'Alveley & Claverley': [0, 25, 0, 0, 75],
                 'Bagley': [30, 30, 0, 0, 40],
                 'Battlefield': [34, 0, 0, 9, 57],
                 'Bayston Hill, Column & Sutton': [53, 4, 3, 7, 33],
                 'Belle Vue': [43,28,0,5,24]}
      
      
      # setup dataframe using the dict provided in the OP
      df = pd.DataFrame(results, index=category_names)
      
      # display(df)
              Abbey  Albrighton  Alveley & Claverley  Bagley  Battlefield  Bayston Hill, Column & Sutton  Belle Vue
      Labour     16           0                    0      30           34                             53         43
      LD         56           0                   25      30            0                              4         28
      Indep       4          32                    0       0            0                              3          0
      Green       0           0                    0       0            9                              7          5
      Tory       24          68                   75      40           57                             33         24
      
      

      • I am trying to get the data to be formatted like this directly from the csv file when entered as a pandas dataframe.

      • Have tried the values method and the to_dict method and while they get data looking similar they are not quite correct.

        • I believe there is a need to divide the data into keys and values but that is where my knowledge hits its limits.

      解决方案

      Option 1: 'Party' as the y-axis

      Using matplotlib from version 3.4.2

      ax = df.plot.barh(stacked=True, cmap='tab10', figsize=(16, 10))
      
      for c in ax.containers:
      
          # format the number of decimal places and replace 0 with an empty string
          labels = [f'{w:.0f}' if (w := v.get_width()) > 0 else '' for v in c ]
          
          ax.bar_label(c, labels=labels, label_type='center')
      

      Using matplotlib before version 3.4.2

      • Extract the .patch components in a loop, and then only plot annotations for values greater than 0.

      # plot 
      ax = df.plot.barh(stacked=True, cmap='tab10', figsize=(16, 10))
      
      # annotations:
      for p in ax.patches:
          left, bottom, width, height = p.get_bbox().bounds
          if width > 0:
               ax.annotate(f'{width:0.0f}', xy=(left+width/2, bottom+height/2), ha='center', va='center')
      

      Option 2: 'Ward' as the y-axis

      • Use pandas.DataFrame.T to swap the Index and Columns
        • 'Ward' will now be the index and 'Party' will be the columns

      # transpose df from the OP so Party is the in the columns and Ward is the index
      dft = df.T
      
      # display(dft)
                                     Labour  LD  Indep  Green  Tory
      Abbey                              16  56      4      0    24
      Albrighton                          0   0     32      0    68
      Alveley & Claverley                 0  25      0      0    75
      Bagley                             30  30      0      0    40
      Battlefield                        34   0      0      9    57
      Bayston Hill, Column & Sutton      53   4      3      7    33
      Belle Vue                          43  28      0      5    24
      

      Using matplotlib from version 3.4.2

      # plot
      ax = df.T.plot.barh(stacked=True, figsize=(16, 10))
      
      plt.legend(loc='center left', bbox_to_anchor=(1.0, 0.5))
      
      # annotations:
      for c in ax.containers:
          
          # format the number of decimal places and replace 0 with an empty string
          labels = [f'{w:.0f}' if (w := v.get_width()) > 0 else '' for v in c ]
          
          ax.bar_label(c, labels=labels, label_type='center')
      

      Using matplotlib before version 3.4.2

      # plot
      ax = dft.plot.barh(stacked=True, figsize=(16, 10))
      
      plt.legend(loc='center left', bbox_to_anchor=(1.0, 0.5))
      
      # annotations:
      for p in ax.patches:
          left, bottom, width, height = p.get_bbox().bounds
          if width > 0:
               ax.annotate(f'{width:0.0f}', xy=(left+width/2, bottom+height/2), ha='center', va='center')
      

      这篇关于如何绘制带有注释的水平堆积条的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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