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.lines import Line2D
import numpy as np
import pandas as pd
color_dict = {"Norway": "#2B314D", "Denmark": "#A54836", "Sweden": "#5375D4" }
xy_ticklabel_color, legend_color, grid_color, datalabels_color ='#757C85',"#101628", "#C8C9C9", "#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)
# custom sort
sort_order_dict = {"Denmark": 2, "Sweden": 1, "Norway": 3, 2004: 5, 2022: 4}
df = df.sort_values(by=["year","countries"], key=lambda x: x.map(sort_order_dict))
#map the colors of a dict to a dataframe
df['color']= df.countries.map(color_dict)
df
| year | countries | sites | color | |
|---|---|---|---|---|
| 5 | 2022 | Sweden | 15 | #5375D4 |
| 1 | 2022 | Denmark | 10 | #A54836 |
| 3 | 2022 | Norway | 8 | #2B314D |
| 4 | 2004 | Sweden | 13 | #5375D4 |
| 0 | 2004 | Denmark | 4 | #A54836 |
| 2 | 2004 | Norway | 5 | #2B314D |
Define the opacity so we can see through:
alpha = [1,1,0.4]
colors = df.color.unique()
sites_max = df.sites.max()
Plot the chart¶
fig, ax = plt.subplots()
ax.xaxis.tick_top()
ax.xaxis.set_label_position('top')
ax.invert_yaxis()
for i, (country, group) in enumerate(df.groupby("countries", sort = False)):
y = group['sites'].iloc[0]
x = group['sites'].iloc[1]
ax.fill_between(
(y, 0),
(0, x),
color=colors[i],
alpha=alpha[i]
)
Add styling:
ax.set(xlim = (0,sites_max + 1), ylim = (sites_max, 0))
#add year labels
ax.set_xlabel(df.year.max(), size = 14, color = grid_color, labelpad = 15)
ax.set_ylabel(df.year.min(), size=14, color = grid_color, labelpad = 15)
ax.spines[['left', 'top']].set_color('#C8C9C9')
ax.spines[['bottom', 'right']].set_color('w')
#customize tick labels
ax.tick_params(
axis='both',
which='major',
length=0,
labelsize=12,
colors= grid_color
)
ax.xaxis.set_ticks(np.arange(0, 20, 5), labels = [0,5,10,15])
ax.yaxis.set_ticks(np.arange(0, 20, 5), labels = [0,5,10,15])
fig
Add the legend:
legend_handles = [
Line2D([0], [0], color=color, marker='o', linestyle='',
markersize=12, markeredgecolor='w')
for color in colors[::-1]
]
# Get unique country labels
legend_labels = df.countries.unique().tolist()
# Add the legend to the plot
fig.legend(
legend_handles, legend_labels,
labelcolor=legend_color,
bbox_to_anchor=(0.5, -0.1), # Position below the plot
loc="lower center",
ncols=3,
frameon=False,
fontsize=12
)
fig