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
import numpy as np
import pandas as pd
color_dict = {"Norway": "#2B314D", "Denmark": "#A54836", "Sweden": "#5375D4" }
xy_ticklabel_color, grand_totals_color, grid_color, datalabels_color ='#757C85',"#101628", "#E9ECED", "#3F4452"
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['pct_change'] = df.groupby('countries', sort=False)['sites'].apply(
lambda x: x.pct_change()).to_numpy()*100
df['sub_total'] = df.groupby('countries')['sites'].transform('sum')
df['diff'] = df.groupby(['countries'])['sites'].diff()
#map the colors of a dict to a dataframe
df['color']= df.countries.map(color_dict)
df
| year | countries | sites | pct_change | sub_total | diff | color | |
|---|---|---|---|---|---|---|---|
| 0 | 2004 | Denmark | 4 | NaN | 14 | NaN | #A54836 |
| 1 | 2022 | Denmark | 10 | 150.000000 | 14 | 6.0 | #A54836 |
| 2 | 2004 | Norway | 5 | NaN | 13 | NaN | #2B314D |
| 3 | 2022 | Norway | 8 | 60.000000 | 13 | 3.0 | #2B314D |
| 4 | 2004 | Sweden | 13 | NaN | 28 | NaN | #5375D4 |
| 5 | 2022 | Sweden | 15 | 15.384615 | 28 | 2.0 | #5375D4 |
fig, ax = plt.subplots( figsize=(5,5),facecolor = "#FFFFFF", zorder= 1)
fig.tight_layout(pad=6.0)
for row in df.iloc[1::2].itertuples():
ax.scatter(
row.diff,
row.pct_change,
color = row.color,
zorder = 2)
offset = .2
ax.annotate(
row.countries,
(row.diff + offset, row.pct_change),
ha= "left",
va="center",
color= datalabels_color
)
label_style = dict(
size = 10,
color = xy_ticklabel_color)
ax.set_xlabel("Absolute change", **label_style)
ax.set_ylabel("Percentual change", **label_style)
ax.tick_params(
axis='both',
which='major',
length=0,
labelsize=8,
colors =xy_ticklabel_color,
pad=12
)
ax.grid(color = grid_color)
ax.set(xlim = (0,8), ylim = (0,2))
y_ticks = np.arange(0, 250, 50)
ax.yaxis.set_ticks(ticks, labels = [f'{tick}%' for tick in ticks])
x_ticks = np.arange(0, 10, 2)
ax.xaxis.set_ticks(x_ticks, labels = x_ticks)
for axis in ['top', 'bottom', 'left', 'right']:
ax.spines[axis].set_color(grid_color)
ax.spines[axis].set_zorder(0)
fig