ax.annotate text partially appearing outside the figure box

659 Views Asked by At

Apologies, rather unskilled with programming and stackoverflow too. I am drawing bar plots on some data and have managed to add percentages beside the bars, using ax.annotate. However for the bar with highest responses I always get part of the percentage number outside the figure box, as per image below. Have tried different ideas but none worked to fix this. Looking for some suggestions on how to fix this.

enter image description here

Here is my code

from matplotlib import pyplot as plt
import seaborn as sns

def plot_barplot(df):
    plt.rcParams.update({'font.size': 18})
    sns.set(font_scale=2)
    if (len(df) > 1):
        fig = plt.figure(figsize=(12,10))
        ax = sns.barplot(x='count', y=df.columns[0], data=df, color='blue')
       
    else:
        fig = plt.figure(figsize=(5,7))
        ax = sns.barplot(x=df.columns[0], y='count', data=df, color='blue')
    fig.set_tight_layout(True)
    
    
    plt.rcParams.update({'font.size': 14})
    total = df['count'].sum()
    
    
    for p in ax.patches:
        percentage ='{:.2f}%'.format(100 * p.get_width()/total)
        
        print(percentage)
        x = p.get_x() + p.get_width() + 0.02
        y = p.get_y() + p.get_height()/2
        ax.annotate(percentage, (x, y))

Dataframe looks like this

enter image description here

1

There are 1 best solutions below

0
On BEST ANSWER

I would suggest you increase the axes' margins (in the x direction in that case). That is the space there is between the maximum of your data and the maximum scale on the axis. You will have to play around with the value depending on your needs, but it looks like a value of 0.1 or 0.2 should be enough.

add:

plt.rcParams.update({'axes.xmargin': 0.2})

to the top of your function

enter image description here

full code:

from matplotlib import pyplot as plt
import seaborn as sns
import pandas as pd


def plot_barplot(df):
    plt.rcParams.update({'font.size': 18})
    plt.rcParams.update({'axes.xmargin': 0.1})

    sns.set(font_scale=2)
    if (len(df) > 1):
        fig = plt.figure(figsize=(12, 10))
        ax = sns.barplot(x='count', y=df.columns[0], data=df, color='blue')

    else:
        fig = plt.figure(figsize=(5, 7))
        ax = sns.barplot(x=df.columns[0], y='count', data=df, color='blue')
    fig.set_tight_layout(True)

    plt.rcParams.update({'font.size': 14})
    total = df['count'].sum()

    for p in ax.patches:
        percentage = '{:.2f}%'.format(100 * p.get_width() / total)

        print(percentage)
        x = p.get_x() + p.get_width() + 0.02
        y = p.get_y() + p.get_height() / 2
        ax.annotate(percentage, (x, y))


df = pd.DataFrame({'question': ['Agree', 'Strongly agree'], 'count': [200, 400]})
plot_barplot(df)
plt.show()