Stacked Bar Chart with Centered Labels

前端 未结 2 860
误落风尘
误落风尘 2020-12-01 12:49

I\'m trying to \"robustly\" center the data labels in a stacked bar chart. A simple code and the result are given below. As you can see, the data labels aren\'t really cente

相关标签:
2条回答
  • 2020-12-01 13:32
    • The following method is more succinct, and more easily scales with the number of columns.
    • Putting the data into a pandas.DataFrame is the easiest way to plot a stacked bar plot.
    • Using pandas.DataFrame.plot.bar(stacked=True) is the easiest way to plot a stacked bar plot.
      • This method returns a matplotlib.axes.Axes or a numpy.ndarray of them.
    • Using the .patches method unpacks a list of matplotlib.patches.Rectangle objects, one for each of the sections of the stacked bar.
      • Each .Rectangle has methods for extracting the various values that define the rectangle.
      • Each .Rectangle is in order from left to right, and bottom to top, so all the .Rectangle objects, for each level, appear in order, when iterating through .patches.
    • The labels are made using an f-string, label_text = f'{height}', so any additional text can be added as needed, such as label_text = f'{height}%'

    Imports

    import pandas as pd
    import matplotlib.pyplot as plt
    

    Data

    A = [45, 17, 47]
    B = [91, 70, 72]
    C = [68, 43, 13]
    
    # pandas dataframe
    df = pd.DataFrame(data={'A': A, 'B': B, 'C': C})
    df.index = ['C1', 'C2', 'C3']
    
         A   B   C
    C1  45  91  68
    C2  17  70  43
    C3  47  72  13
    

    Plot

    plt.style.use('ggplot')
    
    ax = df.plot(stacked=True, kind='bar', figsize=(12, 8), rot='horizontal')
    
    # .patches is everything inside of the chart
    for rect in ax.patches:
        # Find where everything is located
        height = rect.get_height()
        width = rect.get_width()
        x = rect.get_x()
        y = rect.get_y()
        
        # The height of the bar is the data value and can be used as the label
        label_text = f'{height}'  # f'{height:.2f}' to format decimal values
        
        # ax.text(x, y, text)
        label_x = x + width / 2
        label_y = y + height / 2
    
        # plot only when height is greater than specified value
        if height > 0:
            ax.text(label_x, label_y, label_text, ha='center', va='center', fontsize=8)
        
    ax.legend(bbox_to_anchor=(1.05, 1), loc='upper left', borderaxespad=0.)    
    ax.set_ylabel("Count", fontsize=18)
    ax.set_xlabel("Class", fontsize=18)
    plt.show()
    

    • To plot a horizontal bar:
    • kind='barh'
    • label_text = f'{width}'
    • Attribution: jsoma/chart.py
    0 讨论(0)
  • 2020-12-01 13:50

    Why you wrote va="bottom"? You have to use va="center".

    0 讨论(0)
提交回复
热议问题