Skip to content

HDI in Sao Paulo

import geopandas as gp
import numpy as np
import pandas as pd
import plotnine as gg

from ninejs import interactive, save


breaks = np.arange(0.65, 0.951, 0.05)
group_labels = {
    "0": "0.650 or less",
    "1": "0.650 to 0.699",
    "2": "0.700 to 0.749",
    "3": "0.750 to 0.799",
    "4": "0.800 to 0.849",
    "5": "0.850 to 0.899",
    "6": "0.900 to 0.949",
    "7": "0.950 or more",
}
palette = {
    "0": "#ffffcc",
    "1": "#d9f0a3",
    "2": "#addd8e",
    "3": "#78c679",
    "4": "#41ab5d",
    "5": "#238443",
    "6": "#006837",
    "7": "#004529",
}

atlas_data = pd.read_csv("docs/examples/atlas_sp_hdi.csv")
atlas = gp.GeoDataFrame(
    atlas_data.drop(columns="geometry"),
    geometry=gp.GeoSeries.from_wkt(atlas_data["geometry"]),
    crs="EPSG:4326",
)
atlas["group_hdi"] = np.searchsorted(breaks, atlas["HDI"], side="right").astype(str)
atlas["group_label"] = atlas["group_hdi"].map(group_labels)
atlas["tooltip"] = [
    f"HDI: {hdi:.3f}<br>Range: {label}"
    for hdi, label in zip(atlas["HDI"], atlas["group_label"])
]

pop_hdi = (
    atlas.drop(columns="geometry")
    .groupby(["group_hdi", "group_label"], as_index=False, observed=True)["pop"]
    .sum()
    .sort_values("group_hdi")
)
pop_hdi["share"] = pop_hdi["pop"] / pop_hdi["pop"].sum() * 100
pop_hdi["label"] = pop_hdi["share"].map(lambda value: f"{value:.1f}%")
pop_hdi["tooltip"] = [
    f"{label}<br>Population share: {share:.1f}%"
    for label, share in zip(pop_hdi["group_label"], pop_hdi["share"])
]

x_min, y_min, x_max, y_max = atlas.total_bounds
x_span = x_max - x_min
y_span = y_max - y_min

inset_left = x_min + x_span * 0.52
inset_right = x_min + x_span * 0.97
inset_bottom = y_min + y_span * 0.10
inset_top = y_min + y_span * 0.48
bar_slot = (inset_right - inset_left) / len(pop_hdi)
bar_width = bar_slot * 0.72
max_share = pop_hdi["share"].max()

pop_hdi["bar_x"] = inset_left + bar_slot * (np.arange(len(pop_hdi)) + 0.5)
pop_hdi["xmin"] = pop_hdi["bar_x"] - bar_width / 2
pop_hdi["xmax"] = pop_hdi["bar_x"] + bar_width / 2
pop_hdi["ymin"] = inset_bottom
pop_hdi["ymax"] = inset_bottom + (pop_hdi["share"] / max_share) * (
    inset_top - inset_bottom
)
pop_hdi["label_y"] = pop_hdi["ymax"] + y_span * 0.025
pop_hdi["axis_y"] = inset_bottom - y_span * 0.045
pop_hdi["title_y"] = inset_top + y_span * 0.065

caption = "Source: Atlas Brasil | Original design: R Graph Gallery"

plot = (
    gg.ggplot()
    + gg.geom_map(
        data=atlas,
        mapping=gg.aes(fill="group_hdi", tooltip="tooltip", hover_key="group_hdi"),
        color="white",
        size=0.05,
    )
    + gg.geom_rect(
        data=pop_hdi,
        mapping=gg.aes(
            xmin="xmin",
            xmax="xmax",
            ymin="ymin",
            ymax="ymax",
            fill="group_hdi",
            tooltip="tooltip",
            hover_key="group_hdi",
        ),
        color=None,
    )
    + gg.geom_text(
        data=pop_hdi,
        mapping=gg.aes(x="bar_x", y="label_y", label="label"),
        size=5.5,
        color="#1f2933",
    )
    + gg.geom_text(
        data=pop_hdi,
        mapping=gg.aes(x="bar_x", y="axis_y", label="group_label"),
        size=4.2,
        angle=45,
        ha="right",
        color="#374151",
    )
    + gg.annotate(
        "text",
        x=(inset_left + inset_right) / 2,
        y=pop_hdi["title_y"].iloc[0],
        label="Population share",
        size=9,
        fontweight="bold",
        ha="center",
    )
    + gg.annotate(
        "text",
        x=x_min + x_span * 0.50,
        y=y_max + y_span * 0.10,
        label="HDI in Sao Paulo, BR (2010)",
        size=16,
        fontweight="bold",
        ha="center",
    )
    + gg.annotate(
        "text",
        x=x_min + x_span * 0.50,
        y=y_max + y_span * 0.04,
        label="Microregion HDI in Sao Paulo",
        size=8.5,
        color="#4b5563",
        ha="center",
    )
    + gg.annotate(
        "text",
        x=inset_right,
        y=y_min + y_span * 0.01,
        label=caption,
        size=5.5,
        color="#6b7280",
        ha="right",
    )
    + gg.scale_fill_manual(values=palette, guide=None)
    + gg.coord_cartesian(
        xlim=(x_min, x_max),
        ylim=(y_min - y_span * 0.08, y_max + y_span * 0.15),
        expand=False,
    )
    + gg.theme_void(base_size=9)
    + gg.theme(
        figure_size=(5.5, 8),
        plot_background=gg.element_rect(fill="#f7f7f2", color="#f7f7f2"),
        panel_background=gg.element_rect(fill="#f7f7f2", color="#f7f7f2"),
        plot_margin=0.02,
    )
)

(
    interactive(plot)
    + save("docs/iframes/sao-paulo-hdi.html")
)