Generate the data and import packagesΒΆ
First, we need to create the data. I'll start by defining it as a dictionary and then convert it into a pandas DataFrame, since pandas is commonly used in many projects for data manipulation.
from matplotlib.offsetbox import OffsetImage, AnnotationBbox
from matplotlib import pyplot as plt
import pandas as pd
import numpy as np
color_dict = {"Norway": "#2B314D", "Denmark": "#A54836", "Sweden": "#5375D4", }
xy_ticklabel_color, grand_totals_color, grid_color, datalabels_color ='#757C85',"#101628", "#C8C9C9", "#FFFFFF"
I will create the data manually for this chart.
#define the table size
rows = 4
cols = 6
#Define the row labels
ylabel = [
"Biggest % change",
"Biggest change",
"Most in 2022",
"Most in 2004"
]
#define the position of dots
positions = np.arange(0.5, 6.5, 1).tolist()
#define the flags:
img = [
plt.imread("../flags/no-sq.png"),
plt.imread("../flags/de-sq.png"),
plt.imread("../flags/sw-sq.png"),
plt.imread("../flags/de-sq.png"),
plt.imread("../flags/no-sq.png"),
plt.imread("../flags/sw-sq.png")
]
Last, I will be plotting dots on all cells, and use color to determine which ones will show:
colors = [
['w','#A54836','w','#A54836','#2B314D','w'],
['w','#A54836','w','#A54836','#2B314D','w'],
['w','#A54836','#5375D4','w','w','#5375D4'],
['#2B314D','w','#5375D4','w','w','#5375D4']
]
fig, ax = plt.subplots(figsize=(8,6))
# Add table's dots
for i, color in zip(range(rows), colors):
for c, (j, column), in zip(color, enumerate(range(cols))):
ax.scatter(
positions[j],
i,
s = 100,
c= c
)
# adding a bit of padding on bottom (-1), top (1), right (0.5)
ax.set_ylim(-1, rows + 1)
ax.set_xlim(0, cols + .5)
(0.0, 6.5)
Then we add the flags:
for pos, im in zip(positions, img):
image_box = OffsetImage(im, zoom = 0.04) #container for the image
ab = AnnotationBbox(
image_box,
(pos,4.6 ),
frameon = False
)
ax.add_artist(ab)
fig
Add table's row headers:
ax.yaxis.set_ticks(range(rows), labels =ylabel)
fig
Add dividing lines:
for vline in range(0, cols+2 ,2):
ax.axvline(
x = vline,
ymin = 0,
ymax =1 ,
color = 'lightgrey'
)
for dotted_line in range(1, cols ,2):
ax.axvline(
x = dotted_line,
ymin = 0,
ymax =0.85 ,
ls = "dotted" ,
color = 'lightgrey'
)
ax.annotate(
"VS.",
xy =(dotted_line,4.5 ),
ha = "center"
)
fig
Final styling:
ax.tick_params(axis='both', which='both',length=0, color = 'lightgrey',pad = 20, labelbottom = False)
ax.set_frame_on(False)
fig