SPB Git
3.2 KB · 47 lines python
1#!/usr/bin/env python32"""Figure ch08 — effet d'un rezonage mesuré par ventes appariées et par doubles différences (DONNÉES SYNTHÉTIQUES).3(a) différence traité − témoin ajusté (% du témoin) selon l'âge de la maison, avec moyenne et médiane ;4(b) ln P moyen des ventes H1 traitées et témoins avant/après T0 (schéma 2 × 2) et contrefactuel.5Sortie : assets/figures/ch08/ch08-fig-rezonage-paires.pdf"""6import sys, pathlib7ROOT = pathlib.Path(__file__).resolve().parents[3]8sys.path.insert(0, str(ROOT / "analysis/python")); sys.path.insert(0, str(ROOT / "analysis/python/cases"))9import numpy as np, matplotlib.pyplot as plt10from traite.style import setup, palette, savefig, LARGEUR11import ch08_zonage as cas121314def main():15    setup()16    lots, ventes = cas.charger_ou_generer(ecrire=False)17    paires = cas.apparier(ventes); rp = cas.resume_paires(paires); d = cas.did(ventes)18    fig, (a, b) = plt.subplots(1, 2, figsize=(LARGEUR, 3.1), gridspec_kw={"width_ratios": [1.25, 1]})19    x = paires["age_traite"].to_numpy(); y = paires["difference_pct"].to_numpy() * 10020    a.scatter(x, y, s=18, color=palette.cat[0], linewidths=0, zorder=3)21    xx = np.linspace(x.min(), x.max(), 50); pente, orig = np.polyfit(x, y, 1)22    a.plot(xx, orig + pente * xx, color=palette.cat[0], linewidth=1.2)23    a.plot(xx, (np.exp([cas.prime_rezonage(v) for v in xx]) - 1) * 100, color=palette.ink2, linestyle="--", linewidth=1.0)24    a.axhline(rp["moyenne_pct"] * 100, color=palette.cat[1], linewidth=1.0)25    a.axhline(rp["mediane_pct"] * 100, color=palette.cat[1], linewidth=1.0, linestyle=":")26    a.text(x.max(), rp["moyenne_pct"] * 100 + 1.2, f"moyenne {rp['moyenne_pct']*100:.1f} %", ha="right", fontsize=7.5, color=palette.ink)27    a.text(x.max(), rp["mediane_pct"] * 100 - 3.2, f"médiane {rp['mediane_pct']*100:.1f} %", ha="right", fontsize=7.5, color=palette.ink)28    a.text(x.max(), y.min() + 1.0, "tireté : prime injectée\n(vérité du générateur)", ha="right", fontsize=7, color=palette.ink2)29    a.set_xlabel("Âge de la maison traitée (années)"); a.set_ylabel("Traité − témoin ajusté (% du témoin)")30    a.set_title(f"(a) {rp['n']} paires appariées", loc="left")31    m = d["moyennes_lnP"]32    xs = [0, 1]33    b.plot(xs, [m[(False, False)], m[(False, True)]], marker="o", color=palette.cat[2], label="témoins (reste de H1)")34    b.plot(xs, [m[(True, False)], m[(True, True)]], marker="o", color=palette.cat[0], label="traités (îlot rezoné)")35    cf = m[(True, False)] + (m[(False, True)] - m[(False, False)])36    b.plot(xs, [m[(True, False)], cf], marker="o", markerfacecolor="none", color=palette.cat[0], linestyle="--", label="contrefactuel des traités")37    b.annotate("", xy=(1, m[(True, True)]), xytext=(1, cf), arrowprops=dict(arrowstyle="<->", color=palette.ink, lw=1.0))38    b.text(1.03, (m[(True, True)] + cf) / 2, f"δ = {d['delta_2x2']:.3f}\n(2 × 2)", fontsize=7.5, va="center", color=palette.ink)39    b.set_xticks(xs); b.set_xticklabels(["avant T0", "après T0"]); b.set_ylabel("ln P moyen (ventes H1)")40    b.set_xlim(-0.3, 1.5); b.set_title("(b) doubles différences", loc="left"); b.legend(loc="upper left", fontsize=7)41    fig.tight_layout()42    savefig(fig, "ch08/ch08-fig-rezonage-paires.pdf")434445if __name__ == "__main__":46    main()47
Files · 2eb2bf4e67f754808bae5090a9e53eab37149ddb
Menu

Theme