3

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:

Group bar plot goal

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 1

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 2

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()

Attempt 3

Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158
Aaron
  • 33
  • 4

1 Answers1

4
# 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()

enter image description here


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()

enter image description here


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
Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158