SPB Git
6.2 KB · 91 lines python
1#!/usr/bin/env python32"""Figures du chapitre 12 (DONNÉES SYNTHÉTIQUES, cas 1, graine 20261031) :3  ch12-fig-conventions-sujet.pdf : superficie du sujet selon cinq conventions et prix unitaire implicite ;4  ch12-fig-erreur-valeur.pdf     : valeur hédonique du sujet en fonction de la superficie mesurée, tangente et erreur de ±5 % ;5  ch12-fig-attenuation.pdf       : atténuation du coefficient de la superficie par une erreur de mesure (théorie et simulation).6Usage : python3 analysis/python/figures/ch12_figures.py (depuis la racine)."""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 numpy as np, matplotlib.pyplot as plt11from traite.style import setup, palette, savefig, LARGEUR, fmt_dollars12import ch12_mesurage as cas131415def fig_conventions(r):16    pu = r["pu"]; V = r["M"]["V"]17    noms = ["Aire au sol\n(MEFQ R0701A)", "Superficie nette\n(utile)", "Superficie habitable\n(convention de l'ouvrage)",18            "Aire des étages, brute\n(MEFQ R0702A)", "Habitable + sous-sol fini\n(fiches de courtage)"]19    fig, (a, b) = plt.subplots(1, 2, figsize=(LARGEUR, 3.0), gridspec_kw={"width_ratios": [1.1, 1]}, sharey=True)20    y = np.arange(len(pu))21    cols = [palette.cat[1], palette.cat[1], palette.cat[0], palette.cat[1], palette.cat[1]]22    a.barh(y, pu["m2"], color=cols, height=0.6)23    for i, (m2, pi2) in enumerate(zip(pu["m2"], pu["pi2"])):24        a.text(m2 + 3, i, f"{m2:.1f} m² ({pi2:,.0f} pi²)".replace(",", " "), va="center", fontsize=7.5)25    a.set_yticks(y); a.set_yticklabels(noms, fontsize=7.5); a.invert_yaxis(); a.set_xlim(0, 320)26    a.set_xlabel("Superficie (m²)"); a.set_title("(a) Un bâtiment, cinq superficies", loc="left"); a.grid(axis="y", visible=False)27    b.barh(y, pu["dollars_m2"], color=cols, height=0.6)28    for i, (dm, dp) in enumerate(zip(pu["dollars_m2"], pu["dollars_pi2"])):29        b.text(dm + 80, i, (f"{dm:,.0f} " + r"\$/m² (" + f"{dp:,.0f} " + r"\$/pi²)").replace(",", " "), va="center", fontsize=7.5)30    b.set_xlim(0, 9500); b.set_xlabel("Prix unitaire implicite ($/m²)"); b.grid(axis="y", visible=False)31    b.set_title("(b) Cinq prix unitaires pour " + fmt_dollars(V).replace("$", r"\$"), loc="left")32    fig.tight_layout(w_pad=1.0)33    return savefig(fig, "ch12/ch12-fig-conventions-sujet.pdf")343536def fig_erreur(r):37    M = r["M"]; V, S, beta = M["V"], M["S"], M["beta"]; dVdS = r["dVdS"]38    s = np.linspace(135, 200, 200); Vs = V * (s / S) ** beta; tang = V + dVdS * (s - S)39    fig, (a, b) = plt.subplots(1, 2, figsize=(LARGEUR, 3.1))40    a.plot(s, Vs, color=palette.cat[0], label=r"$V(S) = V_0\,(S/S_0)^{\beta}$, $\beta$ = 0,539")41    a.plot(s, tang, color=palette.cat[1], ls="--", lw=1.2, label="tangente en $S_0$ = 165 m²")42    a.axvspan(S * 0.95, S * 1.05, color=palette.cat[2], alpha=0.15, lw=0)43    a.plot([S], [V], "o", color=palette.ink, ms=4)44    for e in (-0.05, 0.05):45        se = S * (1 + e); ve = V * (1 + e) ** beta46        a.plot([se, se], [V, ve], color=palette.ink2, lw=0.8); a.plot([S, se], [ve, ve], color=palette.ink2, lw=0.8)47        a.annotate(("+" if e > 0 else "−") + f"{abs(ve - V):,.0f} $".replace(",", " "), (se, ve), xytext=(6 if e > 0 else -6, -12 if e > 0 else 8),48                   textcoords="offset points", ha="left" if e > 0 else "right", fontsize=7.5)49    a.set_xlabel("Superficie habitable mesurée (m²)"); a.set_ylabel("Valeur indiquée ($)")50    a.yaxis.set_major_formatter(plt.FuncFormatter(lambda x, p: f"{x/1000:.0f} k$")); a.legend(loc="upper left", fontsize=7.2)51    a.set_title("(a) Valeur du sujet et erreur de ±5 % sur S", loc="left")52    e = np.linspace(-0.15, 0.15, 121)53    b.plot(100 * e, 100 * ((1 + e) ** beta - 1), color=palette.cat[0], label="exact, β = 0,539")54    b.plot(100 * e, 100 * beta * e, color=palette.cat[1], ls="--", lw=1.2, label="linéaire, β·e")55    b.plot(100 * e, 100 * e, color=palette.cat[2], ls=":", lw=1.2, label="proportionnel (prix au m², β = 1)")56    mel = r["mel"]57    b.plot([mel["ecart_pct"]], [mel["sujet_brut_pct"]], "o", color=palette.ink, ms=4)58    b.annotate("sujet brut (190 m²)\nvs habitable (165 m²)", (mel["ecart_pct"], mel["sujet_brut_pct"]), xytext=(-10, -34), textcoords="offset points", ha="right", fontsize=7.2)59    b.axhline(0, color=palette.ink2, lw=0.6); b.axvline(0, color=palette.ink2, lw=0.6)60    b.set_xlabel("Erreur relative sur la superficie (%)"); b.set_ylabel("Erreur relative sur la valeur (%)")61    b.legend(loc="lower right", fontsize=7.2); b.set_title("(b) Propagation : erreur sur S → erreur sur V", loc="left")62    fig.tight_layout(w_pad=2.0)63    return savefig(fig, "ch12/ch12-fig-erreur-valeur.pdf")646566def fig_attenuation(r):67    att = r["att"]; beta = r["M"]["beta"]; var_e = att.attrs["var_e"]68    s = np.linspace(0, 0.22, 100); lam = var_e / (var_e + s ** 2)69    fig, (a, b) = plt.subplots(1, 2, figsize=(LARGEUR, 3.0))70    a.plot(s, lam * beta, color=palette.cat[0], label=r"théorie : $\lambda\,\beta$, $\lambda = \sigma_{\tilde e}^2/(\sigma_{\tilde e}^2+\sigma_u^2)$")71    a.errorbar(att["sigma_u"], att["beta_moyen"], yerr=att["beta_ecart_type"], fmt="o", color=palette.cat[1], ms=4, capsize=2, lw=1, label="simulation (200 tirages)")72    a.axhline(beta, color=palette.ink2, lw=0.7, ls=":"); a.text(0.002, beta + 0.004, f"β sans erreur = {beta:.3f}", fontsize=7.2)73    a.set_xlabel(r"Écart-type de l'erreur de mesure sur $\ln S$, $\sigma_u$"); a.set_ylabel(r"Coefficient estimé $\hat\beta_S$")74    a.set_ylim(0.28, 0.58); a.legend(loc="lower left", fontsize=7.2); a.set_title("(a) Atténuation du coefficient", loc="left")75    b.plot(att["sigma_u"], att["V_sujet_165"] / 1000, "o-", color=palette.cat[0], ms=4, label="sujet, 165 m²")76    b.plot(att["sigma_u"], att["V_maison_120"] / 1000, "s-", color=palette.cat[1], ms=4, label="maison de 120 m²")77    b.set_xlabel(r"$\sigma_u$"); b.set_ylabel("Valeur prédite (k$)"); b.legend(loc="center right", fontsize=7.2)78    b.set_title("(b) Le gradient prix-taille s'aplatit", loc="left")79    fig.tight_layout(w_pad=2.0)80    return savefig(fig, "ch12/ch12-fig-attenuation.pdf")818283def main():84    setup(); r = cas.tout()85    for f in (fig_conventions, fig_erreur, fig_attenuation):86        print("OK", f(r))878889if __name__ == "__main__":90    main()91
Files · 774056809e670c3d870d087d88dfeb8a0dd87f8e
Menu

Theme