Skip to content

Household Wealth

The lines of code where ninejs is used are highlighted.

import pandas as pd
import plotnine as gg

from ninejs import interactive, save


data = pd.read_csv("docs/examples/household-wealth.csv")
order = ["United States", "China", "Japan", "Germany", "United Kingdom", "France", "India", "Other"]

palette = {
    "United States": "#003f5c",
    "China": "#2f4b7c",
    "Japan": "#665191",
    "Germany": "#a05195",
    "United Kingdom": "#d45087",
    "France": "#f95d6a",
    "India": "#ff7c43",
    "Other": "#ffa600",
}
display_names = {"United States": "USA", "United Kingdom": "UK", "Other": "Rest of the world"}

data["country"] = pd.Categorical(data["country"], categories=order, ordered=True)
data = data.sort_values(["year", "country"])
data["tooltip"] = [
    f"{display_names.get(str(country), str(country))}: ${value:,.0f}B"
    for country, value in zip(data["country"], data["total_wealth"])
]

totals = data.groupby("year", as_index=False)["total_wealth"].sum()
markers = totals[totals["year"].isin([2000, 2005, 2010, 2015, 2021])].copy()
line_offsets = {
    2000: 20000,
    2005: 20000,
    2010: 20000,
    2015: 25000,
    2021: 50000,
}
label_offsets = {
    2000: 30000,
    2005: 30000,
    2010: 30000,
    2015: 35000,
    2021: 50000,
}
markers["line_y"] = markers["total_wealth"] + markers["year"].map(line_offsets)
markers["label_y"] = markers["total_wealth"] + markers["year"].map(label_offsets)
markers["label"] = markers["total_wealth"].map(lambda value: f"${value:,.0f}B")
markers["label_x"] = markers["year"].astype(float)
markers.loc[markers["year"] == 2000, "label_x"] = 2000.45

latest_values = (
    data[data["year"] == 2021]
    .assign(country_name=lambda frame: frame["country"].astype(str))
    .set_index("country_name")["total_wealth"]
    .to_dict()
)
inline_labels = pd.DataFrame(
    {
        "country": order,
        "x": [2021.35] * 8,
        "y": [420000, 300000, 245000, 220000, 200000, 183000, 165000, 80000],
    }
)
inline_labels["label"] = [
    f"{display_names.get(country, country)} ${latest_values[country]:,.0f}B"
    for country in inline_labels["country"]
]
inline_labels["color"] = inline_labels["country"].map(palette)

x_axis = pd.DataFrame(
    {
        "year": [2000, 2005, 2010, 2015, 2021],
        "label": ["2000", "2005", "2010", "2015", "2021"],
    }
)
caption = (
    "Data: James Davies, Rodrigo Lluberas and Anthony Shorrocks, "
    "Credit Suisse Global Wealth Databook 2022\nDesign: Gilbert Fontana"
)

plot = (
    gg.ggplot(data, gg.aes(x="year", y="total_wealth"))
    + gg.geom_area(
        gg.aes(fill="country", group="country", tooltip="tooltip", data_id="country"),
        color="white",
        size=0.18,
    )
    + gg.geom_segment(
        data=markers,
        mapping=gg.aes(x="year", xend="year", y=0, yend="line_y"),
        inherit_aes=False,
        color="black",
        size=0.7,
    )
    + gg.geom_point(
        data=markers,
        mapping=gg.aes(x="year", y="line_y"),
        inherit_aes=False,
        color="black",
        size=2.2,
    )
    + gg.geom_text(
        data=markers[markers["year"] < 2021],
        mapping=gg.aes(x="label_x", y="label_y", label="label"),
        inherit_aes=False,
        color="black",
        size=8,
        fontweight="bold",
        va="bottom",
    )
    + gg.geom_text(
        data=markers[markers["year"] == 2021],
        mapping=gg.aes(x="year", y="label_y", label="label"),
        inherit_aes=False,
        color="black",
        size=8,
        fontweight="bold",
        ha="right",
        va="center",
    )
    + gg.geom_text(
        data=inline_labels,
        mapping=gg.aes(x="x", y="y", label="label", color="color"),
        inherit_aes=False,
        size=8,
        fontweight="bold",
        ha="left",
        va="center",
        show_legend=False,
    )
    + gg.geom_text(
        data=x_axis,
        mapping=gg.aes(x="year", y=-16000, label="label"),
        inherit_aes=False,
        color="black",
        size=8,
        va="top",
    )
    + gg.annotate("segment", x=2000, xend=2021, y=0, yend=0, color="black", size=0.7)
    + gg.annotate(
        "text",
        x=2000,
        y=505000,
        label="Aggregated\nHousehold\nWealth",
        ha="left",
        va="top",
        size=21,
        fontweight="bold",
        color="black",
    )
    + gg.annotate(
        "text",
        x=2000,
        y=-60000,
        label=caption,
        ha="left",
        va="top",
        size=7.5,
        color="black",
    )
    + gg.scale_fill_manual(values=palette)
    + gg.scale_color_identity()
    + gg.scale_x_continuous(limits=(1999.5, 2026.5))
    + gg.scale_y_continuous(limits=(-90000, 540000), expand=(0, 0))
    + gg.coord_cartesian(expand=False)
    + gg.theme_void(base_size=8)
    + gg.theme(
        legend_position="none",
        figure_size=(10, 6),
        plot_background=gg.element_rect(fill="white", color="white"),
        panel_background=gg.element_rect(fill="white", color="white"),
        plot_margin=0.03,
    )
)

interactive(plot) + save("docs/iframes/household-wealth.html", minify=True)