2

enter image description here

How can I get the counts and percentages on the right of each bar??? At present I only know how to get the counts.

import pandas as pd
import matplotlib.pyplot as plt

age = ['0-17','18-60','61-80']

df3 = pd.DataFrame(data={'Male':[82,550,25], 'Female':[72,309,7]}, index=age)
print(df3)

ax = df3.plot(kind='barh', ylabel='Age', title='Passenger Count by Age and Sex')
ax.set(xlabel='No. of Passengers')

for c in ax.containers:
    # set the bar label
    ax.bar_label(c, fmt='%.0f', label_type='edge')

ax.legend(title='Sex', bbox_to_anchor=(1, 1.02), loc='upper left')

ax.spines['right'].set_visible(False)
ax.spines['top'].set_visible(False)



plt.show()
Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158
Miguel Logan
  • 61
  • 2
  • 6
  • Similar to [How to add percentages on top of bars in seaborn](https://stackoverflow.com/a/68851142/7758804), [How to annotate barplot with percent by hue/legend group](https://stackoverflow.com/q/68850222/7758804), and [How to add multiple annotations to a barplot](https://stackoverflow.com/q/61718127/7758804) – Trenton McKinney Nov 28 '21 at 00:21

1 Answers1

1

The function bar_label accepts a parameter label= with a list of labels to use. A list of strings can be created by looping through the dataframe.

See this answer for a thorough explanation of the function and more examples.

The following example code uses 100% to represent all passengers:

import pandas as pd
import matplotlib.pyplot as plt

age = ['0-17', '18-60', '61-80']

df3 = pd.DataFrame(data={'Male': [82, 550, 25], 'Female': [72, 309, 7]}, index=age)

ax = df3.plot(kind='barh', ylabel='Age', title='Passenger Count by Age and Sex')
ax.set(xlabel='No. of Passengers')

total = sum(df3.sum())
for c, col in zip(ax.containers, df3.columns):
    ax.bar_label(c, label_type='edge', labels=[f'{val}\n{val / total * 100.0:.1f} %' for val in df3[col]])

ax.legend(title='Sex', bbox_to_anchor=(1, 1.02), loc='upper left')

ax.spines['right'].set_visible(False)
ax.spines['top'].set_visible(False)

plt.tight_layout()
plt.show()

bar_label with percentages

  • The following option adds a condition to have blank strings if a bar value is 0.
    • Assignment expressions (:=) are available with python 3.8
ax = df3.plot(kind='barh', ylabel='Age', title='Passenger Count by Age and Sex', width=0.75)
ax.set(xlabel='No. of Passengers')

tot = df.sum().sum()

# add annotations
for c in ax.containers:
    
    # custom label calculates percent and add an empty string so 0 value bars don't have a number
    labels = [f'{w/tot*100:0.1f}%\n{w}' if (w := v.get_width()) > 0 else '' for v in c]
    
    ax.bar_label(c, labels=labels, label_type='edge', padding=0.3)
    
ax.margins(x=0.15)
Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158
JohanC
  • 71,591
  • 8
  • 33
  • 66