66 of 100: Proportional Area 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!
To be improved: Location of things.
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 matplotlib as mpl
from svgpathtools import svg2paths
from svgpath2mpl import parse_path
import numpy as np
import pandas as pdGenerate 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.
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 sort the data.
df = df.sort_values(['year' ,'sites' ], ascending=False ).reset_index(drop=True)Create the heritage symbol
icon_path, attributes = svg2paths('flags/Unesco_World_Heritage_logo_notext_transparent.svg')
#matplotlib path object of the icon
icon_marker = parse_path(attributes[0]['d'])
icon_marker.vertices -= icon_marker.vertices.mean(axis=0)
icon_marker = icon_marker.transformed(mpl.transforms.Affine2D().rotate_deg(180))
icon_marker = icon_marker.transformed(mpl.transforms.Affine2D().scale(-1,1))Define the variables
countries = df.countries.unique()
sites = df.sites
years = df.year.unique()
colors =[ "#5375D4","#A54836","#2B314D"]*2
X, Y = np.meshgrid(np.arange(3), np.arange(2))Plot the chart
fig, ax = plt.subplots(figsize=(8,4), facecolor = "#FFFFFF")
fig.tight_layout(pad=1.0)
X, Y = np.meshgrid(np.arange(3), np.arange(2))
ax.scatter(X,Y,s=sites*400,marker=icon_marker, color = colors, zorder=1)
for i, site in enumerate(sites):
ax.annotate(site, (X.flatten()[i], Y.flatten()[i]-0.4), ha= "center", va="center", color= "k")
ax.axhline(-0.5, -0 ,1, ls="dotted", color ="#D4D5D7", clip_on = False )
ax.axhline(0.4, 0 , 1, ls="dotted", color ="#D4D5D7" , clip_on = False )
ax.axhline(1.4, 0 , 1, ls="dotted", color ="#D4D5D7" , clip_on = False )
ax.set_xlim(-0.5,2.5)
ax.set_ylim(-0.5,1.5)
ax.tick_params(axis='both', which='major',labeltop=True,labelbottom=False,length=0,labelsize=12,colors= '#757C85',pad = 2.5)
ax.spines[['top', 'left','right' ,'bottom']].set_visible(False)
ax.yaxis.set_ticks(range(len(years)), labels =years)
ax.xaxis.set_ticks(range(len(countries)), labels = countries) The result:

Reader Interactions