Question: I have created a bar plot with the following code. I would like to label the percentages adding up to ~100% for each user, as I've done in MSpaint for user1 and user2 below:  import matplotlib.pyplot as plt import numpy as np import pandas as pd users = ['user1', 'user2', 'user3', 'user4', 'user5', 'user6', 'user7',\ 'user8', 'user9', 'user10', 'user11', 'user12'] NEG = [433, 1469, 1348, 2311, 522, 924, 54, 720, 317, 135, 388, 9] NEU = [2529, 4599, 4617, 4297, 1782, 2742, 61, 2640, 1031, 404, 1723, 76] POS = [611, 1149, 1262, 1378, 411, 382, 29, 513, 421, 101, 584, 49] data = {'Negative': NEG, 'Neutral': NEU, 'Positive': POS} df = pd.DataFrame(data, index=users) ax = df.plot(kind='bar', ylabel='Number of Messages\nw/ <= 128 Characters',\ xlabel='Username', title='Discord Sentiment Analysis',\ color=['coral', 'khaki', 'skyblue']) plt.tight_layout() plt.show()  Following the advice from this thread, I've made the following attempts: Attempt 1 ax = df.plot(kind='bar', ylabel='Number of Messages\nw/ <= 128 Characters',\ xlabel='Username', title='Discord Sentiment Analysis',\ color=['coral', 'khaki', 'skyblue']) for p in ax.containers: ax.bar_label(p, fmt='%.1f%%', label_type='edge')` plt.tight_layout() plt.show()   Attempt 2 ax = df.plot(kind='bar', ylabel='Number of Messages\nw/ <= 128 Characters',\ xlabel='Username', title='Discord Sentiment Analysis',\ color=['coral', 'khaki', 'skyblue']) for p in ax.patches: width = p.get_width() height = p.get_height() x, y = p.get_xy() ax.annotate(f'{height:.0%}', (x + width/2, y + height*1.02), ha='center') plt.tight_layout() plt.show()   Attempt 3 ax = df.plot(kind='bar', ylabel='Number of Messages\nw/ <= 128 Characters',\ xlabel='Username', title='Discord Sentiment Analysis',\ color=['coral', 'khaki', 'skyblue']) for p in ax.containers: ax.bar_label(p, fmt='%.1f%%', label_type='edge') plt.tight_layout() plt.show()  

Answer:  Plot df, but create a dataframe of the percents, which can be used as custom labels for .bar_label. See How to add value labels on a bar chart for a thorough explanation, and additional examples, of .bar_label.  # create a dataframe of percents percent = df.div(df.sum(axis=1), axis=0).mul(100).round(1) # plot ax = df.plot(kind='bar', ylabel='Number of Messages\nw/ <= 128 Characters',\ xlabel='Username', title='Discord Sentiment Analysis',\ color=['coral', 'khaki', 'skyblue'], width=0.9, figsize=(10, 8)) # add annotations for p in ax.containers: # get the current legend label, which is the column name label = p.get_label() # use the column name to access the correct labels from percent labels = percent[label].astype(str).add('%') # add the bar labels ax.bar_label(p, labels=labels, label_type='edge', rotation=90, fontsize=10, padding=3) # pad the spacing between the number and the edge of the figure ax.margins(y=0.1) plt.tight_layout() plt.show()    The code for annotating a grouped horizontal bar chart, kind='barh', is exactly the same. # create a dataframe of percents percent = df.div(df.sum(axis=1), axis=0).mul(100).round(1) # plot ax = df.plot(kind='barh', ylabel='Number of Messages\nw/ <= 128 Characters',\ xlabel='Username', title='Discord Sentiment Analysis',\ color=['coral', 'khaki', 'skyblue'], width=0.9, figsize=(10, 8)) # add annotations for p in ax.containers: label = p.get_label() labels = percent[label].astype(str).add('%') ax.bar_label(p, labels=labels, label_type='edge', rotation=0, fontsize=10, padding=3) # pad the spacing between the number and the edge of the figure ax.margins(x=0.1) plt.tight_layout() plt.show()    df  Negative Neutral Positive user1 433 2529 611 user2 1469 4599 1149 user3 1348 4617 1262 user4 2311 4297 1378 user5 522 1782 411 user6 924 2742 382 user7 54 61 29 user8 720 2640 513 user9 317 1031 421 user10 135 404 101 user11 388 1723 584 user12 9 76 49  percent  Negative Neutral Positive user1 12.1 70.8 17.1 user2 20.4 63.7 15.9 user3 18.7 63.9 17.5 user4 28.9 53.8 17.3 user5 19.2 65.6 15.1 user6 22.8 67.7 9.4 user7 37.5 42.4 20.1 user8 18.6 68.2 13.2 user9 17.9 58.3 23.8 user10 21.1 63.1 15.8 user11 14.4 63.9 21.7 user12 6.7 56.7 36.6