- Matplotlib add value labels on a bar chart using bar_label
- How To Annotate Barplot with bar_label() in Matplotlib
- Labeling Barplots with Matplotlib’s bar_label() function
- Customizing Barplot Labels with Matplotlib’s bar_label()
- Stacked Bar Charts with Labels in Matplotlib
- Simple Stacked Bar Chart
- Customizing the Stacked Bar Chart
- Adding Labels to the Bars
- Adding a Total Label
- Adding both Sub-Bar and Total Labels
Matplotlib add value labels on a bar chart using bar_label
We want to add the value labels in a bar chart, which is the value of each label on the top or center of a bar in a plot. We have bar_label() method in matplotlib to label a bar plot and it add labels to the bars in the given container. It takes five parameters:
- container — Container with all the bars and returned from bar or barh plots
- labels — list of labels that needs to be displayed on the bar
- fmt — format string for the label
- label_type — Either edge or center
- padding — Distance of label from the end of the bar
And it returns a list of text for the labels
Here is an example of bar plot using bar_label to add labels on the top of the bar.
import numpy as np import pandas as pd import matplotlib.pyplot as plt %matplotlib inline Scores = [6, 16, 75, 160, 244, 260, 145, 73, 16, 4, 1] score_series = pd.Series(Scores) x_labels = [10, 20, 32, 44, 53, 61, 70, 79, 88, 91, 105] # Plot the figure. plt.figure(figsize=(12, 8)) fig = score_series.plot(kind='bar') fig.set_xticklabels(x_labels) fig.bar_label(fig.containers[0], label_type='edge')
Another example for a horizontal group bar plot, we need to call bar_label() two times in this case since it’s a group bar chart with 2 bars in each group
maths = [50, 57, 70, 48, 62, 89, 98] physics = [70, 88, 90, 54, 45, 72, 48] # index = ['snail', 'pig', 'elephant','rabbit', 'giraffe', 'coyote', 'horse'] df = pd.DataFrame('maths': maths,'physics': physics>) ax = df.plot.barh() ax.axhline(0, color='grey', linewidth=0.8) ax.bar_label(ax.containers[0]) ax.bar_label(ax.containers[1])
Padding parameter will pad the spacing between the values and the top of the bar
import seaborn as sns import seaborn as sns fig, ax = plt.subplots(figsize=(8, 8)) barchart = sns.barplot(x=x_labels, y=Scores, ax=ax) barchart.bar_label(ax.containers[0], label_type='edge', padding=15)
Updated: July 2, 2022
How To Annotate Barplot with bar_label() in Matplotlib
Annotating barplots with labels like texts or numerical values can be helpful to make the plot look better. Till now, one of the options add annotations in Matplotlib is to use pyplot’s annotate() function. Starting from Matplotlib version 3.4.2 and above, we have a new function, axes.bar_label() that lets you annotate barplots with labels easily.
In this tutorial, we will learn how to add labels to barplots using bar_label() function. As before, we will make barplots using Seaborn’s barplot() function, but add labels using Matplotlib’s bar_label() function.
Let us load Pandas, Seaborn and Matplotlib.
import pandas as pd import seaborn as sns import matplotlib.pyplot as plt
Let us create some data to make the barplot.
continent = ["Africa","Americas","Asia","Europe","Oceania"] lifeExp=[49,65,60,72,74]
Our data for making barplot looks like this.
Let us make simple barplot with Seaborn’s barplot() function. Here we have customized the barplot’s labels with Matplotlib’s function xlabel and ylabel.
plt.figure(figsize=(8, 6)) splot=sns.barplot(x="continent",y="lifeExp",data=df) plt.xlabel("Continent", size=16) plt.ylabel("LifeExp", size=16) plt.savefig("barplot_Seaborn_Python.png")
Labeling Barplots with Matplotlib’s bar_label() function
Similar to customizing the plot labels, now we can customize the bar labels using bar_label() function. Now, let us specify the bar labels using bar_label() function after making the barplot. Here we add bar height as bar labels to make it easy to read the barplot.
plt.figure(figsize=(8, 6)) splot=sns.barplot(x="continent",y="lifeExp",data=df) plt.xlabel("Continent", size=16) plt.ylabel("LifeExp", size=16) plt.bar_label(splot.containers[0]) plt.savefig("annotate_barplot_with_Matplotlib_bar_label_Python.png")
Barplot function returns a bar container with all “artists” describing the barplot. Matplotlib’s bar_label() function takes a container as input to add labels/annotations to the barplot.
Customizing Barplot Labels with Matplotlib’s bar_label()
We can customize the label size using size argument to bar_label() function.
plt.figure(figsize=(8, 6)) splot=sns.barplot(x="continent",y="lifeExp",data=df) plt.xlabel("Continent", size=16) plt.ylabel("LifeExp", size=16) plt.bar_label(splot.containers[0],size=16) plt.savefig("annotate_barplot_with_Matplotlib_bar_label_change_size_Python.png")
We can also place the bar label in the middle of the bars instead of at the bar edges using “label_type” argument.
plt.figure(figsize=(8, 6)) splot=sns.barplot(x="continent",y="lifeExp",data=df) plt.xlabel("Continent", size=16) plt.ylabel("LifeExp", size=16) plt.bar_label(splot.containers[0],size=16,label_type='center') plt.savefig("annotate_barplot_with_Matplotlib_bar_label_at_center_Python.png")
Stacked Bar Charts with Labels in Matplotlib
This post will go through a few examples of creating stacked bar charts using Matplotlib. We’ll look at some styling tweaks (like choosing custom colors) as well as go through how to add labels to the bars, both the totals and sub-totals for each bar.
And be sure to check out our related post on creating stacked bar charts using several python libraries beyond Matplotlib, like Seaborn and Altair.
Simple Stacked Bar Chart
The general idea for creating stacked bar charts in Matplotlib is that you’ll plot one set of bars (the bottom), and then plot another set of bars on top, offset by the height of the previous bars, so the bottom of the second set starts at the top of the first set. Sound confusing? It’s really not, so let’s get into it.
Let’s first get some data to work with.
import seaborn as sns tips = sns.load_dataset('tips') # Let's massage the data a bit to be aggregated by day of week, with # columns for each gender. We could leave it in long format as well ( # with gender as values in a single column). agg_tips = tips.groupby(['day', 'sex'])['tip'].sum().unstack().fillna(0) agg_tips
Now let’s create our first chart. We want to know the total amount tipped by day of week, split out by gender.
from matplotlib import pyplot as plt fig, ax = plt.subplots() # First plot the 'Male' bars for every day. ax.bar(agg_tips.index, agg_tips['Male'], label='Male') # Then plot the 'Female' bars on top, starting at the top of the 'Male' # bars. ax.bar(agg_tips.index, agg_tips['Female'], bottom=agg_tips['Male'], label='Female') ax.set_title('Tips by Day and Gender') ax.legend()
As you can see, it’s pretty simple. We first plot tips that males gave and then plot tips that females gave, but give an additional bottom argument to tell Matplotlib where to start the bars (which happens to be the values of the previous bars; in this case male tips).
The above code generates this lovely plot:
Customizing the Stacked Bar Chart
The problem with the above code is that it starts to get very verbose, and quite repetitive, if we have more than a few layers in our stacked bars. So let’s make it a bit more DRY.
import numpy as np from matplotlib import pyplot as plt fig, ax = plt.subplots() # Initialize the bottom at zero for the first set of bars. bottom = np.zeros(len(agg_tips)) # Plot each layer of the bar, adding each bar to the "bottom" so # the next bar starts higher. for i, col in enumerate(agg_tips.columns): ax.bar(agg_tips.index, agg_tips[col], bottom=bottom, label=col) bottom += np.array(agg_tips[col]) ax.set_title('Tips by Day and Gender') ax.legend()
This gives the exact same output as above, but is much nicer because we can apply it to any stacked bar need now, and it can handle as many layers as you need.
It’s also pretty flexible; for example, if we want to use custom colors we can easily do that:
fig, ax = plt.subplots() colors = ['#24b1d1', '#ae24d1'] bottom = np.zeros(len(agg_tips)) for i, col in enumerate(agg_tips.columns): ax.bar(agg_tips.index, agg_tips[col], bottom=bottom, label=col, color=colors[i]) bottom += np.array(agg_tips[col]) ax.set_title('Tips by Day and Gender') ax.legend()
Adding Labels to the Bars
It’s often nice to add value labels to the bars in a bar chart. With a stacked bar chart, it’s a bit trickier, because you could add a total label or a label for each sub-bar within the stack. We’ll show you how to do both.
Adding a Total Label
We’ll do the same thing as above, but add a step where we compute the totals for each day of the week and then use ax.text() to add those above each bar.
fig, ax = plt.subplots() colors = ['#24b1d1', '#ae24d1'] bottom = np.zeros(len(agg_tips)) for i, col in enumerate(agg_tips.columns): ax.bar( agg_tips.index, agg_tips[col], bottom=bottom, label=col, color=colors[i]) bottom += np.array(agg_tips[col]) # Sum up the rows of our data to get the total value of each bar. totals = agg_tips.sum(axis=1) # Set an offset that is used to bump the label up a bit above the bar. y_offset = 4 # Add labels to each bar. for i, total in enumerate(totals): ax.text(totals.index[i], total + y_offset, round(total), ha='center', weight='bold') ax.set_title('Tips by Day and Gender') ax.legend()
Adding both Sub-Bar and Total Labels
Now let’s do the same thing again, but this time, add annotations for each sub-bar in the stack. The method here is a bit different; we can actually get the patches or bars that we’ve already plotted, read their values, and then add those values as text annotations at the right location.
fig, ax = plt.subplots() colors = ['#24b1d1', '#ae24d1'] bottom = np.zeros(len(agg_tips)) for i, col in enumerate(agg_tips.columns): ax.bar( agg_tips.index, agg_tips[col], bottom=bottom, label=col, color=colors[i]) bottom += np.array(agg_tips[col]) totals = agg_tips.sum(axis=1) y_offset = 4 for i, total in enumerate(totals): ax.text(totals.index[i], total + y_offset, round(total), ha='center', weight='bold') # Let's put the annotations inside the bars themselves by using a # negative offset. y_offset = -15 # For each patch (basically each rectangle within the bar), add a label. for bar in ax.patches: ax.text( # Put the text in the middle of each bar. get_x returns the start # so we add half the width to get to the middle. bar.get_x() + bar.get_width() / 2, # Vertically, add the height of the bar to the start of the bar, # along with the offset. bar.get_height() + bar.get_y() + y_offset, # This is actual value we'll show. round(bar.get_height()), # Center the labels and style them a bit. ha='center', color='w', weight='bold', size=8 ) ax.set_title('Tips by Day and Gender') ax.legend()
Looks good. Thanks for reading and hopefully this helps get you on your way in creating annotated stacked bar charts in Matplotlib.