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.
import matplotlib.pyplot as plt
from matplotlib.offsetbox import OffsetImage, AnnotationBbox
import pandas as pd
color_dict = {"Norway": "#2B314D", "Denmark": "#A54836", "Sweden": "#5375D4"}
xy_label_color, datalabels_color = "#757C85", "#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["sub_total"] = df.groupby("countries")["sites"].transform("sum")
df = df.sort_values(["sub_total"], ascending=True).reset_index(drop=True)
# map the colors of a dict to a dataframe
df["color"] = df.countries.map(color_dict)
df
| year | countries | sites | sub_total | color | |
|---|---|---|---|---|---|
| 0 | 2022 | Norway | 8 | 13 | #2B314D |
| 1 | 2004 | Norway | 5 | 13 | #2B314D |
| 2 | 2022 | Denmark | 10 | 14 | #A54836 |
| 3 | 2004 | Denmark | 4 | 14 | #A54836 |
| 4 | 2004 | Sweden | 13 | 28 | #5375D4 |
| 5 | 2022 | Sweden | 15 | 28 | #5375D4 |
img = [
plt.imread("../flags/de-sq.png"),
plt.imread("../flags/no-sq.png"),
plt.imread("../flags/sw-sq.png"),
]
groups = df.groupby("year")
fig, axes = plt.subplots(ncols=df.year.nunique(), nrows=1, figsize=(7, 5), sharex=True, sharey=True, facecolor="#FFFFFF", zorder=1)
fig.tight_layout(pad=3.0)
for (year, group), ax in zip(groups, axes.ravel()):
sites = group.sites
countries = group.countries
colors = group.color
#add the bars
ax.bar(
countries,
height = sites,
width = 1,
align = "edge",
color = colors)
#add the data labels
for bar, site in zip(ax.patches, sites):
ax.text(
bar.get_x() + bar.get_width() / 2,
0.3, # height
site,
ha = "center",
va = "bottom",
color = datalabels_color,
weight = "light",
)
# add the flags
tick_labels = ax.xaxis.get_ticklabels()
for i, im in enumerate(img):
ib = OffsetImage(im, zoom=0.04)
ab = AnnotationBbox(
ib,
tick_labels[i].get_position(), #get the position of the tick labels in the x axis
frameon=False,
box_alignment=(-0.7, 2)
)
ax.add_artist(ab)
# add x labels
ax.set_xlabel(
year,
color = xy_label_color,
size = 12,
labelpad = 53
)
ax.tick_params(
axis = "both",
which = "both",
length = 0,
labelbottom = False,
labelleft = False
)
ax.set_frame_on(False)