33 of 100: Bar chart in matplotlib
At the beginning of the year I challenged myself to create all 100 visualizations using python and matplotlib from the 1 dataset,100 visualizations project and I am sharing with you the code for all the visualizations.
Note: Data Viz Project is copyright Ferdio and available under a Creative Commons Attribution – Non Commercial – No Derivatives 4.0 International license. I asked Ferdio and they told me they used a Design tool to create all the plots.
Collaborate
There are a ton of improvements that can be made on the code, so let me know in the comments any improvements you make and I will update the post accordingly!
This is the original viz that we are trying to recreate in matplotlib:

Import the packages
We will need the following packages:
import matplotlib.pyplot as plt
import pandas as pd
Generate the data
We could actually go from numpy to matplotlib, but most data projects use pandas to transform the data, so I am using a pandas dataframe as the starting point.
color_dict = {"Norway": "#2B314D", "Denmark": "#A54836", "Sweden": "#5375D4", }
xy_ticklabel_color, ='#757C85',
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)
index | year | countries | sites |
---|---|---|---|
0 | 2004 | Sweden | 13 |
1 | 2022 | Sweden | 15 |
2 | 2004 | Denmark | 4 |
3 | 2022 | Denmark | 10 |
4 | 2004 | Norway | 5 |
5 | 2022 | Norway | 8 |
We need to create the subtotals for each year, year labels, county codes and colors and then sort the data.
df['year_lbl'] ="'"+df['year'].astype(str).str[-2:].astype(str)
df['sub_total'] = df.groupby('countries')['sites'].transform('sum')
df['ctry_code'] = df.countries.astype(str).str[:2].astype(str).str.upper()
df = df.sort_values([ 'sites'], ascending=True ).reset_index(drop=True)
df['color']= df.countries.map(color_dict)
index | year | countries | sites | year_lbl | sub_total | ctry_code | color |
---|---|---|---|---|---|---|---|
0 | 2004 | Denmark | 4 | ’04 | 14 | DE | #A54836 |
1 | 2004 | Norway | 5 | ’04 | 13 | NO | #2B314D |
2 | 2022 | Norway | 8 | ’22 | 13 | NO | #2B314D |
3 | 2022 | Denmark | 10 | ’22 | 14 | DE | #A54836 |
4 | 2004 | Sweden | 13 | ’04 | 28 | SW | #5375D4 |
5 | 2022 | Sweden | 15 | ’22 | 28 | SW | #5375D4 |
Define the variables
nr_years = df.year.unique()
codes = df.ctry_code
colors = df.color
yr_lables = df.year_lbl
tick_lables = [f' {code}\n{lbl}' for code, lbl in zip(codes, yr_lables) ]
x = df.index
y = df.sites
Plot the chart
fig, ax = plt.subplots( figsize=(7,5), facecolor = "w")
fig.tight_layout(pad=3.0)
ax.bar(x, height = y, color = colors, label = codes)
for bar, site in zip(ax.patches, y):
ax.text(
bar.get_x() + bar.get_width() / 2,
bar.get_height() + bar.get_y(), #height
site, ha="center", va="bottom",
color = xy_ticklabel_color, size = 12, weight= "light",
)
ax.set_yticklabels([])
ax.xaxis.set_ticks(range(6), labels =tick_lables)
for xtick, color in zip(ax.get_xticklabels(), colors):
xtick.set_color(color)
ax.tick_params(axis='both', which='both',length=0, pad=10)
ax.spines[['top', 'left','bottom', 'right']].set_visible(False)
for xtick, color in zip(ax.get_xticklabels(), colors):
xtick.set_color(color)
ax.tick_params(axis='both', which='both',length=0, pad=10)
ax.spines[['top', 'left','bottom', 'right']].set_visible(False)
The result:

Reader Interactions