SPB Git
3.5 KB · 50 lines python
1#!/usr/bin/env python32"""Figure ch03 — Mises en chantier au Québec, données RÉELLES : Statistique Canada (SCHL), tableau 34-10-0135-01,3toutes les régions, trimestriel non désaisonnalisé, lu dans data/raw/statcan_34100135/34100135.csv (téléchargé le 2026-10-31).4Panneau A : totaux annuels 1990-2025 (2026 : trois trimestres, hachuré) et somme mobile sur quatre trimestres ; la zone grisée5marque le resserrement monétaire (mars 2022 → juillet 2023, série V39079). Panneau B : composition par type d'unité.6Sortie : assets/figures/ch03/ch03-fig-mises-chantier-quebec.pdf"""7import sys, pathlib8ROOT = pathlib.Path(__file__).resolve().parents[3]9sys.path.insert(0, str(ROOT / "analysis/python")); sys.path.insert(0, str(ROOT / "analysis/python/cases"))10import pandas as pd, matplotlib.pyplot as plt11from traite.style import setup, palette, savefig, LARGEUR, fmt_milliers12import ch03_cycles as cas131415def main():16    setup()17    df = cas.mises_en_chantier_quebec()18    ann = cas.mises_en_chantier_annuelles(df)19    tot = df[df["type"] == "Total d'unités"].set_index("date")["unites"]20    mobile = tot.rolling(4).sum()21    fig, (a, b) = plt.subplots(2, 1, figsize=(LARGEUR, 4.9), height_ratios=[3, 2], sharex=False)22    yrs = ann.loc[1990:2026]23    complet = yrs[yrs["trimestres"] == 4]; partiel = yrs[yrs["trimestres"] < 4]24    a.bar(complet.index, complet["total"] / 1000, width=0.8, color=palette.cat[0], alpha=0.75, label="total annuel")25    a.bar(partiel.index, partiel["total"] / 1000, width=0.8, color=palette.cat[0], alpha=0.35, hatch="///", edgecolor=palette.cat[0], label=f"{int(partiel.index[0])} (3 trimestres)")26    mob = mobile[mobile.index >= "1990-10-01"]27    a.plot(mob.index.year + (mob.index.month - 1) / 12 + 0.25, mob / 1000, color=palette.cat[1], lw=1.4, label="somme mobile sur 4 trimestres")28    a.axvspan(2022 + 2 / 12, 2023 + 6.5 / 12, color=palette.grid, alpha=0.8, lw=0)29    a.text(2023.75, 74, "resserrement monétaire\n(mars 2022 – juillet 2023)", ha="left", va="top", fontsize=7, color=palette.ink2)30    for y, va in ((2021, "bottom"), (2023, "bottom"), (2025, "bottom")):31        a.annotate(f"{fmt_milliers(ann.loc[y, 'total'])}", xy=(y, ann.loc[y, "total"] / 1000), xytext=(0, 3), textcoords="offset points", ha="center", va=va, fontsize=7.5)32    a.set_ylabel("milliers de logements"); a.set_xlim(1989.3, 2026.9); a.set_ylim(0, 75)33    a.legend(loc="upper left", fontsize=7.5, ncol=1); a.set_title("A. Logements mis en chantier, Québec (toutes les régions)", loc="left")34    # B. composition35    comp = ann.loc[1990:2025]36    b.stackplot(comp.index, 100 * comp["part_individuelles"], 100 * comp["jumeles"] / comp["total"] + 100 * comp["bande"] / comp["total"],37                100 * comp["part_appartements"], colors=[palette.cat[0], palette.cat[2], palette.cat[1]], alpha=0.85,38                labels=["maisons individuelles", "jumelés et en bande", "appartements et autres"])39    b.set_ylim(0, 100); b.set_ylabel("% des unités"); b.set_xlim(1989.3, 2026.9)40    b.legend(loc="upper center", bbox_to_anchor=(0.5, -0.16), fontsize=7.5, ncol=3, frameon=False)41    b.set_title("B. Composition par type d'unité (années complètes)", loc="left")42    for y, ha in ((2005, "center"), (2025, "right")):43        b.annotate(f"{100*ann.loc[y,'part_individuelles']:.0f} %", xy=(y + (0.3 if ha == "right" else 0), 100 * ann.loc[y, "part_individuelles"] / 2), ha=ha, va="center", fontsize=7.5, color="white")44    fig.tight_layout(h_pad=1.4)45    out = savefig(fig, "ch03/ch03-fig-mises-chantier-quebec.pdf"); print("OK", out)464748if __name__ == "__main__":49    main()50
Files · a58cc978dd49eee20fac414bfb0e69af32f1a29e
Menu

Theme