plotseabornsubplotpyhookcountplot

How to show percentage in each plot?


When trying to plot the following code I got 4 graphs but the percentage shows in only in the last graph.

fig, axes =plt.subplots(12,2,figsize=(12,50))
plt.subplots_adjust(wspace=0.9, hspace=0.9)
i=0
total = len(data['work_year']) 

for fea_name in fea:
     ax= axes[i//2, i%2]
     i += 1
     sns.countplot(x=fea_name, data=data, ax=ax,palette='icefire' )
     ax.set_title(f'Countplot of {fea_name}')

for i in range(len(fea), 12 * 2):
    fig.delaxes(axes[i//2, i%2])

for p in ax.patches:
        percentage = '{:.1f}%'.format(100 * p.get_height() / total)
        x = p.get_x() + p.get_width()/3
        y = p.get_y() + p.get_height()+50
        ax.annotate(percentage, (x, y))

plt.tight_layout()
plt.show()

Showing percentage in only one graphenter image description here


Solution

  • You can simplify your code a bit via ax.bar_label().

    (Seaborn's latest version wants hue= equal to the x= column when using a palette.)

    import matplotlib.pyplot as plt
    import seaborn as sns
    import pandas as pd
    import numpy as np
    
    # first, create some reproducible test data
    data = pd.DataFrame({'feature1': np.random.choice([*'abc'], 200),
                         'feature2': np.random.choice([*'defg'], 200),
                         'feature3': np.random.choice([*'hij'], 200),
                         'feature4': np.random.choice([*'klmno'], 200)})
    fea = ['feature1', 'feature2', 'feature3', 'feature4']
    
    fig, axes = plt.subplots(2, 2, figsize=(12, 12))
    
    total = len(data)
    
    for fea_name, ax in zip(fea, axes.flat):
        sns.countplot(x=fea_name, data=data, ax=ax, hue=fea_name, palette='icefire')
        ax.set_title(f'Countplot of {fea_name}')
        for c in ax.containers:
            ax.bar_label(c, fmt=lambda x: f'{x / total:.1%}')
    
    plt.tight_layout()
    plt.show()
    

    sns.countplot with percentages