0

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

sdptn
  • 11
  • 3
  • 1
    It would be good to add the sample input that generated the above image to the code. – Mr. T Oct 14 '20 at 10:40
  • Thanks for the comment, unfortunately I can't share the data, anyway it's an aesthetic problem of the figure, not of the underlying data – sdptn Oct 14 '20 at 10:43
  • A sample input is not your actual data, just an example, so that people can see your input data structure. As it is, I cannot copy your code to run it. Anyway, how about showing the [values inside the bars](https://datavizpyr.com/how-to-annotate-bars-in-barplot-with-matplotlib-in-python/)? – Mr. T Oct 14 '20 at 10:48
  • There is also a version for annotation of horizontal bars [here](https://stackoverflow.com/a/56780852). – Mr. T Oct 14 '20 at 10:51
  • 1
    added a sample dataframe...none of the other solutions you suggest would work, I have other graphs with slimmer bars (e.g. one with all the countries of respondents), where the percentage won't fit in the bar and if I put horizontally they would overlap. I Have thought about enlarging the grey box, but am not sure how to do it – sdptn Oct 14 '20 at 11:11

1 Answers1

0

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()
Diziet Asahi
  • 38,379
  • 7
  • 60
  • 75