Dumbbell charts in matplotlib
In this tutorial I will show you how to create Dumbbell charts using Python and Matplotlib. For more matplotlib charts, check out the gallery:

Important notes:
1. This are my personal notes, so apologies if some explanations and notations are missing.
Dumbbell charts in matplotlib
Click on the links to go to the specific tutorials:



Import the packages
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from matplotlib.lines import Line2D
Add necessary columns:
color_dict = {"Norway": "#2B314D", "Denmark": "#A54836", "Sweden": "#5375D4", }
xy_ticklabel_color, grid_color, datalabels_color ='#757C85', "#C8C9C9", "#FFFFFF"
data = {
"year": [2004, 2022, 2004, 2022, 2004, 2022],
"countries" : [ "Denmark", "Denmark", "Norway", "Norway","Sweden", "Sweden",],
"sites": [4,10,5,8,13,15]
}
df= pd.DataFrame(data)
df = df.sort_values(['year','sites' ], ascending=False ).reset_index(drop=True)
#map the colors of a dict to a dataframe
df['color']= df.countries.map(color_dict)
df
year | countries | sites | color | |
---|---|---|---|---|
0 | 2022 | Sweden | 15 | #5375D4 |
1 | 2022 | Denmark | 10 | #A54836 |
2 | 2022 | Norway | 8 | #2B314D |
3 | 2004 | Sweden | 13 | #5375D4 |
4 | 2004 | Norway | 5 | #2B314D |
5 | 2004 | Denmark | 4 | #A54836 |
Define the variables
unique_countries = df.countries.unique()
countries = df.countries
colors = df.color.unique()
Create the plot
fig, ax = plt.subplots(figsize=(8,3), facecolor = "#FFFFFF")
for color, country in zip(colors,unique_countries):
temp_df= df[df.countries ==country]
ax.plot(temp_df.sites, temp_df.countries, '-o', markersize = 12, mec = "w", mew=2, color = color, zorder=1)
# Set xlim
ax.set_xlim(0, df.sites.max()+3)
ax.xaxis.set_tick_params(labeltop=True, # Put x-axis labels on top
labelbottom=False, # Set no x-axis labels on bottom
bottom=False, # Set no ticks on bottom
labelsize=11, # Set tick label size
pad=10) # Lower tick labels a bit
# Create grid
ax.grid(which="major", axis='both', color='#758D99', alpha=0.6, zorder=1)
# Remove splines. Can be done one at a time or can slice with a list.
ax.spines[['top','right','bottom']].set_visible(False)
#add legend
lines = [Line2D([0], [0], color=c, marker='o',linestyle='', markersize=8,) for c in reversed(colors)]
plt.legend(lines, reversed(countries), labelcolor = xy_ticklabel_color,
prop=dict(weight='light', size=10),
bbox_to_anchor=(0.5, -0.25), loc="lower center",
ncols = 3,frameon=False, fontsize= 14)

Was this helpful?
Reader Interactions