from plotjs import PlotJS, css
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from pypalettes import load_cmap
from highlight_text import fig_text, ax_text
from pyfonts import load_google_font
from drawarrow import ax_arrow
url = "https://raw.githubusercontent.com/holtzy/The-Python-Graph-Gallery/master/static/data/disaster-events.csv"
df = pd.read_csv(url)
def remove_agg_rows(entity: str):
if entity.lower().startswith("all disasters"):
return False
else:
return True
df = df.replace("Dry mass movement", "Drought")
df = df[df["Entity"].apply(remove_agg_rows)]
df = df[~df["Entity"].isin(["Fog", "Glacial lake outburst flood"])]
df = df.pivot_table(index="Entity", columns="Year", values="Disasters").T
df.loc[1900, :] = df.loc[1900, :].fillna(0)
df = df[df.index >= 1960]
df = df[df.index <= 2023]
df = df.interpolate(axis=1)
df.head()
# set up the font properties
font = load_google_font("Bebas Neue")
other_font = load_google_font("Fira Sans", weight="light")
other_bold_font = load_google_font("Fira Sans", weight="medium")
# initialize the figure
fig, ax = plt.subplots(figsize=(14, 7), dpi=300)
ax.set_axis_off()
# define the x-axis variable and order the columns
columns = df.sum().sort_values().index.to_list()
x = df.index
# defines color map and mapping with columns
colors = load_cmap("Dali").colors
color_mapping = {
"Flood": colors[4],
"Volcanic activity": colors[0],
"Wildfire": colors[6],
"Drought": colors[7],
"Extreme temperature": colors[5],
"Wet mass movement": colors[3],
"Earthquake": colors[2],
"Extreme weather": colors[1],
}
colors = [color_mapping[col] for col in columns]
# create the stacked area plot
areas = np.stack(df[columns].values, axis=-1)
ax.stackplot(x, areas, colors=colors)
# add label for the x-axis
for year in range(1960, 2030, 10):
ax_text(
x=year,
y=-10,
s=f"{year}",
va="top",
ha="left",
fontsize=13,
font=font,
color="grey",
)
# add label for the y-axis
for value in range(100, 400, 100):
ax_text(
x=1960,
y=value,
s=f"{value}",
va="center",
ha="left",
fontsize=13,
font=font,
color="grey",
)
ax.plot([1963, 2023], [value, value], color="grey", lw=0.1)
# add title
fig_text(
s="More than 1 natural disaster occurs\n<every day> since the 21st century",
x=0.16,
y=0.83,
fontsize=24,
ha="left",
va="top",
color="black",
font=other_font,
fig=fig,
highlight_textprops=[{"font": other_bold_font}],
)
# source and credit
text = """
<Design>: barbierjoseph.com
<Data>: EM-DAT, CRED / UCLouvain (2024)
"""
fig_text(
s=text,
x=0.16,
y=0.05,
fontsize=10,
ha="left",
va="top",
color="black",
fontproperties=other_font,
highlight_textprops=[{"font": other_bold_font}, {"font": other_bold_font}],
)
# add inline labels
y_pos = [330, 220, 180, 100, 70, 30, -10, -30]
for i in range(len(y_pos)):
country = columns[::-1][i]
val_2023 = int(df.loc[2023, country])
ax_text(
x=2030,
y=y_pos[i],
s=f"{country.upper()} - {val_2023} disasters in 2023",
va="center",
ha="left",
font=other_bold_font,
fontsize=12,
color=colors[7 - i],
)
# add inflexion arrows
x_axis_start = 2023
x_axis_end = 2030
radius = 10
arrow_props = {"clip_on": False, "color": "black", "fill_head": False}
ax_arrow(
tail_position=(x_axis_start, 330), head_position=(x_axis_end, 330), **arrow_props
)
ax_arrow(
tail_position=(x_axis_start, 220), head_position=(x_axis_end, 220), **arrow_props
)
ax_arrow(
tail_position=(x_axis_start, 90),
head_position=(x_axis_end, 180),
inflection_position=(2040, 180),
**arrow_props,
)
ax_arrow(
tail_position=(x_axis_start, 60),
head_position=(x_axis_end, 100),
inflection_position=(2040, 100),
**arrow_props,
)
ax_arrow(
tail_position=(x_axis_start, 45),
head_position=(x_axis_end, 70),
inflection_position=(2040, 70),
**arrow_props,
)
ax_arrow(
tail_position=(x_axis_start, 30), head_position=(x_axis_end, 30), **arrow_props
)
ax_arrow(
tail_position=(x_axis_start, 20),
head_position=(x_axis_end, -10),
inflection_position=(2040, -10),
**arrow_props,
)
ax_arrow(
tail_position=(x_axis_start, 4),
head_position=(x_axis_end, -30),
inflection_position=(2040, -30),
**arrow_props,
)
plt.savefig("debug.svg")
PlotJS(fig, bbox_inches="tight").add_css(
css.from_dict(
{
".tooltip": {
"width": "180px",
"text-align": "center",
"font-size": "1.2em",
"background": "#000814",
}
}
)
).add_tooltip(labels=columns).save("docs/iframes/area-natural-disasters.html")
import numpy as np
import matplotlib.pyplot as plt
from plotjs import PlotJS
size = 10000
labels = ["S&P500", "CAC40", "Bitcoin", "Livret A", "Default"]
groups = ["safe", "safe", "safe", "not safe", "not safe"]
fig, axs = plt.subplots(figsize=(10, 10), nrows=2)
axs[0].plot(
np.cumsum(np.random.choice([-1, 1], size=size)),
linewidth=5,
color="#264653",
label=labels[0],
)
axs[0].plot(
np.cumsum(np.random.choice([-1, 1], size=size)),
linewidth=5,
color="#2a9d8f",
label=labels[1],
)
axs[0].plot(
np.cumsum(np.random.choice([-1, 1], size=size)),
linewidth=5,
color="#e9c46a",
label=labels[2],
)
axs[0].plot(
np.cumsum(np.random.choice([-1, 1], size=size)),
linewidth=5,
color="#0077b6",
label=labels[3],
)
axs[0].plot(
np.cumsum(np.random.choice([-1, 1], size=size)),
linewidth=5,
color="#14213d",
label=labels[4],
)
axs[0].legend()
axs[1].plot(
np.cumsum(np.random.choice([-1, 1], size=size)),
linewidth=5,
color="#264653",
label=labels[0],
)
axs[1].plot(
np.cumsum(np.random.choice([-1, 1], size=size)),
linewidth=5,
color="#2a9d8f",
label=labels[1],
)
axs[1].plot(
np.cumsum(np.random.choice([-1, 1], size=size)),
linewidth=5,
color="#e9c46a",
label=labels[2],
)
axs[1].plot(
np.cumsum(np.random.choice([-1, 1], size=size)),
linewidth=5,
color="#0077b6",
label=labels[3],
)
axs[1].plot(
np.cumsum(np.random.choice([-1, 1], size=size)),
linewidth=5,
color="#14213d",
label=labels[4],
)
axs[1].legend()
(
PlotJS(fig=fig)
.add_tooltip(labels=labels, groups=labels, ax=axs[0])
.add_tooltip(labels=labels, groups=labels, ax=axs[1])
.save("docs/iframes/random-walk-1.html")
)