Reputation: 11
I am creating a grouped bar chart in which the groups are presented in descending order based on a percentage. I need to be able to label both bars within a group separately like shown below:
However with the code I have been finding online I can only get this so far:
This is my code so far, anything that will point me in the right direction will help:
products = ['chew', 'e_cigarette', 'cigarette', 'hookah', 'cigar']
def make_a_graph(products, per_totals, per_users):
per_totals.sort(reverse = True)
per_users.sort(reverse = True)
n_groups = len(products)
fig, ax = plt.subplots()
index = np.arange(n_groups)
bar_width = 0.4
totals = plt.bar(index - bar_width/2, per_totals, bar_width, color = 'b', label = '% of All Students')
users = plt.bar(index + bar_width/2, per_users, bar_width, color = 'lightblue', label = '% of Product Users')
plt.xlabel('Tobacco Product')
plt.ylabel('Percent of Users')
plt.title('Figure 2. Tobacco Use for 16-18 Year Olds')
plt.legend()
plt.tight_layout()
plt.show()
Upvotes: 1
Views: 1652
Reputation: 80534
This code seems to be what you're after. Note that when you sort the per_totals and the per_users, you also need to maintain the correspondence between the number and the product name.
import matplotlib.pyplot as plt
import numpy as np
products = ['chew', 'cigarette', 'hookah', 'cigar', 'e_cigarette']
per_totals = [3.2, 3.5, 0.9, 1.1, 6.7]
per_users = [36.1, 26, 20, 16, 31]
# sort both lists together
per_totals, products_totals = zip(*sorted(zip(per_totals, products), reverse=True))
per_users, products_users = zip(*sorted(zip(per_users, products), reverse=True))
n_groups = len(products)
fig, ax = plt.subplots()
index = np.arange(n_groups)
bar_width = 0.4
totals = plt.bar(index - bar_width/2, per_totals, bar_width, color = '#2c7fb8', label = '% of All Students')
users = plt.bar(index + bar_width/2, per_users, bar_width, color = '#7fcdbb', label = '% of Product Users')
# list of ticks: combine the ticks from both groups
# followed by the list of corresponding labels
# note that matplotlib takes care of sorting both lists while maintaining the correspondence
plt.xticks(np.append(index - bar_width/2, index + bar_width/2), # tick positions
products_totals+products_users, # label corresponding to each tick
rotation=30)
plt.xlabel('Tobacco Product')
plt.ylabel('Percent of Users')
plt.title('Figure 2. Tobacco Use for 16-18 Year Olds')
plt.legend()
plt.tight_layout()
plt.show()
Upvotes: 1