SPB Git
2.5 KB · 48 lines python
1#!/usr/bin/env python32"""Figure ch22 — répartition du devis du sujet du cas 1 par corps de métier et par type d'unité de mesure3(mesuré en m³/m²/m lin., dénombré en unités/appareils/semaines, forfait). DONNÉES SYNTHÉTIQUES, graine 20261031.4Mêmes sept blocs et même ordre que la figure 21 (ch21_decomposition.py).5Sortie : assets/figures/ch22/ch22-fig-repartition-corps.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 matplotlib.pyplot as plt10from traite.style import setup, palette, savefig, LARGEUR, fmt_dollars11import ch21_cout_neuf as c2112import ch22_metre as cas131415def main():16    setup()17    devis, _ = c21.charger()18    rep = cas.repartition_par_type(devis)19    types = [c for c in ("mesuré", "dénombré", "forfait") if c in rep.columns]20    etiquettes = {"mesuré": "Mesuré (m³, m², m lin.)", "dénombré": "Dénombré (unités, appareils, semaines)", "forfait": "Forfait"}21    couleurs = {"mesuré": palette.cat[0], "dénombré": palette.cat[2], "forfait": palette.cat[1]}22    fig, ax = plt.subplots(figsize=(LARGEUR, 3.3))23    ordre = list(rep.index)[::-1]           # premier bloc en haut24    y = list(range(len(ordre)))25    gauche = [0.0] * len(ordre)26    for t in types:27        vals = [float(rep.loc[c, t]) for c in ordre]28        ax.barh(y, vals, left=gauche, color=couleurs[t], height=0.66, label=etiquettes[t])29        gauche = [g + v for g, v in zip(gauche, vals)]30    tot_di = float(rep.to_numpy().sum())31    for k, c in enumerate(ordre):32        tot = float(rep.loc[c].sum())33        ax.text(tot + 900, k, f"{fmt_dollars(tot)}  ({tot/tot_di*100:.1f} %)", va="center", ha="left", fontsize=8, color=palette.ink)34    ax.set_yticks(y); ax.set_yticklabels(ordre)35    ax.set_xlim(0, max(gauche) * 1.45)36    ax.xaxis.set_major_formatter(plt.FuncFormatter(fmt_dollars))37    ax.set_xlabel("Montant du devis (dollars de 2026) ; part du sous-total directs + indirects")38    ax.grid(axis="y", visible=False)39    parts = rep.sum() / tot_di * 10040    ax.set_title("Sous-total D + I = " + fmt_dollars(tot_di) + " : " + ", ".join(f"{etiquettes[t].split(' (')[0].lower()} {parts[t]:.1f} %" for t in types),41                 loc="left", fontsize=8.5, color=palette.ink)42    ax.legend(loc="upper center", bbox_to_anchor=(0.45, -0.2), ncol=3, fontsize=7.5)43    out = savefig(fig, "ch22/ch22-fig-repartition-corps.pdf"); print("OK", out)444546if __name__ == "__main__":47    main()48
Files · 11f6c54e39ac2d8ce41b1b464d12e942e4170c06
Menu

Theme