Ch. 19 livré et validé (compilation isolée, tests, fusion des registres)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
47 changed files +2,984 −89
added
analysis/python/cases/ch20_reconciliation.py
+338 −0
@@ -0,0 +1,338 @@ | |||||
| 1 | +#!/usr/bin/env python3 | ||||
| 2 | +"""Chapitre 20 — réconciliation et incertitude : combinaison des indications du cas 1 (Gatineau, données synthétiques). | ||||
| 3 | + | ||||
| 4 | +Reprend sans les recalculer « à la main » : la sélection du chapitre 16 (traite.cas1.selection), la grille hédonique du | ||||
| 5 | +chapitre 17 (traite.cas1.ajustements_hedoniques), le modèle de référence et la prédiction du chapitre 18 | ||||
| 6 | +(traite.cas1.hedonique / predire / intervalle_prediction) et le coût neuf du chapitre 21 (ch21_cout_neuf.cout_neuf_sujet). | ||||
| 7 | +Ajoute : bootstrap des comparables (candidats, ajustements, les deux), énumération exhaustive des sous-ensembles de cinq | ||||
| 8 | +comparables, indication par le coût sous hypothèses déclarées, pondération (égale, inverse de la variance, moindres carrés | ||||
| 9 | +généralisés avec corrélation, raisonnée), fourchette de la conclusion, et « vérité » de la loi de génération. | ||||
| 10 | +Imprime tous les chiffres cités dans le chapitre. | ||||
| 11 | +Usage (racine du dépôt) : PYTHONPATH=analysis/python python3 analysis/python/cases/ch20_reconciliation.py""" | ||||
| 12 | +from __future__ import annotations | ||||
| 13 | +import sys, pathlib, math, itertools, datetime | ||||
| 14 | +import numpy as np, pandas as pd | ||||
| 15 | +HERE = pathlib.Path(__file__).resolve() | ||||
| 16 | +sys.path.insert(0, str(HERE.parents[1])) | ||||
| 17 | +sys.path.insert(0, str(HERE.parent)) | ||||
| 18 | +from traite import cas1, cout as ct, comparables as cp | ||||
| 19 | +import ch21_cout_neuf as c21 | ||||
| 20 | + | ||||
| 21 | +ROOT = HERE.parents[3] | ||||
| 22 | +GRAINE = 20261031 | ||||
| 23 | +B = 2000 # réplications bootstrap | ||||
| 24 | +PLANCHER_BRUT = 0.01 # plancher de l'inverse du brut (ch. 17, eq. 17.poids) | ||||
| 25 | +GROUPES = ["conditions_marche", "localisation", "superficie", "terrain", "age", "qualite", "garage", "sous_sol", "piscine", "type"] | ||||
| 26 | +COLS_GROUPES = {"conditions_marche": ["mois"], "localisation": ["dist_centre"] + [f"sect_{x}" for x in cas1.SECTEURS[1:]], | ||||
| 27 | + "superficie": ["ln_S"], "terrain": ["ln_T"], "age": ["age", "age2_100"], "qualite": ["qualite"], | ||||
| 28 | + "garage": ["garage"], "sous_sol": ["sous_sol"], "piscine": ["piscine"], "type": ["etages"]} | ||||
| 29 | +# Hypothèses déclarées de l'indication par le coût (à aligner avec les ch. 24 et 25 ; voir verification/chapters/ch20.md) | ||||
| 30 | +ALPHA_TERRAIN = 0.30 # part du terrain dans la valeur (méthode d'allocation) — hypothèse pédagogique, NON_VERIFIE | ||||
| 31 | +VIE_ECONOMIQUE = 60 # vie économique totale (ans), méthode âge-vie — hypothèse pédagogique, NON_VERIFIE | ||||
| 32 | +AGE_EFFECTIF = 28 # âge effectif = âge chronologique (entretien normal présumé, aucune inspection dans le dossier) | ||||
| 33 | +GRILLE_ALPHA = [0.20, 0.25, 0.30, 0.35, 0.40] | ||||
| 34 | +GRILLE_VIE = [50, 60, 75] | ||||
| 35 | +# Prédictions du sujet sous les quatre spécifications « en logarithme » du ch. 18 (tab. 18.variantes : semi-log, log-log, | ||||
| 36 | +# Box–Cox, indicatrices trimestrielles) : sert à l'incertitude de spécification du modèle hédonique. | ||||
| 37 | +PRED_SPEC_CH18 = [637953.0, 627260.0, 635171.0, 649980.0] | ||||
| 38 | +POIDS_RAISONNES = {"comparaison": 0.40, "hedonique": 0.55, "cout": 0.05} | ||||
| 39 | +ARRONDI_CONCLUSION = 5000 | ||||
| 40 | + | ||||
| 41 | + | ||||
| 42 | +# ---------------------------------------------------------------- 1. indications héritées des chapitres 16 à 18 | ||||
| 43 | +def base() -> dict: | ||||
| 44 | + t = cas1.tout() | ||||
| 45 | + m = t["modele"]; sel = t["selection"]; s = t["sujet"]; v = t["ventes"] | ||||
| 46 | + cand = sel["candidats"].copy() # 16 candidats, triés par distance d'attributs croissante | ||||
| 47 | + comps = sel["comparables"] | ||||
| 48 | + adj16 = cas1.ajustements_hedoniques(m, cand, s) | ||||
| 49 | + adj16["distance"] = cand["distance"].values | ||||
| 50 | + res = pd.Series(m["residus"], index=v.index) | ||||
| 51 | + adj16["residu_log"] = res.loc[cand.index].values | ||||
| 52 | + adj16["retenu"] = np.arange(len(cand)) < len(comps) | ||||
| 53 | + adj5 = adj16[adj16["retenu"]].copy() | ||||
| 54 | + # indication par comparaison, exactement comme au chapitre 17 (bibliothèque traite.comparables) | ||||
| 55 | + ca = [cp.ComparableAjuste(r["id_vente"], r["prix_vente"], {g: r[g] for g in GROUPES}) for _, r in adj5.iterrows()] | ||||
| 56 | + w = cp.poids_inverse_brut(ca, PLANCHER_BRUT) | ||||
| 57 | + rec = cp.reconciliation(ca, w) | ||||
| 58 | + cols = list(m["X"].columns) | ||||
| 59 | + Xs = cas1.matrice(cas1.sujet_df(s))[cols].values[0] | ||||
| 60 | + Xc16 = cas1.matrice(cand)[cols].values | ||||
| 61 | + G = np.zeros((len(cols), len(GROUPES))) | ||||
| 62 | + for j, g in enumerate(GROUPES): | ||||
| 63 | + for c in COLS_GROUPES[g]: | ||||
| 64 | + G[cols.index(c), j] = 1.0 | ||||
| 65 | + return {**t, "cand": cand, "comps": comps, "adj16": adj16, "adj5": adj5, "poids_comp": np.array(w), "reconciliation": rec, | ||||
| 66 | + "V_comp": rec["valeur_ponderee"], "sd_comp_pondere": rec["ecart_type_pondere"], "V_hed": t["prediction_hedonique"], | ||||
| 67 | + "ip_hed": t["intervalle"], "cols": cols, "Xs": Xs, "Xc16": Xc16, "P16": cand["prix_vente"].values.astype(float), "G": G, | ||||
| 68 | + "X": m["X"].values, "y": m["y"], "beta": m["beta"], "V_hc1": m["V_hc1"], "sigma": m["sigma"]} | ||||
| 69 | + | ||||
| 70 | + | ||||
| 71 | +def grille_rapide(beta: np.ndarray, Xs: np.ndarray, Xc: np.ndarray, P: np.ndarray, G: np.ndarray, plancher: float = PLANCHER_BRUT) -> dict: | ||||
| 72 | + """Cascade hédonique vectorisée (identique à traite.cas1.ajustements_hedoniques) : Δ_k par groupe, bases cumulées, | ||||
| 73 | + ajustements A_k = B_{k-1}(e^{Δ_k} − 1), prix ajusté P e^{ΣΔ}, brut Σ|A_k|/P, poids inverse du brut, valeur pondérée.""" | ||||
| 74 | + D = ((Xs[None, :] - Xc) * beta[None, :]) @ G # n_c × n_groupes | ||||
| 75 | + cum = np.cumsum(D, axis=1) | ||||
| 76 | + bases = P[:, None] * np.exp(cum) | ||||
| 77 | + bases_prec = np.hstack([P[:, None], bases[:, :-1]]) | ||||
| 78 | + A = bases_prec * (np.exp(D) - 1.0) | ||||
| 79 | + P_aj = bases[:, -1] | ||||
| 80 | + brut = np.abs(A).sum(axis=1) / P | ||||
| 81 | + w = 1.0 / np.maximum(brut, plancher); w = w / w.sum() | ||||
| 82 | + V = float(w @ P_aj) | ||||
| 83 | + return {"P_aj": P_aj, "brut": brut, "poids": w, "valeur": V, "sd_pondere": float(math.sqrt(w @ (P_aj - V) ** 2))} | ||||
| 84 | + | ||||
| 85 | + | ||||
| 86 | +def valeur_ponderee(P_aj: np.ndarray, brut: np.ndarray, plancher: float = PLANCHER_BRUT) -> float: | ||||
| 87 | + w = 1.0 / np.maximum(brut, plancher) | ||||
| 88 | + return float((w @ P_aj) / w.sum()) | ||||
| 89 | + | ||||
| 90 | + | ||||
| 91 | +# ---------------------------------------------------------------- 2. bootstrap des comparables | ||||
| 92 | +def bootstrap(b: dict, B: int = B, graine: int = GRAINE) -> dict: | ||||
| 93 | + """Trois rééchantillonnages : (A) les 16 candidats avec remise puis sélection des 5 plus proches (modèle fixe) ; | ||||
| 94 | + (B) les 600 ventes avec remise, réestimation du modèle, grille des 5 comparables fixes et prédiction du sujet ; | ||||
| 95 | + (C) les deux à la fois (même réplication b pour la corrélation) ; variante paramétrique β* ~ N(β̂, V_HC1).""" | ||||
| 96 | + rng = np.random.default_rng(graine) | ||||
| 97 | + n_c = len(b["P16"]); k = len(b["comps"]) | ||||
| 98 | + g0 = grille_rapide(b["beta"], b["Xs"], b["Xc16"], b["P16"], b["G"]) | ||||
| 99 | + P_aj16, brut16 = g0["P_aj"], g0["brut"] | ||||
| 100 | + # (A) candidats | ||||
| 101 | + idxA = np.sort(rng.integers(0, n_c, size=(B, n_c)), axis=1)[:, :k] # candidats triés par distance : rang = indice | ||||
| 102 | + VA = np.array([valeur_ponderee(P_aj16[i], brut16[i]) for i in idxA]) | ||||
| 103 | + # (B) modèle (bootstrap par paires) | ||||
| 104 | + X, y = b["X"], b["y"]; n = len(y) | ||||
| 105 | + idxB = rng.integers(0, n, size=(B, n)) | ||||
| 106 | + betas = np.empty((B, X.shape[1])); duan = np.empty(B) | ||||
| 107 | + for r in range(B): | ||||
| 108 | + Xb, yb = X[idxB[r]], y[idxB[r]] | ||||
| 109 | + beta_b, *_ = np.linalg.lstsq(Xb, yb, rcond=None) | ||||
| 110 | + betas[r] = beta_b; duan[r] = float(np.mean(np.exp(yb - Xb @ beta_b))) | ||||
| 111 | + pred = np.exp(betas @ b["Xs"]) * duan | ||||
| 112 | + retenus = np.arange(k) | ||||
| 113 | + VB = np.empty(B); VC = np.empty(B) | ||||
| 114 | + for r in range(B): | ||||
| 115 | + g = grille_rapide(betas[r], b["Xs"], b["Xc16"], b["P16"], b["G"]) | ||||
| 116 | + VB[r] = valeur_ponderee(g["P_aj"][retenus], g["brut"][retenus]) | ||||
| 117 | + VC[r] = valeur_ponderee(g["P_aj"][idxA[r]], g["brut"][idxA[r]]) | ||||
| 118 | + # variante paramétrique (coefficients tirés de la normale asymptotique, comparables fixes) | ||||
| 119 | + betasP = rng.multivariate_normal(b["beta"], b["V_hc1"], size=B) | ||||
| 120 | + VP = np.array([valeur_ponderee(*(lambda g: (g["P_aj"][retenus], g["brut"][retenus]))(grille_rapide(bp, b["Xs"], b["Xc16"], b["P16"], b["G"]))) for bp in betasP]) | ||||
| 121 | + def resume(x): | ||||
| 122 | + q = np.percentile(x, [2.5, 5, 25, 50, 75, 95, 97.5]) | ||||
| 123 | + return {"moyenne": float(x.mean()), "ecart_type": float(x.std(ddof=1)), "q025": q[0], "q05": q[1], "q25": q[2], "q50": q[3], "q75": q[4], "q95": q[5], "q975": q[6]} | ||||
| 124 | + rho = float(np.corrcoef(VC, pred)[0, 1]) | ||||
| 125 | + rhoB = float(np.corrcoef(VB, pred)[0, 1]) | ||||
| 126 | + return {"P_aj16": P_aj16, "brut16": brut16, "idxA": idxA, "VA": VA, "VB": VB, "VC": VC, "VP": VP, "pred": pred, "betas": betas, | ||||
| 127 | + "resume": {"candidats": resume(VA), "ajustements": resume(VB), "conjoint": resume(VC), "parametrique": resume(VP), "prediction": resume(pred)}, | ||||
| 128 | + "rho_conjoint_pred": rho, "rho_ajustements_pred": rhoB, | ||||
| 129 | + "part_A_sous_hed": float((VA < b["V_hed"]).mean()), "part_C_sous_hed": float((VC < b["V_hed"]).mean()), | ||||
| 130 | + "part_C_au_dessus_comp": float((VC > b["V_comp"]).mean())} | ||||
| 131 | + | ||||
| 132 | + | ||||
| 133 | +def exhaustif(b: dict, P_aj16: np.ndarray, brut16: np.ndarray, k: int = 5) -> dict: | ||||
| 134 | + """Tous les sous-ensembles de k candidats parmi les 16 (C(16,5) = 4368), modèle fixe.""" | ||||
| 135 | + n_c = len(P_aj16) | ||||
| 136 | + vals = []; n_retenus = [] | ||||
| 137 | + for sub in itertools.combinations(range(n_c), k): | ||||
| 138 | + i = np.array(sub) | ||||
| 139 | + vals.append(valeur_ponderee(P_aj16[i], brut16[i])); n_retenus.append(int((i < k).sum())) | ||||
| 140 | + vals = np.array(vals); n_retenus = np.array(n_retenus) | ||||
| 141 | + q = np.percentile(vals, [2.5, 5, 50, 95, 97.5]) | ||||
| 142 | + par_n = pd.DataFrame({"n_retenus": n_retenus, "valeur": vals}).groupby("n_retenus")["valeur"].agg(["count", "mean", "min", "max"]) | ||||
| 143 | + return {"valeurs": vals, "n": len(vals), "moyenne": float(vals.mean()), "ecart_type": float(vals.std(ddof=1)), "min": float(vals.min()), | ||||
| 144 | + "max": float(vals.max()), "q025": q[0], "q05": q[1], "q50": q[2], "q95": q[3], "q975": q[4], "par_n_retenus": par_n, | ||||
| 145 | + "rang_selection": int((vals < b["V_comp"]).sum()), "part_sous_hed": float((vals < b["V_hed"]).mean())} | ||||
| 146 | + | ||||
| 147 | + | ||||
| 148 | +# ---------------------------------------------------------------- 3. indication par le coût (hypothèses déclarées) | ||||
| 149 | +def cout(b: dict, alpha: float = ALPHA_TERRAIN, vie: float = VIE_ECONOMIQUE, age_eff: float = AGE_EFFECTIF) -> dict: | ||||
| 150 | + devis, sujet = c21.charger() | ||||
| 151 | + cn = c21.cout_neuf_sujet(devis) | ||||
| 152 | + CN = cn["total"] | ||||
| 153 | + V_L = alpha * b["V_comp"] # allocation : part α de l'indication par comparaison | ||||
| 154 | + D = ct.depreciation_age_vie(CN, age_eff, vie) | ||||
| 155 | + val = ct.valeur_par_cout(V_L, CN, D) | ||||
| 156 | + extraction_hed = ct.extraction_depreciation_marche(b["V_hed"], V_L, CN, age_eff) | ||||
| 157 | + extraction_comp = ct.extraction_depreciation_marche(b["V_comp"], V_L, CN, age_eff) | ||||
| 158 | + grille = pd.DataFrame([{"alpha": a, "vie": vv, "V_L": a * b["V_comp"], "D": ct.depreciation_age_vie(CN, age_eff, vv), | ||||
| 159 | + "valeur": ct.valeur_par_cout(a * b["V_comp"], CN, ct.depreciation_age_vie(CN, age_eff, vv))["valeur"]} | ||||
| 160 | + for a in GRILLE_ALPHA for vv in GRILLE_VIE]) | ||||
| 161 | + # âge effectif réduit (entretien supérieur) : variante | ||||
| 162 | + age_var = {ae: ct.valeur_par_cout(V_L, CN, ct.depreciation_age_vie(CN, ae, vie))["valeur"] for ae in (20, 24, 28)} | ||||
| 163 | + # terrain nécessaire pour que le coût rejoigne la comparaison ou le modèle (D âge-vie inchangée) | ||||
| 164 | + return {"CN": CN, "V_L": V_L, "D": D, "taux_D": D / CN, "contribution_batiment": val["contribution_batiment"], "valeur": val["valeur"], | ||||
| 165 | + "extraction_hed": extraction_hed, "extraction_comp": extraction_comp, "grille": grille, | ||||
| 166 | + "sd_grille": float(grille["valeur"].std(ddof=0)), "min_grille": float(grille["valeur"].min()), "max_grille": float(grille["valeur"].max()), | ||||
| 167 | + "age_effectif_variantes": age_var, "V_L_pour_comp": b["V_comp"] - (CN - D), "V_L_pour_hed": b["V_hed"] - (CN - D), | ||||
| 168 | + "cout_neuf_plus_terrain": CN + V_L, "alpha": alpha, "vie": vie, "age_eff": age_eff} | ||||
| 169 | + | ||||
| 170 | + | ||||
| 171 | +# ---------------------------------------------------------------- 4. combinaison | ||||
| 172 | +def poids_optimaux_deux(s1: float, s2: float, rho: float) -> float: | ||||
| 173 | + """Poids optimal de l'indication 1 parmi deux indications corrélées (Bates–Granger) : w1 = (σ2² − ρσ1σ2)/(σ1² + σ2² − 2ρσ1σ2).""" | ||||
| 174 | + return (s2 ** 2 - rho * s1 * s2) / (s1 ** 2 + s2 ** 2 - 2 * rho * s1 * s2) | ||||
| 175 | + | ||||
| 176 | + | ||||
| 177 | +def poids_gls(Sigma: np.ndarray) -> np.ndarray: | ||||
| 178 | + """w = Σ⁻¹1 / 1'Σ⁻¹1 (variance minimale sous Σw = 1, poids non contraints).""" | ||||
| 179 | + inv = np.linalg.inv(Sigma); un = np.ones(Sigma.shape[0]) | ||||
| 180 | + w = inv @ un | ||||
| 181 | + return w / w.sum() | ||||
| 182 | + | ||||
| 183 | + | ||||
| 184 | +def combinaison(b: dict, bs: dict, co: dict, graine: int = GRAINE) -> dict: | ||||
| 185 | + V = np.array([b["V_comp"], b["V_hed"], co["valeur"]]) | ||||
| 186 | + sd_spec = float(np.std(PRED_SPEC_CH18, ddof=1)) | ||||
| 187 | + sd_pred_boot = bs["resume"]["prediction"]["ecart_type"] | ||||
| 188 | + s = np.array([bs["resume"]["conjoint"]["ecart_type"], math.sqrt(sd_pred_boot ** 2 + sd_spec ** 2), co["sd_grille"]]) | ||||
| 189 | + rho = bs["rho_conjoint_pred"] | ||||
| 190 | + Sigma = np.diag(s ** 2); Sigma[0, 1] = Sigma[1, 0] = rho * s[0] * s[1] | ||||
| 191 | + schemas = { | ||||
| 192 | + "comparaison seule": np.array([1.0, 0.0, 0.0]), | ||||
| 193 | + "hédonique seule": np.array([0.0, 1.0, 0.0]), | ||||
| 194 | + "égale (un tiers chacune)": np.ones(3) / 3, | ||||
| 195 | + "inverse de la variance (indépendance)": (1 / s ** 2) / (1 / s ** 2).sum(), | ||||
| 196 | + "variance minimale avec corrélation (MCG)": poids_gls(Sigma), | ||||
| 197 | + "raisonnée (retenue)": np.array([POIDS_RAISONNES["comparaison"], POIDS_RAISONNES["hedonique"], POIDS_RAISONNES["cout"]]), | ||||
| 198 | + } | ||||
| 199 | + tab = pd.DataFrame([{"schema": k, "w_comp": w[0], "w_hed": w[1], "w_cout": w[2], "valeur": float(w @ V), "ecart_type": float(math.sqrt(w @ Sigma @ w))} | ||||
| 200 | + for k, w in schemas.items()]) | ||||
| 201 | + # distribution bootstrap de la conclusion retenue (réplication conjointe : comparaison et modèle issus du même tirage ; coût tiré de la grille) | ||||
| 202 | + rng = np.random.default_rng(graine + 1) | ||||
| 203 | + cout_b = rng.choice(co["grille"]["valeur"].values, size=len(bs["VC"])) | ||||
| 204 | + w = schemas["raisonnée (retenue)"] | ||||
| 205 | + Vb = w[0] * bs["VC"] + w[1] * bs["pred"] + w[2] * cout_b | ||||
| 206 | + q = np.percentile(Vb, [2.5, 5, 50, 95, 97.5]) | ||||
| 207 | + V_raisonnee = float(w @ V) | ||||
| 208 | + arrondi = ARRONDI_CONCLUSION | ||||
| 209 | + conclusion = round(V_raisonnee / arrondi) * arrondi | ||||
| 210 | + fourchette90 = (math.floor(q[1] / arrondi) * arrondi, math.ceil(q[3] / arrondi) * arrondi) | ||||
| 211 | + # courbes de sensibilité aux poids : w_hed de 0 à 1 − w_cout, pour trois poids du coût | ||||
| 212 | + wh = np.linspace(0, 1, 101) | ||||
| 213 | + courbes = {wc: np.array([ (1 - h - wc) * V[0] + h * V[1] + wc * V[2] if h <= 1 - wc + 1e-12 else np.nan for h in wh]) for wc in (0.0, 0.05, 0.10)} | ||||
| 214 | + # variance de la combinaison de deux indications (comparaison, hédonique) selon ρ | ||||
| 215 | + var_deux = {r: np.array([((1 - h) ** 2) * s[0] ** 2 + h ** 2 * s[1] ** 2 + 2 * h * (1 - h) * r * s[0] * s[1] for h in wh]) for r in (0.0, 0.3, 0.6, 0.9)} | ||||
| 216 | + w_opt_deux = {r: poids_optimaux_deux(s[0], s[1], r) for r in (0.0, rho, 0.3, 0.6, 0.9)} | ||||
| 217 | + return {"V": V, "s": s, "sd_spec_hed": sd_spec, "sd_pred_boot": sd_pred_boot, "rho": rho, "Sigma": Sigma, "schemas": schemas, "tableau": tab, | ||||
| 218 | + "Vb": Vb, "cout_b": cout_b, "q": {"q025": q[0], "q05": q[1], "q50": q[2], "q95": q[3], "q975": q[4]}, "V_raisonnee": V_raisonnee, | ||||
| 219 | + "conclusion": conclusion, "fourchette90": fourchette90, "wh": wh, "courbes": courbes, "var_deux": var_deux, "w_opt_deux": w_opt_deux, | ||||
| 220 | + "ecart_conclusion_comp": conclusion / b["V_comp"] - 1, "ecart_conclusion_hed": conclusion / b["V_hed"] - 1} | ||||
| 221 | + | ||||
| 222 | + | ||||
| 223 | +# ---------------------------------------------------------------- 5. ce que révèle la loi de génération | ||||
| 224 | +def verite(b: dict) -> dict: | ||||
| 225 | + """Espérance conditionnelle « vraie » du prix du sujet selon la loi déclarée dans data/synthetic/README.md ; | ||||
| 226 | + la constante (normalisation de la médiane) est estimée sur les 600 ventes (erreur-type σ/√n ≈ 0,35 %).""" | ||||
| 227 | + from traite.synth import _mois_depuis | ||||
| 228 | + v = b["ventes"]; s = b["sujet"] | ||||
| 229 | + med = 475000.0; med_sect = {"Gatineau": 464900.0, "Aylmer": 530000.0, "Buckingham": 395000.0, "Masson-Angers": 395000.0} | ||||
| 230 | + prime = {"Hull": 0.0, **{k: math.log(m / med) for k, m in med_sect.items()}}; prime["Masson-Angers"] -= 0.02 | ||||
| 231 | + g = 1.0906 ** 0.5 - 1 | ||||
| 232 | + ref = _mois_depuis([datetime.date(2024, 7, 1)])[0] | ||||
| 233 | + def f(df, dates): | ||||
| 234 | + mois = _mois_depuis([d.date() for d in pd.to_datetime(dates)]) | ||||
| 235 | + return (0.55 * np.log(df["superficie_habitable_m2"].values / 140) + 0.10 * np.log(df["superficie_terrain_m2"].values / 560) | ||||
| 236 | + - 0.0055 * df["age"].values + 0.00003 * df["age"].values ** 2 + 0.06 * (df["qualite_1a5"].values - 3) | ||||
| 237 | + + 0.035 * df["garage_places"].values + 0.03 * df["sous_sol_fini"].values + 0.02 * df["piscine"].values | ||||
| 238 | + + np.array([prime[x] for x in df["secteur"].values]) - 0.006 * np.clip(df["dist_centre_km"].values - 3, 0, None) | ||||
| 239 | + + 0.02 * (df["type"].values == "à étages") + math.log1p(g) * (mois - ref) / 12) | ||||
| 240 | + fv = f(v, v["date_vente"]); e = np.log(v["prix_vente"].values) - fv | ||||
| 241 | + c_hat = float(e.mean()); se_c = float(e.std(ddof=1) / math.sqrt(len(e))) | ||||
| 242 | + sd = cas1.sujet_df(s); fs = float(f(sd, sd["date_vente"])[0]) | ||||
| 243 | + V_true = math.exp(fs + c_hat) * math.exp(0.085 ** 2 / 2) | ||||
| 244 | + return {"c_hat": c_hat, "se_c": se_c, "sigma_e": float(e.std(ddof=1)), "V_true": V_true, | ||||
| 245 | + "V_true_bas": V_true * math.exp(-1.96 * se_c), "V_true_haut": V_true * math.exp(1.96 * se_c), | ||||
| 246 | + "ecart_comp": b["V_comp"] / V_true - 1, "ecart_hed": b["V_hed"] / V_true - 1} | ||||
| 247 | + | ||||
| 248 | + | ||||
| 249 | +# ---------------------------------------------------------------- 6. exercices (chiffres des solutions) | ||||
| 250 | +def exercices(b: dict, bs: dict, co: dict, cb: dict) -> dict: | ||||
| 251 | + out = {} | ||||
| 252 | + # ex. 1 : deux indications indépendantes | ||||
| 253 | + V1, s1, V2, s2 = 582000.0, 30000.0, 636000.0, 12000.0 | ||||
| 254 | + w1 = (1 / s1 ** 2) / (1 / s1 ** 2 + 1 / s2 ** 2) | ||||
| 255 | + out["ex1"] = {"w1": w1, "w2": 1 - w1, "V": w1 * V1 + (1 - w1) * V2, "sd": math.sqrt(1 / (1 / s1 ** 2 + 1 / s2 ** 2)), | ||||
| 256 | + "V_egal": 0.5 * (V1 + V2), "sd_egal": math.sqrt(0.25 * s1 ** 2 + 0.25 * s2 ** 2)} | ||||
| 257 | + # ex. 3 : poids optimaux avec corrélation | ||||
| 258 | + out["ex3"] = {r: {"w1": poids_optimaux_deux(s1, s2, r), | ||||
| 259 | + "sd": math.sqrt(max(0.0, (lambda w: w ** 2 * s1 ** 2 + (1 - w) ** 2 * s2 ** 2 + 2 * w * (1 - w) * r * s1 * s2)(poids_optimaux_deux(s1, s2, r))))} | ||||
| 260 | + for r in (0.0, 0.3, 0.5, 0.6)} | ||||
| 261 | + # ex. 4 : bootstrap à la main (percentiles de 20 réplications données) | ||||
| 262 | + rep = np.array([561, 568, 571, 574, 576, 577, 579, 580, 582, 583, 585, 586, 588, 590, 592, 595, 598, 603, 611, 624]) * 1000.0 | ||||
| 263 | + out["ex4"] = {"moyenne": float(rep.mean()), "ecart_type": float(rep.std(ddof=1)), "q05": float(np.percentile(rep, 5)), "q95": float(np.percentile(rep, 95)), | ||||
| 264 | + "q10": float(np.percentile(rep, 10)), "q90": float(np.percentile(rep, 90))} | ||||
| 265 | + # ex. 5 : coût avec autres hypothèses | ||||
| 266 | + CN = co["CN"] | ||||
| 267 | + out["ex5"] = {"a": ct.valeur_par_cout(0.35 * b["V_comp"], CN, ct.depreciation_age_vie(CN, 22, 60))["valeur"], | ||||
| 268 | + "b": ct.valeur_par_cout(0.35 * b["V_comp"], CN, ct.depreciation_age_vie(CN, 28, 75))["valeur"], | ||||
| 269 | + "extraction": ct.extraction_depreciation_marche(b["V_hed"], 0.35 * b["V_comp"], CN, 28)} | ||||
| 270 | + # ex. 7 : incidence d'une hypothèse extraordinaire (eq. 10.incidence / 10.esperance) | ||||
| 271 | + out["ex7"] = {"V_H": cb["conclusion"], "V_nonH": cb["conclusion"] - 14000.0, "p": 0.7} | ||||
| 272 | + out["ex7"]["delta"] = out["ex7"]["V_H"] - out["ex7"]["V_nonH"] | ||||
| 273 | + out["ex7"]["esperance"] = out["ex7"]["V_nonH"] + out["ex7"]["p"] * out["ex7"]["delta"] | ||||
| 274 | + return out | ||||
| 275 | + | ||||
| 276 | + | ||||
| 277 | +# ---------------------------------------------------------------- tout | ||||
| 278 | +_CACHE: dict = {} | ||||
| 279 | + | ||||
| 280 | +def tout(verbose: bool = False) -> dict: | ||||
| 281 | + if "r" in _CACHE: | ||||
| 282 | + return _CACHE["r"] | ||||
| 283 | + b = base() | ||||
| 284 | + bs = bootstrap(b) | ||||
| 285 | + ex = exhaustif(b, bs["P_aj16"], bs["brut16"]) | ||||
| 286 | + co = cout(b) | ||||
| 287 | + cb = combinaison(b, bs, co) | ||||
| 288 | + vt = verite(b) | ||||
| 289 | + exo = exercices(b, bs, co, cb) | ||||
| 290 | + r = {"base": b, "bootstrap": bs, "exhaustif": ex, "cout": co, "combinaison": cb, "verite": vt, "exercices": exo} | ||||
| 291 | + _CACHE["r"] = r | ||||
| 292 | + if verbose: | ||||
| 293 | + imprimer(r) | ||||
| 294 | + return r | ||||
| 295 | + | ||||
| 296 | + | ||||
| 297 | +def imprimer(r: dict) -> None: | ||||
| 298 | + b, bs, ex, co, cb, vt = r["base"], r["bootstrap"], r["exhaustif"], r["cout"], r["combinaison"], r["verite"] | ||||
| 299 | + f = lambda x: f"{x:,.0f}".replace(",", " ") | ||||
| 300 | + print("=== Indications héritées ===") | ||||
| 301 | + print(f"Comparaison (ch. 17) : pondérée {f(b['V_comp'])} $, écart-type pondéré {f(b['sd_comp_pondere'])} $, poids {np.round(b['poids_comp'], 3)}") | ||||
| 302 | + ip = b["ip_hed"] | ||||
| 303 | + print(f"Hédonique (ch. 18) : {f(b['V_hed'])} $ (Duan) ; IP 95 % [{f(ip['bas'])} ; {f(ip['haut'])}]") | ||||
| 304 | + print("\n=== 16 candidats : prix ajusté, brut, résidu (%) ===") | ||||
| 305 | + a = b["adj16"] | ||||
| 306 | + print(a[["id_vente", "distance", "prix_vente", "prix_ajuste", "ajust_brut_pct", "residu_log", "retenu"]].assign(residu_pct=lambda d: np.exp(d["residu_log"]) - 1).round(4).to_string(index=False)) | ||||
| 307 | + print(f"résidu moyen (exp−1) des 5 retenus : {np.mean(np.exp(a.loc[a['retenu'], 'residu_log']) - 1):.4f} ; des 11 autres : {np.mean(np.exp(a.loc[~a['retenu'], 'residu_log']) - 1):.4f} ; des 16 : {np.mean(np.exp(a['residu_log']) - 1):.4f}") | ||||
| 308 | + print("\n=== Bootstrap (B = %d) ===" % B) | ||||
| 309 | + for k, v in bs["resume"].items(): | ||||
| 310 | + print(f"{k:14s} moy {f(v['moyenne'])} é.-t. {f(v['ecart_type'])} q2.5 {f(v['q025'])} q5 {f(v['q05'])} q50 {f(v['q50'])} q95 {f(v['q95'])} q97.5 {f(v['q975'])}") | ||||
| 311 | + print(f"corrélation (conjoint, prédiction) = {bs['rho_conjoint_pred']:.3f} ; (ajustements, prédiction) = {bs['rho_ajustements_pred']:.3f}") | ||||
| 312 | + print(f"part des rééchantillons de candidats sous la prédiction hédonique : {bs['part_A_sous_hed']:.3f} ; conjoint : {bs['part_C_sous_hed']:.3f}") | ||||
| 313 | + print("\n=== Énumération exhaustive C(16,5) ===") | ||||
| 314 | + print(f"n = {ex['n']} ; moyenne {f(ex['moyenne'])} ; é.-t. {f(ex['ecart_type'])} ; min {f(ex['min'])} ; max {f(ex['max'])} ; q5 {f(ex['q05'])} ; q50 {f(ex['q50'])} ; q95 {f(ex['q95'])}") | ||||
| 315 | + print(f"rang de la sélection du ch. 16 : {ex['rang_selection']} sous-ensembles sur {ex['n']} donnent moins ; part sous la prédiction hédonique {ex['part_sous_hed']:.3f}") | ||||
| 316 | + print(ex["par_n_retenus"].round(0).to_string()) | ||||
| 317 | + print("\n=== Coût (hypothèses : α = %.2f, vie = %d ans, âge effectif = %d) ===" % (co["alpha"], co["vie"], co["age_eff"])) | ||||
| 318 | + print(f"C_N {f(co['CN'])} ; V_L {f(co['V_L'])} ; D âge-vie {f(co['D'])} ({co['taux_D']:.3f}) ; contribution bâtiment {f(co['contribution_batiment'])} ; valeur {f(co['valeur'])}") | ||||
| 319 | + print(f"C_N + V_L = {f(co['cout_neuf_plus_terrain'])} ; extraction du marché à la prédiction hédonique : D = {f(co['extraction_hed']['depreciation'])} (taux {co['extraction_hed']['taux']:.3f}) ; à la comparaison : D = {f(co['extraction_comp']['depreciation'])} (taux {co['extraction_comp']['taux']:.3f})") | ||||
| 320 | + print(f"terrain implicite pour rejoindre la comparaison : {f(co['V_L_pour_comp'])} ; le modèle : {f(co['V_L_pour_hed'])}") | ||||
| 321 | + print(f"grille α × vie : min {f(co['min_grille'])}, max {f(co['max_grille'])}, é.-t. {f(co['sd_grille'])} ; âge effectif 20/24/28 : {[f(x) for x in co['age_effectif_variantes'].values()]}") | ||||
| 322 | + print(co["grille"].pivot(index="alpha", columns="vie", values="valeur").round(0).to_string()) | ||||
| 323 | + print("\n=== Combinaison ===") | ||||
| 324 | + print(f"indications : {[f(x) for x in cb['V']]} ; écarts-types : {[f(x) for x in cb['s']]} (hédonique : boot {f(cb['sd_pred_boot'])} + spécification {f(cb['sd_spec_hed'])}) ; ρ = {cb['rho']:.3f}") | ||||
| 325 | + print(cb["tableau"].round(3).to_string(index=False)) | ||||
| 326 | + print(f"poids optimal de la comparaison à deux indications selon ρ : { {round(k,3): round(v,3) for k, v in cb['w_opt_deux'].items()} }") | ||||
| 327 | + q = cb["q"] | ||||
| 328 | + print(f"conclusion raisonnée {f(cb['V_raisonnee'])} → arrondie {f(cb['conclusion'])} ; bootstrap de la combinaison : q2.5 {f(q['q025'])} q5 {f(q['q05'])} q50 {f(q['q50'])} q95 {f(q['q95'])} q97.5 {f(q['q975'])} ; fourchette 90 % arrondie {f(cb['fourchette90'][0])}–{f(cb['fourchette90'][1])}") | ||||
| 329 | + print(f"écart conclusion / comparaison {cb['ecart_conclusion_comp']:.4f} ; / hédonique {cb['ecart_conclusion_hed']:.4f}") | ||||
| 330 | + print("\n=== Loi de génération ===") | ||||
| 331 | + print(f"c_hat {vt['c_hat']:.4f} (e.-t. {vt['se_c']:.4f}, σ_e {vt['sigma_e']:.4f}) ; V_vraie {f(vt['V_true'])} [{f(vt['V_true_bas'])} ; {f(vt['V_true_haut'])}] ; écart comparaison {vt['ecart_comp']:.4f} ; hédonique {vt['ecart_hed']:.4f} ; conclusion {cb['conclusion']/vt['V_true']-1:.4f}") | ||||
| 332 | + print("\n=== Exercices ===") | ||||
| 333 | + for k, v in r["exercices"].items(): | ||||
| 334 | + print(k, {kk: (round(vv, 4) if isinstance(vv, float) else vv) for kk, vv in v.items()} if isinstance(v, dict) else v) | ||||
| 335 | + | ||||
| 336 | + | ||||
| 337 | +if __name__ == "__main__": | ||||
| 338 | + tout(verbose=True) | ||||
modified
analysis/python/cases/ch33_six_logements.py
+2 −2
@@ -170,7 +170,7 @@ def taux_predit(reg: dict, rmr: str, etat: int, n: int, age: float, inond: int = | |||||
| 170 | return float(np.exp(x @ reg["beta"]) * (reg["duan"] if duan else 1.0)) | 170 | return float(np.exp(x @ reg["beta"]) * (reg["duan"] if duan else 1.0)) | ||
| 171 | 171 | ||||
| 172 | 172 | ||||
| 173 | −def p45(som: dict, et: dict, amortissement_mois: int = 300) -> dict: | 173 | +def p45(som: dict, et: dict, amortissement_mois: int = 480) -> dict: | ||
| 174 | pf = som["portefeuille"]; row = pf.set_index("id_immeuble").loc[ID_36] | 174 | pf = som["portefeuille"]; row = pf.set_index("id_immeuble").loc[ID_36] | ||
| 175 | reg = _regression_cas4(pf) | 175 | reg = _regression_cas4(pf) | ||
| 176 | rne = float(row["rne_2026"]); n = int(row["nb_logements"]); rmr = str(row["rmr"]); etat = int(row["etat_1a5"]); age = float(row["age"]) | 176 | rne = float(row["rne_2026"]); n = int(row["nb_logements"]); rmr = str(row["rmr"]); etat = int(row["etat_1a5"]); age = float(row["age"]) | ||
@@ -316,7 +316,7 @@ def imprimer(R: dict) -> None: | |||||
| 316 | print(f"Décomposition : Montréal 12 log. état 2 âge 72 → {_p(d['regression_montreal_12_log_etat2_age72'], 3)} ; effet taille {d['effet_taille_pb']:+.1f} pb ; effet RMR {d['effet_rmr_pb']:+.1f} pb") | 316 | print(f"Décomposition : Montréal 12 log. état 2 âge 72 → {_p(d['regression_montreal_12_log_etat2_age72'], 3)} ; effet taille {d['effet_taille_pb']:+.1f} pb ; effet RMR {d['effet_rmr_pb']:+.1f} pb") | ||
| 317 | print(f"Écart Montréal cas 3 vs régression : {_p(p['ecart_montreal_vs_sujet'], 1)} ; valeur/log. Gatineau cas 4 {_d(p['gatineau_valeur_par_logement'])}, Montréal {_d(p['montreal_valeur_par_logement'])}") | 317 | print(f"Écart Montréal cas 3 vs régression : {_p(p['ecart_montreal_vs_sujet'], 1)} ; valeur/log. Gatineau cas 4 {_d(p['gatineau_valeur_par_logement'])}, Montréal {_d(p['montreal_valeur_par_logement'])}") | ||
| 318 | f = p["financement"] | 318 | f = p["financement"] | ||
| 319 | − print(f"Dette {_d(f['dette'])} à {_p(f['taux_dette'])} (échéance {f['echeance']}) ; service (300 mois, hyp.) {_d(f['service_dette'])} ; RCD {f['rcd']:.2f} ; RPV dossier {_p(f['rpv_fichier'], 1)} ; RPV sur V régression {_p(f['rpv_regression'], 1)} ; constante {_p(f['constante'])}") | 319 | + print(f"Dette {_d(f['dette'])} à {_p(f['taux_dette'])} (échéance {f['echeance']}) ; service (480 mois, hyp. prêt assuré) {_d(f['service_dette'])} ; RCD {f['rcd']:.2f} ; RPV dossier {_p(f['rpv_fichier'], 1)} ; RPV sur V régression {_p(f['rpv_regression'], 1)} ; constante {_p(f['constante'])}") | ||
| 320 | reg = p["regression"]; print(f"Régression cas 4 : n = {reg['n']}, R² = {reg['r2']:.3f}, facteur de Duan {reg['duan']:.4f}") | 320 | reg = p["regression"]; print(f"Régression cas 4 : n = {reg['n']}, R² = {reg['r2']:.3f}, facteur de Duan {reg['duan']:.4f}") | ||
| 321 | s = R["sensibilite"] | 321 | s = R["sensibilite"] | ||
| 322 | print("\n=== Sensibilité P45 ===") | 322 | print("\n=== Sensibilité P45 ===") | ||
modified
analysis/python/figures/ch19_figures.py
+2 −2
@@ -67,12 +67,12 @@ def fig_gwr_coefficients(res): | |||||
| 67 | j = cols.index("dist_centre"); dist = b["Xr"]["dist_centre"].values | 67 | j = cols.index("dist_centre"); dist = b["Xr"]["dist_centre"].values | ||
| 68 | sect = v["secteur"].values | 68 | sect = v["secteur"].values | ||
| 69 | loc = g["beta"][:, 0] + g["beta"][:, j] * dist - np.median(g["beta"][sect == "Hull", 0]) | 69 | loc = g["beta"][:, 0] + g["beta"][:, j] * dist - np.median(g["beta"][sect == "Hull", 0]) | ||
| 70 | − panneaux = [("Effet de localisation local\n(écart à Hull, en log)", loc, palette.cmap_div(), -0.35, 0.35), | 70 | + panneaux = [("Effet de localisation local\n(écart à Hull, en log)", loc, palette.cmap_div(), -0.32, 0.32), | ||
| 71 | ("Coefficient local de ln(superficie)\n(élasticité)", g["beta"][:, cols.index("ln_S")], palette.cmap_seq(), None, None), | 71 | ("Coefficient local de ln(superficie)\n(élasticité)", g["beta"][:, cols.index("ln_S")], palette.cmap_seq(), None, None), | ||
| 72 | ("Coefficient local de l'âge\n(× 100, % par année)", 100 * g["beta"][:, cols.index("age")], palette.cmap_seq(), None, None)] | 72 | ("Coefficient local de l'âge\n(× 100, % par année)", 100 * g["beta"][:, cols.index("age")], palette.cmap_seq(), None, None)] | ||
| 73 | fig, axes = plt.subplots(1, 3, figsize=(LARGEUR, 2.75)) | 73 | fig, axes = plt.subplots(1, 3, figsize=(LARGEUR, 2.75)) | ||
| 74 | for ax, (titre, z, cmap, vmin, vmax) in zip(axes, panneaux): | 74 | for ax, (titre, z, cmap, vmin, vmax) in zip(axes, panneaux): | ||
| 75 | − sc = ax.scatter(xy[:, 0], xy[:, 1], c=z, cmap=cmap, vmin=vmin, vmax=vmax, s=6, lw=0) | 75 | + sc = ax.scatter(xy[:, 0], xy[:, 1], c=z, cmap=cmap, vmin=vmin, vmax=vmax, s=9, lw=0) | ||
| 76 | ax.scatter(cs[:, 0], cs[:, 1], marker="*", s=70, color=palette.ink, zorder=5) | 76 | ax.scatter(cs[:, 0], cs[:, 1], marker="*", s=70, color=palette.ink, zorder=5) | ||
| 77 | _axes_km(ax, xy); ax.set_title(titre, fontsize=7.5); ax.tick_params(labelsize=6.5); ax.set_xlabel("Est (km)", fontsize=7) | 77 | _axes_km(ax, xy); ax.set_title(titre, fontsize=7.5); ax.tick_params(labelsize=6.5); ax.set_xlabel("Est (km)", fontsize=7) | ||
| 78 | cb = fig.colorbar(sc, ax=ax, orientation="horizontal", fraction=0.06, pad=0.22, aspect=28); cb.ax.tick_params(labelsize=6.5) | 78 | cb = fig.colorbar(sc, ax=ax, orientation="horizontal", fraction=0.06, pad=0.22, aspect=28); cb.ax.tick_params(labelsize=6.5) | ||
modified
analysis/python/figures/ch25_figures.py
+2 −2
@@ -72,9 +72,9 @@ def fig_lotissement(S): | |||||
| 72 | for t, v in zip(yrs, cum): | 72 | for t, v in zip(yrs, cum): | ||
| 73 | a1.annotate(fmt_milliers(v / 1000), (t, v), xytext=(0, 6), textcoords="offset points", ha="center", fontsize=7, color=palette.ink) | 73 | a1.annotate(fmt_milliers(v / 1000), (t, v), xytext=(0, 6), textcoords="offset points", ha="center", fontsize=7, color=palette.ink) | ||
| 74 | a1.axhline(0, color=palette.ink2, lw=0.6) | 74 | a1.axhline(0, color=palette.ink2, lw=0.6) | ||
| 75 | − a1.set_xticks(yrs); a1.set_xticklabels([str(t) for t in yrs]); a1.set_xlabel("Année (flux de fin d'année)"); a1.set_ylim(-1_250_000, 1_450_000); a1.yaxis.set_major_formatter(plt.FuncFormatter(lambda x, p_: fmt_milliers(x / 1000))) | 75 | + a1.set_xticks(yrs); a1.set_xticklabels([str(t) for t in yrs]); a1.set_xlabel("Année (flux de fin d'année)"); a1.set_ylim(-1_250_000, 2_300_000); a1.yaxis.set_major_formatter(plt.FuncFormatter(lambda x, p_: fmt_milliers(x / 1000))) | ||
| 76 | a1.set_ylabel("Milliers de dollars"); a1.set_title("(a) Flux du lotissement de 12 lots", loc="left", fontsize=9) | 76 | a1.set_ylabel("Milliers de dollars"); a1.set_title("(a) Flux du lotissement de 12 lots", loc="left", fontsize=9) | ||
| 77 | − a1.legend(fontsize=6.5, loc="lower left", handlelength=1.2) | 77 | + a1.legend(fontsize=6.5, loc="upper left", handlelength=1.2) | ||
| 78 | sl = cas.sensibilite_lotissement(m); base = sl["base"] | 78 | sl = cas.sensibilite_lotissement(m); base = sl["base"] | ||
| 79 | items = [("Absorption\n2 → 6 lots/an", sl["absorption"][2], sl["absorption"][6]), | 79 | items = [("Absorption\n2 → 6 lots/an", sl["absorption"][2], sl["absorption"][6]), | ||
| 80 | ("Prix des lots\n−10 % → +10 %", sl["prix"][-0.10], sl["prix"][0.10]), | 80 | ("Prix des lots\n−10 % → +10 %", sl["prix"][-0.10], sl["prix"][0.10]), | ||
modified
analysis/python/figures/ch28_figures.py
+30 −25
@@ -22,9 +22,9 @@ NOTE = "DONNÉES SYNTHÉTIQUES" | |||||
| 22 | 22 | ||||
| 23 | def fig_cascade(res): | 23 | def fig_cascade(res): | ||
| 24 | b = res["base"]; cl = res["classement"] | 24 | b = res["base"]; cl = res["classement"] | ||
| 25 | − etapes = [("Revenu brut\npotentiel", b["rbp_contrat"], "total"), ("Inoccupation\net pertes", -b["vacance_pertes"], "neg"), ("Autres\nrevenus", b["autres_revenus"], "pos"), | 25 | + etapes = [("RBP\n(baux)", b["rbp_contrat"], "total"), ("Inocc.\net pertes", -b["vacance_pertes"], "neg"), ("Autres\nrevenus", b["autres_revenus"], "pos"), | ||
| 26 | − ("Revenu brut\neffectif", b["rbe"], "total"), ("Dépenses\nfixes", -cl["fixes"], "neg"), ("Dépenses\nvariables", -cl["variables_hors_gestion"], "neg"), | 26 | + ("RBE", b["rbe"], "total"), ("Dépenses\nfixes", -cl["fixes"], "neg"), ("Dépenses\nvariables", -cl["variables_hors_gestion"], "neg"), | ||
| 27 | − ("Gestion\nimputée", -cl["gestion"], "neg"), ("Réserve de\nremplacement", -cl["reserve"], "neg"), ("Revenu net\nd'exploitation", b["rne"], "total")] | 27 | + ("Gestion\nimputée", -cl["gestion"], "neg"), ("Réserve", -cl["reserve"], "neg"), ("RNE", b["rne"], "total")] | ||
| 28 | fig, ax = plt.subplots(figsize=(LARGEUR, 3.3)) | 28 | fig, ax = plt.subplots(figsize=(LARGEUR, 3.3)) | ||
| 29 | cum = 0.0 | 29 | cum = 0.0 | ||
| 30 | for i, (nom, v, k) in enumerate(etapes): | 30 | for i, (nom, v, k) in enumerate(etapes): | ||
@@ -36,7 +36,7 @@ def fig_cascade(res): | |||||
| 36 | ax.text(i, top + 2500, fmt_dollars(abs(v)) if k != "total" else fmt_dollars(v), ha="center", va="bottom", fontsize=7.2, color=palette.ink) | 36 | ax.text(i, top + 2500, fmt_dollars(abs(v)) if k != "total" else fmt_dollars(v), ha="center", va="bottom", fontsize=7.2, color=palette.ink) | ||
| 37 | if i < len(etapes) - 1: | 37 | if i < len(etapes) - 1: | ||
| 38 | ax.plot([i + 0.35, i + 0.65], [cum, cum], color=palette.ink2, lw=0.6, ls=":") | 38 | ax.plot([i + 0.35, i + 0.65], [cum, cum], color=palette.ink2, lw=0.6, ls=":") | ||
| 39 | − ax.set_xticks(range(len(etapes))); ax.set_xticklabels([e[0] for e in etapes], fontsize=7.2) | 39 | + ax.set_xticks(range(len(etapes))); ax.set_xticklabels([e[0] for e in etapes], fontsize=7.4) | ||
| 40 | ax.yaxis.set_major_formatter(kdol); ax.set_ylabel("Dollars par année (première année)"); ax.set_ylim(0, 195000); ax.grid(axis="x", visible=False) | 40 | ax.yaxis.set_major_formatter(kdol); ax.set_ylabel("Dollars par année (première année)"); ax.set_ylim(0, 195000); ax.grid(axis="x", visible=False) | ||
| 41 | ax.set_title("Cas 3 : du revenu brut potentiel au revenu net d'exploitation normalisé", loc="left") | 41 | ax.set_title("Cas 3 : du revenu brut potentiel au revenu net d'exploitation normalisé", loc="left") | ||
| 42 | ax.text(0.99, -0.28, NOTE, transform=ax.transAxes, ha="right", va="bottom", fontsize=7, color=palette.ink2) | 42 | ax.text(0.99, -0.28, NOTE, transform=ax.transAxes, ha="right", va="bottom", fontsize=7, color=palette.ink2) | ||
@@ -60,27 +60,32 @@ def fig_structure(res): | |||||
| 60 | 60 | ||||
| 61 | 61 | ||||
| 62 | def fig_evolution(res): | 62 | def fig_evolution(res): | ||
| 63 | − dep = res["dep"].copy(); dep["groupe"] = dep["poste"].map(GROUPES) | 63 | + dep = res["dep"].copy() | ||
| 64 | − g = dep.groupby(["groupe", "annee"])["montant"].sum().unstack("annee").reindex(ORDRE_GROUPES).dropna(how="all") | 64 | + REG = {"Taxes foncières": "Taxes foncières", "Assurances": "Assurances", "Énergie des aires communes": "Énergie des aires communes", | ||
| 65 | − g = g[g[2023] > 0] | 65 | + "Entretien et réparations": "Autres postes variables", "Conciergerie et services": "Autres postes variables", "Honoraires et publicité": "Autres postes variables", | ||
| 66 | − det = res["detail"].assign(groupe=res["detail"]["poste"].map(GROUPES)).groupby("groupe")["normalise"].sum() | 66 | + "Réserve de remplacement": "Réserve de remplacement"} | ||
| 67 | − fig, axes = plt.subplots(1, 2, figsize=(LARGEUR, 3.2), gridspec_kw={"width_ratios": [1.15, 1]}) | 67 | + ORDRE = ["Taxes foncières", "Assurances", "Énergie des aires communes", "Autres postes variables", "Réserve de remplacement"] | ||
| 68 | + dep["groupe"] = dep["poste"].map(GROUPES).map(REG) | ||||
| 69 | + g = dep.groupby(["groupe", "annee"])["montant"].sum().unstack("annee").reindex(ORDRE) | ||||
| 70 | + det = res["detail"].assign(groupe=res["detail"]["poste"].map(GROUPES).map(lambda x: REG.get(x, "Gestion imputée"))).groupby("groupe")["normalise"].sum() | ||||
| 71 | + fig, axes = plt.subplots(1, 2, figsize=(LARGEUR, 3.4), gridspec_kw={"width_ratios": [1.1, 1]}) | ||||
| 68 | ax = axes[0] | 72 | ax = axes[0] | ||
| 69 | for i, (grp, r) in enumerate(g.iterrows()): | 73 | for i, (grp, r) in enumerate(g.iterrows()): | ||
| 70 | − idx = r / r[2023] * 100 | 74 | + ax.plot([2023, 2024, 2025], (r / r[2023] * 100).values, marker="o", color=palette.cat[i], lw=1.4, ms=3.5, label=grp) | ||
| 71 | − ax.plot([2023, 2024, 2025], idx.values, marker="o", color=palette.cat[i % 6], lw=1.4, ms=3.5, ls="-" if i < 6 else "--") | 75 | + tot = res["historique"].loc["Total", [2023, 2024, 2025]] | ||
| 72 | − ax.text(2025.07, idx[2025], grp, fontsize=6.8, va="center", color=palette.ink) | 76 | + ax.plot([2023, 2024, 2025], (tot / tot[2023] * 100).values, color=palette.ink, lw=2.2, marker="s", ms=4, label="Total déclaré") | ||
| 73 | − tot = res["historique"].loc["Total", [2023, 2024, 2025]]; ax.plot([2023, 2024, 2025], (tot / tot[2023] * 100).values, color=palette.ink, lw=2.2, marker="s", ms=4) | 77 | + ax.set_xticks([2023, 2024, 2025]); ax.set_xlim(2022.8, 2025.2); ax.set_ylabel("Indice (2023 = 100)") | ||
| 74 | − ax.text(2025.07, tot[2025] / tot[2023] * 100, "Total", fontsize=7.2, va="center", fontweight="bold") | 78 | + ax.set_title("Historique déclaré : indice par groupe", loc="left", fontsize=8.5) | ||
| 75 | − ax.set_xticks([2023, 2024, 2025]); ax.set_xlim(2022.8, 2026.1); ax.set_ylabel("Indice (2023 = 100)"); ax.set_title("Historique déclaré, indice par groupe", loc="left", fontsize=8.5) | 79 | + ax.legend(loc="upper center", bbox_to_anchor=(0.5, -0.17), ncol=2, fontsize=6.8, handlelength=1.6, columnspacing=1.0) | ||
| 76 | ax = axes[1] | 80 | ax = axes[1] | ||
| 77 | − grp_order = [x for x in ORDRE_GROUPES if x in g.index or x in det.index] | 81 | + ordre_d = ORDRE + ["Gestion imputée"] | ||
| 78 | − h25 = pd.Series({k: g.loc[k, 2025] if k in g.index else 0.0 for k in grp_order}); hn = det.reindex(grp_order).fillna(0.0) | 82 | + h25 = pd.Series({k: g.loc[k, 2025] if k in g.index else 0.0 for k in ordre_d}); hn = det.reindex(ordre_d).fillna(0.0) | ||
| 79 | − y = np.arange(len(grp_order)); w = 0.38 | 83 | + y = np.arange(len(ordre_d)); w = 0.38 | ||
| 80 | ax.barh(y + w / 2, h25.values, height=w, color=palette.cat[4], label="Déclaré 2025") | 84 | ax.barh(y + w / 2, h25.values, height=w, color=palette.cat[4], label="Déclaré 2025") | ||
| 81 | ax.barh(y - w / 2, hn.values, height=w, color=palette.cat[0], label="Normalisé (première année)") | 85 | ax.barh(y - w / 2, hn.values, height=w, color=palette.cat[0], label="Normalisé (première année)") | ||
| 82 | − ax.set_yticks(y); ax.set_yticklabels(grp_order, fontsize=7); ax.invert_yaxis(); ax.xaxis.set_major_formatter(kdol); ax.grid(axis="y", visible=False) | 86 | + for yy, v in zip(y - w / 2, hn.values): ax.text(v + 400, yy, fmt_dollars(v), va="center", fontsize=6.5) | ||
| 83 | − ax.legend(loc="lower right", fontsize=7); ax.set_title("2025 déclaré et montant normalisé", loc="left", fontsize=8.5) | 87 | + ax.set_yticks(y); ax.set_yticklabels(ordre_d, fontsize=7); ax.invert_yaxis(); ax.xaxis.set_major_formatter(kdol); ax.grid(axis="y", visible=False); ax.set_xlim(0, 48000) | ||
| 88 | + ax.legend(loc="upper center", bbox_to_anchor=(0.5, -0.17), ncol=1, fontsize=6.8); ax.set_title("2025 déclaré et montant normalisé", loc="left", fontsize=8.5) | ||||
| 84 | fig.text(0.99, -0.02, NOTE, ha="right", va="bottom", fontsize=7, color=palette.ink2) | 89 | fig.text(0.99, -0.02, NOTE, ha="right", va="bottom", fontsize=7, color=palette.ink2) | ||
| 85 | fig.tight_layout(w_pad=1.5) | 90 | fig.tight_layout(w_pad=1.5) | ||
| 86 | return savefig(fig, "ch28/ch28-fig-evolution.pdf") | 91 | return savefig(fig, "ch28/ch28-fig-evolution.pdf") | ||
@@ -107,24 +112,24 @@ def fig_ratio_loyer(res): | |||||
| 107 | 112 | ||||
| 108 | def fig_sensibilite(res): | 113 | def fig_sensibilite(res): | ||
| 109 | s = res["sensibilites"]; noi0 = res["base"]["rne"] | 114 | s = res["sensibilites"]; noi0 = res["base"]["rne"] | ||
| 110 | − fig, axes = plt.subplots(1, 3, figsize=(LARGEUR, 2.9), sharey=True) | 115 | + fig, axes = plt.subplots(1, 3, figsize=(LARGEUR, 3.0), sharey=True) | ||
| 111 | # réserve | 116 | # réserve | ||
| 112 | ax = axes[0]; r = s["reserve"] | 117 | ax = axes[0]; r = s["reserve"] | ||
| 113 | ax.plot(r["reserve_par_logement"], r["rne"], color=palette.cat[0], marker="o", ms=3.5) | 118 | ax.plot(r["reserve_par_logement"], r["rne"], color=palette.cat[0], marker="o", ms=3.5) | ||
| 114 | − ax.axvline(675.25, color=palette.ink2, lw=0.7, ls=":"); ax.set_xlabel("Réserve ($ par logement par an)"); ax.set_title("Réserve de remplacement", loc="left", fontsize=8.5) | 119 | + ax.axvline(675.25, color=palette.ink2, lw=0.7, ls=":"); ax.set_xlabel("Réserve (\\$/logement/an)"); ax.set_title("Réserve de remplacement", loc="left", fontsize=8.5) | ||
| 115 | ax.text(690, noi0 + 300, "675 $ (dossier)", fontsize=7) | 120 | ax.text(690, noi0 + 300, "675 $ (dossier)", fontsize=7) | ||
| 116 | # taxes : taux continu | 121 | # taxes : taux continu | ||
| 117 | ax = axes[1]; taux = np.linspace(0.0040, 0.0080, 50); role = res["hyp"]["valeur_role_2026"]; taxe0 = role * res["hyp"]["taux_taxe_fonciere"] | 122 | ax = axes[1]; taux = np.linspace(0.0040, 0.0080, 50); role = res["hyp"]["valeur_role_2026"]; taxe0 = role * res["hyp"]["taux_taxe_fonciere"] | ||
| 118 | ax.plot(taux * 100, noi0 - (role * taux - taxe0), color=palette.cat[1]) | 123 | ax.plot(taux * 100, noi0 - (role * taux - taxe0), color=palette.cat[1]) | ||
| 119 | for _, row in s["taxe"].iterrows(): | 124 | for _, row in s["taxe"].iterrows(): | ||
| 120 | if row["taux_par_100"] <= 0.80: ax.scatter([row["taux_par_100"]], [row["rne"]], color=palette.cat[1], s=22, zorder=4) | 125 | if row["taux_par_100"] <= 0.80: ax.scatter([row["taux_par_100"]], [row["rne"]], color=palette.cat[1], s=22, zorder=4) | ||
| 121 | − ax.axvline(0.4631, color=palette.ink2, lw=0.7, ls=":"); ax.set_xlabel("Taxe municipale ($ par 100 $ du rôle)"); ax.set_title("Taux de taxe (rôle inchangé)", loc="left", fontsize=8.5) | 126 | + ax.axvline(0.4631, color=palette.ink2, lw=0.7, ls=":"); ax.set_xlabel("Taxe (\\$ par 100 \\$ du rôle)"); ax.set_title("Taux de taxe (rôle inchangé)", loc="left", fontsize=8.5) | ||
| 122 | ax.xaxis.set_major_formatter(FuncFormatter(lambda x, p: f"{x:.2f}".replace(".", ","))) | 127 | ax.xaxis.set_major_formatter(FuncFormatter(lambda x, p: f"{x:.2f}".replace(".", ","))) | ||
| 123 | − ax.text(0.48, noi0 + 300, "Montréal 0,4631", fontsize=7); ax.text(0.70, noi0 - 6200, "Gatineau 6+\n0,6964", fontsize=6.8); ax.text(0.715, noi0 - 9500, "Québec 6+\n0,7697", fontsize=6.8, ha="left") | 128 | + ax.text(0.475, noi0 + 300, "Montréal 0,4631", fontsize=7); ax.text(0.585, noi0 - 4300, "Gatineau 6+ 0,6964", fontsize=6.8); ax.text(0.585, noi0 - 7600, "Québec 6+ 0,7697", fontsize=6.8) | ||
| 124 | # gestion | 129 | # gestion | ||
| 125 | ax = axes[2]; g = s["gestion"] | 130 | ax = axes[2]; g = s["gestion"] | ||
| 126 | ax.plot(g["gestion_pct"], g["rne"], color=palette.cat[2], marker="o", ms=3.5) | 131 | ax.plot(g["gestion_pct"], g["rne"], color=palette.cat[2], marker="o", ms=3.5) | ||
| 127 | − ax.axvline(0.04, color=palette.ink2, lw=0.7, ls=":"); ax.set_xlabel("Gestion imputée (% du RBE)"); ax.set_title("Taux de gestion", loc="left", fontsize=8.5) | 132 | + ax.axvline(0.04, color=palette.ink2, lw=0.7, ls=":"); ax.set_xlabel("Gestion (% du RBE)"); ax.set_title("Taux de gestion", loc="left", fontsize=8.5) | ||
| 128 | ax.xaxis.set_major_formatter(pct0); ax.text(0.045, noi0 + 300, "4 % (dossier)", fontsize=7) | 133 | ax.xaxis.set_major_formatter(pct0); ax.text(0.045, noi0 + 300, "4 % (dossier)", fontsize=7) | ||
| 129 | for ax in axes: | 134 | for ax in axes: | ||
| 130 | ax.axhline(noi0, color=palette.ink2, lw=0.7, ls=":"); ax.yaxis.set_major_formatter(kdol) | 135 | ax.axhline(noi0, color=palette.ink2, lw=0.7, ls=":"); ax.yaxis.set_major_formatter(kdol) | ||
added
analysis/python/figures/ch33_figures.py
+129 −0
@@ -0,0 +1,129 @@ | |||||
| 1 | +#!/usr/bin/env python3 | ||||
| 2 | +"""Chapitre 33 — figures (4) : (1) SCHL, île de Montréal, loyers et inoccupation par taille d'immeuble et par année de | ||||
| 3 | +construction (DONNÉES RÉELLES, Enquête sur les logements locatifs d'octobre 2025) ; (2) cas 4 : valeur par logement et | ||||
| 4 | +taux global par RMR ; (3) taux global selon la taille : comparables du cas 3 et immeubles du cas 4 ; (4) sensibilité | ||||
| 5 | +de la valeur par logement de l'immeuble P45 (36 logements) à la RMR et à l'état (régression du cas 4). | ||||
| 6 | +Idempotent ; écrit dans assets/figures/ch33/ch33-fig-<slug>.pdf. | ||||
| 7 | +Usage (racine) : PYTHONPATH=analysis/python python3 analysis/python/figures/ch33_figures.py""" | ||||
| 8 | +from __future__ import annotations | ||||
| 9 | +import sys, pathlib | ||||
| 10 | +import numpy as np, pandas as pd | ||||
| 11 | +import matplotlib.pyplot as plt | ||||
| 12 | +from matplotlib.ticker import FuncFormatter | ||||
| 13 | +sys.path.insert(0, str(pathlib.Path(__file__).resolve().parents[1])) | ||||
| 14 | +from traite.style import setup, palette, savefig, LARGEUR, fmt_milliers | ||||
| 15 | +sys.path.insert(0, str(pathlib.Path(__file__).resolve().parents[1] / "cases")) | ||||
| 16 | +import ch33_six_logements as ch | ||||
| 17 | + | ||||
| 18 | +ROOT = pathlib.Path(__file__).resolve().parents[3] | ||||
| 19 | +pct1 = FuncFormatter(lambda x, p: f"{x:.1f}".replace(".", ",") + " %") | ||||
| 20 | +pct2 = FuncFormatter(lambda x, p: f"{x*100:.1f}".replace(".", ",") + " %") | ||||
| 21 | +kdol = FuncFormatter(lambda x, p: f"{x/1000:.0f} k$") | ||||
| 22 | +dol = FuncFormatter(lambda x, p: fmt_milliers(x) + " $") | ||||
| 23 | + | ||||
| 24 | + | ||||
| 25 | +def fig_schl(R): | ||||
| 26 | + t = R["schl"]["taille"]; a = R["schl"]["annee"] | ||||
| 27 | + t = t[t["categorie"] != "Tous les immeubles"].copy(); a = a[a["categorie"] != "Tous les immeubles"].copy() | ||||
| 28 | + t["etiquette"] = t["categorie"].str.replace(" unités", "").str.replace(" et +", " et plus") | ||||
| 29 | + a["etiquette"] = a["categorie"].map({"Avant 1940": "< 1940", "1940 à 1959": "1940-59", "1960 à 1974": "1960-74", "1975 à 1989": "1975-89", | ||||
| 30 | + "1990 à 2004": "1990-2004", "2005 à 2014": "2005-14", "2015 ou après": "2015 +"}) | ||||
| 31 | + fig, axes = plt.subplots(2, 2, figsize=(LARGEUR, 5.4), gridspec_kw={"hspace": 0.75, "wspace": 0.35}) | ||||
| 32 | + for (ax_l, ax_i), df, titre in ((axes[0], t, "taille d'immeuble"), (axes[1], a, "année de construction")): | ||||
| 33 | + x = np.arange(len(df)); w = 0.38 | ||||
| 34 | + ax_l.bar(x - w / 2, df["loyer_tous"], w, color=palette.cat[0], label="tous les logements") | ||||
| 35 | + ax_l.bar(x + w / 2, df["loyer_2ch"], w, color=palette.cat[1], label="2 chambres") | ||||
| 36 | + for xi, v in zip(x - w / 2, df["loyer_tous"]): ax_l.text(xi, v + 25, fmt_milliers(v), ha="center", va="bottom", fontsize=6.5, color=palette.ink) | ||||
| 37 | + ax_l.set_xticks(x); ax_l.set_xticklabels(df["etiquette"], fontsize=7, rotation=30, ha="right") | ||||
| 38 | + ax_l.yaxis.set_major_formatter(dol); ax_l.set_ylim(0, 2450); ax_l.set_title(f"Loyer moyen selon la {titre}", loc="left", fontsize=8.5) | ||||
| 39 | + ax_i.bar(x, df["inoccupation_tous"], 0.6, color=palette.cat[2]) | ||||
| 40 | + for xi, v in zip(x, df["inoccupation_tous"]): | ||||
| 41 | + if not np.isnan(v): ax_i.text(xi, v + 0.08, f"{v:.1f}".replace(".", ","), ha="center", va="bottom", fontsize=7, color=palette.ink) | ||||
| 42 | + else: ax_i.text(xi, 0.15, "n. d.", ha="center", va="bottom", fontsize=7, color=palette.ink2) | ||||
| 43 | + ax_i.set_xticks(x); ax_i.set_xticklabels(df["etiquette"], fontsize=7, rotation=30, ha="right") | ||||
| 44 | + ax_i.yaxis.set_major_formatter(pct1); ax_i.set_ylim(0, 6.6); ax_i.set_title(f"Inoccupation selon la {titre}", loc="left", fontsize=8.5) | ||||
| 45 | + axes[0][0].legend(loc="upper left", fontsize=6.5, ncol=1) | ||||
| 46 | + fig.text(0.99, 0.005, "Source : SCHL, Enquête sur les logements locatifs, octobre 2025, île de Montréal (zones 1-18) ; « n. d. » : donnée supprimée par la SCHL (fiabilité insuffisante)", | ||||
| 47 | + ha="right", va="bottom", fontsize=6.5, color=palette.ink2) | ||||
| 48 | + return savefig(fig, "ch33/ch33-fig-schl-typologie.pdf") | ||||
| 49 | + | ||||
| 50 | + | ||||
| 51 | +def fig_rmr(R): | ||||
| 52 | + g = R["sommaire"]["par_rmr"]; pf = R["sommaire"]["portefeuille"] | ||||
| 53 | + rmrs = list(g.index); x = np.arange(len(rmrs)) | ||||
| 54 | + fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(LARGEUR, 3.3), gridspec_kw={"wspace": 0.38}) | ||||
| 55 | + ax1.bar(x, g["valeur_par_logement"], 0.6, color=palette.cat[0], alpha=0.85, label="valeur agrégée / logements (RMR)") | ||||
| 56 | + rng = np.random.default_rng(20261031) | ||||
| 57 | + for i, r in enumerate(rmrs): | ||||
| 58 | + s = pf[pf["rmr"] == r] | ||||
| 59 | + ax1.scatter(i + rng.uniform(-0.18, 0.18, len(s)), s["valeur_par_logement"], s=np.sqrt(s["nb_logements"]) * 4, color=palette.ink, alpha=0.55, zorder=3, | ||||
| 60 | + label="immeuble (aire proportionnelle au nombre de logements)" if i == 0 else None) | ||||
| 61 | + ax1.text(i, 9000, fmt_milliers(round(g.loc[r, "valeur_par_logement"], -3)), ha="center", va="bottom", fontsize=6.8, color="white", rotation=90) | ||||
| 62 | + ax1.set_xticks(x); ax1.set_xticklabels(rmrs, rotation=25, ha="right", fontsize=7.5); ax1.yaxis.set_major_formatter(kdol); ax1.set_ylim(0, 320_000) | ||||
| 63 | + ax1.set_title("Valeur 2026 par logement", loc="left") | ||||
| 64 | + ax2.errorbar(x, g["taux_median"], yerr=[g["taux_median"] - g["taux_min"], g["taux_max"] - g["taux_median"]], fmt="o", color=palette.cat[1], ecolor=palette.ink2, capsize=3, label="médiane (étendue min–max)") | ||||
| 65 | + ax2.scatter(x, g["taux_pondere"], marker="_", s=260, color=palette.cat[0], linewidths=2.2, label="taux pondéré (RNE / valeur)", zorder=4) | ||||
| 66 | + ax2.axhline(R["effet_taille"]["cas3_mediane"], color=palette.ink, linestyle=":", linewidth=1, label="cas 3 : médiane des 40 ventes (Montréal)") | ||||
| 67 | + for i, r in enumerate(rmrs): ax2.text(i + 0.12, g.loc[r, "taux_pondere"], f"{g.loc[r, 'taux_pondere']*100:.2f}".replace(".", ","), fontsize=7, va="center") | ||||
| 68 | + ax2.set_xticks(x); ax2.set_xticklabels(rmrs, rotation=25, ha="right", fontsize=7.5); ax2.yaxis.set_major_formatter(pct2); ax2.set_ylim(0.035, 0.075) | ||||
| 69 | + ax2.set_title("Taux global par RMR", loc="left") | ||||
| 70 | + h1, l1 = ax1.get_legend_handles_labels(); h2, l2 = ax2.get_legend_handles_labels() | ||||
| 71 | + fig.legend(h1 + h2, l1 + l2, loc="lower center", bbox_to_anchor=(0.5, -0.16), ncol=2, fontsize=7) | ||||
| 72 | + fig.text(0.99, -0.22, "DONNÉES SYNTHÉTIQUES — cas 4 (48 immeubles, 6 RMR)", ha="right", va="bottom", fontsize=7, color=palette.ink2) | ||||
| 73 | + return savefig(fig, "ch33/ch33-fig-rmr.pdf") | ||||
| 74 | + | ||||
| 75 | + | ||||
| 76 | +def fig_taux_taille(R): | ||||
| 77 | + et = R["effet_taille"]; c3 = et["cas3_comparables"]; pf = R["sommaire"]["portefeuille"]; p = R["p45"]; reg = p["regression"] | ||||
| 78 | + fig, ax = plt.subplots(figsize=(LARGEUR, 3.6)) | ||||
| 79 | + m = pf["rmr"] == "Montréal" | ||||
| 80 | + ax.scatter(c3["nb_logements"], c3["taux_global"], s=22, color=palette.cat[0], marker="o", alpha=0.8, label=f"cas 3 : {len(c3)} ventes, Montréal (2024-09 à 2026-08)", zorder=3) | ||||
| 81 | + ax.scatter(pf.loc[m, "nb_logements"], pf.loc[m, "taux_global"], s=30, color=palette.cat[1], marker="s", alpha=0.85, label=f"cas 4 : Montréal ({int(m.sum())} immeubles)", zorder=3) | ||||
| 82 | + ax.scatter(pf.loc[~m, "nb_logements"], pf.loc[~m, "taux_global"], s=30, color=palette.cat[2], marker="^", alpha=0.85, label=f"cas 4 : cinq autres RMR ({int((~m).sum())} immeubles)", zorder=3) | ||||
| 83 | + xs = np.linspace(6, 30, 50) | ||||
| 84 | + ax.plot(xs, et["cas3_constante"] + (et["cas3_pente_pb_par_logement"] / 1e4) * (xs - 12), color=palette.cat[0], linewidth=1.2, label="cas 3 : régression linéaire (état 3)") | ||||
| 85 | + xs4 = np.linspace(6, 72, 80) | ||||
| 86 | + ax.plot(xs4, [ch.taux_predit(reg, "Montréal", 3, k, 50) for k in xs4], color=palette.cat[1], linewidth=1.2, linestyle="--", label="cas 4 : régression semi-log, Montréal (état 3, 50 ans)") | ||||
| 87 | + ax.plot(xs4, [ch.taux_predit(reg, "Gatineau", 3, k, 50) for k in xs4], color=palette.cat[2], linewidth=1.2, linestyle="--", label="cas 4 : idem, Gatineau") | ||||
| 88 | + ax.scatter([12], [et["cas3_mediane"]], marker="*", s=140, color=palette.ink, zorder=5) | ||||
| 89 | + ax.annotate("sujet du cas 3 (12 log., médiane 4,415 %)", (12, et["cas3_mediane"]), xytext=(14, 0.0385), fontsize=7, arrowprops=dict(arrowstyle="-", color=palette.ink2, lw=0.7)) | ||||
| 90 | + ax.scatter([p["n"]], [p["taux"]["fichier"]], marker="D", s=60, facecolors="none", edgecolors=palette.ink, linewidths=1.3, zorder=5) | ||||
| 91 | + ax.annotate(f"{p['id']} : {p['n']} log., Gatineau, état {p['etat']}", (p["n"], p["taux"]["fichier"]), xytext=(40, 0.0455), fontsize=7, arrowprops=dict(arrowstyle="-", color=palette.ink2, lw=0.7)) | ||||
| 92 | + ax.set_xscale("log"); ax.set_xticks([6, 8, 12, 16, 24, 36, 48, 72]); ax.get_xaxis().set_major_formatter(FuncFormatter(lambda x, p: f"{x:.0f}")) | ||||
| 93 | + ax.xaxis.set_minor_formatter(FuncFormatter(lambda x, p: "")) | ||||
| 94 | + ax.yaxis.set_major_formatter(pct2); ax.set_xlabel("Nombre de logements (échelle logarithmique)"); ax.set_ylabel("Taux global (RNE / prix ou valeur)") | ||||
| 95 | + ax.set_title("Taux global selon la taille de l'immeuble : effet de taille modeste, effet de marché dominant", loc="left") | ||||
| 96 | + ax.legend(loc="upper center", bbox_to_anchor=(0.5, -0.2), ncol=2, fontsize=7) | ||||
| 97 | + ax.text(0.99, -0.46, "DONNÉES SYNTHÉTIQUES (cas 3 et cas 4)", transform=ax.transAxes, ha="right", va="bottom", fontsize=7, color=palette.ink2) | ||||
| 98 | + return savefig(fig, "ch33/ch33-fig-taux-taille.pdf") | ||||
| 99 | + | ||||
| 100 | + | ||||
| 101 | +def fig_sensibilite(R): | ||||
| 102 | + s = R["sensibilite"]; p = R["p45"] | ||||
| 103 | + G = s["grille_valeur_par_logement"]; T = s["grille_taux"] | ||||
| 104 | + fig, ax = plt.subplots(figsize=(LARGEUR, 3.4)) | ||||
| 105 | + im = ax.imshow(G.values / 1000, cmap=palette.cmap_seq(), aspect="auto", origin="lower") | ||||
| 106 | + ax.set_xticks(range(G.shape[1])); ax.set_xticklabels(G.columns, fontsize=7.5, rotation=20, ha="right") | ||||
| 107 | + ax.set_yticks(range(G.shape[0])); ax.set_yticklabels(G.index, fontsize=7.5) | ||||
| 108 | + seuil = np.percentile(G.values / 1000, 60) | ||||
| 109 | + for i in range(G.shape[0]): | ||||
| 110 | + for j in range(G.shape[1]): | ||||
| 111 | + v = G.values[i, j] / 1000; coul = "white" if v > seuil else palette.ink | ||||
| 112 | + ax.text(j, i, f"{v:.0f} k$\n{T.values[i, j]*100:.2f} %".replace(".", ","), ha="center", va="center", fontsize=6.8, color=coul) | ||||
| 113 | + j0 = list(G.columns).index(p["rmr"]); i0 = p["etat"] - 1 | ||||
| 114 | + ax.add_patch(plt.Rectangle((j0 - 0.5, i0 - 0.5), 1, 1, fill=False, edgecolor=palette.cat[1], linewidth=1.8)) | ||||
| 115 | + ax.grid(False); ax.set_xlabel("Région métropolitaine (RMR)"); ax.set_ylabel("État de l'immeuble (1 = mauvais, 5 = excellent)") | ||||
| 116 | + ax.set_title(f"P45 (36 logements, 72 ans) : valeur par logement et taux prédits selon la RMR et l'état ; cadre = sujet", loc="left") | ||||
| 117 | + cb = fig.colorbar(im, ax=ax, pad=0.02); cb.set_label("valeur par logement (k$)") | ||||
| 118 | + ax.text(0.99, -0.30, "DONNÉES SYNTHÉTIQUES — régression semi-log du cas 4 (48 immeubles), RNE de P45 constant", transform=ax.transAxes, ha="right", va="bottom", fontsize=7, color=palette.ink2) | ||||
| 119 | + return savefig(fig, "ch33/ch33-fig-p45-sensibilite.pdf") | ||||
| 120 | + | ||||
| 121 | + | ||||
| 122 | +def main(): | ||||
| 123 | + setup(); R = ch.calculer() | ||||
| 124 | + for f in (fig_schl, fig_rmr, fig_taux_taille, fig_sensibilite): | ||||
| 125 | + print("OK", f(R).relative_to(ROOT)) | ||||
| 126 | + | ||||
| 127 | + | ||||
| 128 | +if __name__ == "__main__": | ||||
| 129 | + main() | ||||
added
analysis/python/tests/test_ch13.py
+176 −0
@@ -0,0 +1,176 @@ | |||||
| 1 | +"""Tests du chapitre 13 — lecture des fichiers RÉELS de data/raw (StatCan 18-10-0289-01, 18-10-0205-01, 18-10-0004-01 ; | ||||
| 2 | +MAMH RFU 2026 et répertoire du rôle ; SCHL ELL octobre 2025), identités et valeurs citées dans le texte et les solutions. | ||||
| 3 | +Tolérances : valeurs d'indices exactes (lecture du CSV) ; pourcentages cités à 0,05 point ; montants des solutions à 1 $ ; | ||||
| 4 | +identités à 1e-9.""" | ||||
| 5 | +import sys, pathlib, math | ||||
| 6 | +import numpy as np, pytest | ||||
| 7 | +sys.path.insert(0, str(pathlib.Path(__file__).resolve().parents[1] / "cases")) | ||||
| 8 | +import ch13_sources as cas | ||||
| 9 | + | ||||
| 10 | + | ||||
| 11 | +@pytest.fixture(scope="module") | ||||
| 12 | +def ipcb(): | ||||
| 13 | + return cas.charger_ipcb() | ||||
| 14 | + | ||||
| 15 | + | ||||
| 16 | +@pytest.fixture(scope="module") | ||||
| 17 | +def schl(): | ||||
| 18 | + t = cas.schl_rmr() | ||||
| 19 | + return t, cas.tableau_schl(t) | ||||
| 20 | + | ||||
| 21 | + | ||||
| 22 | +class TestIPCB: | ||||
| 23 | + def test_structure(self, ipcb): | ||||
| 24 | + st = cas.structure_ipcb(ipcb) | ||||
| 25 | + assert st["lignes"] == 318954 and st["colonnes"] == 16 | ||||
| 26 | + assert st["n_geo"] == 25 and st["n_types"] == 16 and st["n_divisions"] == 24 | ||||
| 27 | + assert st["n_vecteurs"] == 8750 and st["produit_theorique"] == 9600 | ||||
| 28 | + assert st["periode_min"] == "1981-01" and st["periode_max"] == "2026-07" and st["n_periodes"] == 183 | ||||
| 29 | + assert st["unite"] == "Indice, 2023=100" and st["valeurs_manquantes"] == 0 | ||||
| 30 | + assert st["debuts_montreal"]["Bâtiments résidentiels [621]"] == "2017-01" | ||||
| 31 | + assert st["debuts_montreal"]["Tour d'habitations (cinq étages ou plus) [621111]"] == "1988-01" | ||||
| 32 | + assert st["debuts_montreal"]["Bâtiments non résidentiels [622]"] == "1981-01" | ||||
| 33 | + | ||||
| 34 | + def test_series_citees(self, ipcb): | ||||
| 35 | + r = cas.resume_ipcb(ipcb) | ||||
| 36 | + m, q = r["Montréal"], r["Québec"] | ||||
| 37 | + assert m["debut"] == "2017T1" and m["fin"] == "2026T3" and m["n"] == 39 | ||||
| 38 | + assert m["2017T1"] == 65.5 and m["2025T3"] == 108.5 and m["2026T3"] == 117.8 and m["2023T1"] == 99.9 | ||||
| 39 | + assert m["var_annuelle_pct"] == pytest.approx(8.57, abs=0.05) | ||||
| 40 | + assert m["facteur_2017T1_2026T3"] == pytest.approx(1.798, abs=5e-4) | ||||
| 41 | + assert m["facteur_2023T1_2026T3"] == pytest.approx(1.179, abs=5e-4) | ||||
| 42 | + assert q["debut"] == "2023T1" and q["n"] == 15 and q["2023T1"] == 98.8 and q["2026T3"] == 124.8 and q["2017T1"] is None | ||||
| 43 | + assert q["var_annuelle_pct"] == pytest.approx(9.19, abs=0.05) | ||||
| 44 | + assert q["facteur_2023T1_2026T3"] == pytest.approx(1.263, abs=5e-4) | ||||
| 45 | + | ||||
| 46 | + def test_vecteur_montreal(self, ipcb): | ||||
| 47 | + s = cas.serie_ipcb(ipcb, cas.GEO_MTL) | ||||
| 48 | + assert s["VECTEUR"].iloc[0] == "v1617911460" | ||||
| 49 | + assert cas.serie_ipcb(ipcb, cas.GEO_QC)["VECTEUR"].iloc[0] == "v1617911076" | ||||
| 50 | + | ||||
| 51 | + | ||||
| 52 | +class TestIndices: | ||||
| 53 | + def test_rebasage(self, ipcb): | ||||
| 54 | + t = cas.indices_compares(ipcb, ecrire=False); r = cas.resume_indices(t) | ||||
| 55 | + assert r["n_trimestres"] == 39 and t["trimestre"].iloc[0] == "2017T1" and t["trimestre"].iloc[-1] == "2026T3" | ||||
| 56 | + for c in ("ipcb_mtl_resid", "ipc_quebec", "ipln_mtl"): | ||||
| 57 | + assert t.loc[0, c + "_base2017"] == pytest.approx(100.0, abs=1e-9) | ||||
| 58 | + assert r["ipcb_2026T3_base2017"] == pytest.approx(179.8, abs=0.05) | ||||
| 59 | + assert r["ipln_2026T3_base2017"] == pytest.approx(159.0, abs=0.05) | ||||
| 60 | + assert r["ipc_2026T3_base2017"] == pytest.approx(132.2, abs=0.05) | ||||
| 61 | + # invariance du ratio d'indexation au rebasage (eq. 13.11) | ||||
| 62 | + assert t["ipcb_mtl_resid_base2017"].iloc[-1] / t["ipcb_mtl_resid_base2017"].iloc[0] == pytest.approx(t["ipcb_mtl_resid"].iloc[-1] / t["ipcb_mtl_resid"].iloc[0], rel=1e-12) | ||||
| 63 | + assert r["ipc_quebec_2026T3_moy"] == pytest.approx(167.2, abs=0.05) and r["ipln_mtl_2026T3_moy"] == pytest.approx(159.5, abs=0.05) | ||||
| 64 | + | ||||
| 65 | + def test_fichier_processed(self, ipcb): | ||||
| 66 | + t = cas.indices_compares(ipcb, ecrire=True) | ||||
| 67 | + assert (cas.PROCESSED / "ch13_indices.csv").exists() and len(t) == 39 | ||||
| 68 | + | ||||
| 69 | + | ||||
| 70 | +class TestDictionnaireEtRoles: | ||||
| 71 | + def test_dictionnaire(self): | ||||
| 72 | + d = cas.dictionnaire_role() | ||||
| 73 | + assert d["n_pages"] == 2 and d["n_codes_uniques"] == 62 and d["n_repetitifs"] == 24 | ||||
| 74 | + assert d["par_section"] == {1: 21, 2: 2, 3: 17, 4: 5, 5: 17} | ||||
| 75 | + assert all(d["champs_cles_presents"].values()) | ||||
| 76 | + assert d["date_document"] == "24 mars 2022" | ||||
| 77 | + | ||||
| 78 | + def test_index_roles(self): | ||||
| 79 | + ix = cas.index_roles() | ||||
| 80 | + assert ix["n_municipalites"] == 1134 and ix["colonnes"] == ["code géographique", "nom du territoire", "lien"] | ||||
| 81 | + assert ix["gatineau"][-1].endswith("RL81017_2026.xml") and ix["montreal"][-1].endswith("RL66023_2026.xml") and ix["quebec"][-1].endswith("RL23027_2026.xml") | ||||
| 82 | + | ||||
| 83 | + | ||||
| 84 | +class TestRFU: | ||||
| 85 | + def test_structure_et_villes(self): | ||||
| 86 | + rf = cas.rfu_2026() | ||||
| 87 | + assert rf["n_lignes"] == 1132 and rf["n_colonnes"] == 37 and rf["types_org"] == {"Municipalité locale": 1132} and rf["n_postes_decrits"] == 24 | ||||
| 88 | + v = rf["villes"] | ||||
| 89 | + assert v["Montréal"]["imposable_uniformise"] == pytest.approx(430.75e9, abs=0.005e9) | ||||
| 90 | + assert v["Québec"]["imposable_uniformise"] == pytest.approx(105.22e9, abs=0.005e9) | ||||
| 91 | + assert v["Gatineau"]["imposable_uniformise"] == pytest.approx(60.01e9, abs=0.005e9) | ||||
| 92 | + assert v["Montréal"]["facteur_redressement"] == 1.00 and v["Québec"]["facteur_redressement"] == 1.08 and v["Gatineau"]["facteur_redressement"] == 1.02 | ||||
| 93 | + for d in v.values(): # identité : somme des six postes = évaluation imposable uniformisée | ||||
| 94 | + assert abs(d["ecart_somme_vs_imposable"]) < 1.0 | ||||
| 95 | + assert sum(d["parts_pct"].values()) == pytest.approx(100.0, abs=1e-6) | ||||
| 96 | + assert v["Gatineau"]["parts_pct"]["Résidences d'un logement"] == pytest.approx(56.5, abs=0.05) | ||||
| 97 | + assert v["Montréal"]["parts_pct"]["Immeubles à logements et condominiums"] == pytest.approx(60.6, abs=0.05) | ||||
| 98 | + assert v["Québec"]["parts_pct"]["Résidences d'un logement"] == pytest.approx(40.2, abs=0.05) | ||||
| 99 | + assert v["Québec"]["parts_pct"]["Immeubles à logements et condominiums"] == pytest.approx(38.8, abs=0.05) | ||||
| 100 | + assert rf["total_rfu"] == pytest.approx(2077.9e9, abs=0.05e9) and rf["part_3_villes_rfu_pct"] == pytest.approx(31.1, abs=0.05) | ||||
| 101 | + | ||||
| 102 | + | ||||
| 103 | +class TestSCHL: | ||||
| 104 | + def test_tableau(self, schl): | ||||
| 105 | + t, ts = schl | ||||
| 106 | + assert t["n_onglets"] == 20 | ||||
| 107 | + attendu = { # inocc 2024, inocc 2025, loyer 2 ch. 2024, 2025, univers 2025, var. estimative 2 ch. | ||||
| 108 | + "Montréal": (2.1, 2.9, 1176, 1346, 667266, 7.2), "Québec": (0.9, 2.4, 1159, 1277, 118693, 6.1), | ||||
| 109 | + "Gatineau": (1.9, 3.8, 1353, 1460, 33553, 4.7), "Sherbrooke": (1.4, 2.7, 1002, 1062, 41949, 9.8), | ||||
| 110 | + "Trois-Rivières": (0.9, 2.7, 885, 1016, 22505, 6.6), "Saguenay": (1.6, 1.3, 882, 985, 16241, 10.9)} | ||||
| 111 | + for rmr, (i24, i25, l24, l25, u, ve) in attendu.items(): | ||||
| 112 | + r = ts.loc[rmr] | ||||
| 113 | + assert r["inocc_2024"] == i24 and r["inocc_2025"] == i25 and r["loyer_2ch_2024"] == l24 and r["loyer_2ch_2025"] == l25 | ||||
| 114 | + assert r["univers_2025"] == u and r["var_estim_2ch_pct"] == ve | ||||
| 115 | + assert r["var_brute_2ch_pct"] == pytest.approx((l25 / l24 - 1) * 100, rel=1e-12) | ||||
| 116 | + assert r["logements_vacants_implicites"] == pytest.approx(u * i25 / 100, rel=1e-12) | ||||
| 117 | + assert ts.loc["Montréal", "var_brute_2ch_pct"] == pytest.approx(14.5, abs=0.05) | ||||
| 118 | + assert ts.loc["Montréal", "logements_vacants_implicites"] == pytest.approx(19351, abs=0.5) | ||||
| 119 | + assert ts.loc["Saguenay", "logements_vacants_implicites"] == pytest.approx(211, abs=0.5) | ||||
| 120 | + assert ts.loc["Sherbrooke", "var_brute_2ch_pct"] < ts.loc["Sherbrooke", "var_estim_2ch_pct"] # seule RMR où l'effet de composition est négatif | ||||
| 121 | + assert ts.loc["Montréal", "inocc_q"] == "a" and ts.loc["Gatineau", "inocc_q"] == "c" and ts.loc["Trois-Rivières", "inocc_q"] == "b" | ||||
| 122 | + assert ts.loc["Montréal", "univers_2ch_2025"] == 362373 | ||||
| 123 | + | ||||
| 124 | + | ||||
| 125 | +class TestDatation: | ||||
| 126 | + def test_biais(self): | ||||
| 127 | + bd = cas.biais_datation().set_index(["croissance_annuelle_pct", "delai_mois"])["biais_pct"] | ||||
| 128 | + assert bd[(6.0, 3)] == pytest.approx(1.47, abs=0.005) and bd[(10.0, 3)] == pytest.approx(2.41, abs=0.005) | ||||
| 129 | + assert bd[(10.0, 6)] == pytest.approx(4.88, abs=0.005) and bd[(-3.0, 6)] == pytest.approx(-1.51, abs=0.005) | ||||
| 130 | + assert (bd.xs(0.0, level=0) == 0).all() | ||||
| 131 | + # approximation du premier ordre : b ≈ g·δ/12 | ||||
| 132 | + assert bd[(3.0, 1)] == pytest.approx(0.25, abs=0.01) | ||||
| 133 | + | ||||
| 134 | + def test_proposition_signe(self): | ||||
| 135 | + for g in (-0.03, 0.03, 0.10): | ||||
| 136 | + b = (1 + g) ** (-3 / 12) - 1 | ||||
| 137 | + assert math.copysign(1, b) == -math.copysign(1, g) | ||||
| 138 | + | ||||
| 139 | + | ||||
| 140 | +class TestExercices: | ||||
| 141 | + def test_ex1_registre(self): | ||||
| 142 | + r = cas.exercice_registre() | ||||
| 143 | + assert r["consultation"] == 50 and r["etats"] == 96 and r["total"] == 146 | ||||
| 144 | + | ||||
| 145 | + def test_ex2_prix_corrige(self): | ||||
| 146 | + ex = cas.prix_corrige(612000, 12000, 0.06, 75 / 30.4375) | ||||
| 147 | + assert ex["prix_immeuble"] == 600000 and ex["facteur_datation"] == pytest.approx(1.0120, abs=5e-5) | ||||
| 148 | + assert ex["ecart_dollars"] == pytest.approx(7222, abs=1) | ||||
| 149 | + | ||||
| 150 | + def test_ex4_indexation(self, schl): | ||||
| 151 | + _, ts = schl | ||||
| 152 | + brute = ts.loc["Montréal", "loyer_2ch_2025"] / ts.loc["Montréal", "loyer_2ch_2024"] | ||||
| 153 | + assert 1300 * brute == pytest.approx(1487.93, abs=0.01) and 1300 * 1.072 == pytest.approx(1393.60, abs=0.01) | ||||
| 154 | + ecart = 1300 * (brute - 1.072) | ||||
| 155 | + assert ecart == pytest.approx(94.33, abs=0.01) and ecart * 12 == pytest.approx(1132, abs=0.5) | ||||
| 156 | + assert ecart * 12 * 12 / 0.045 == pytest.approx(301840, abs=5) | ||||
| 157 | + | ||||
| 158 | + def test_ex5_ipcb_quebec(self, ipcb): | ||||
| 159 | + e = cas.exercice_ipcb_quebec(ipcb) | ||||
| 160 | + assert e["Montréal"]["ratio_2023T1_2026T3"] == pytest.approx(1.1792, abs=5e-5) and e["Montréal"]["tcac_2023T1_2026T3_pct"] == pytest.approx(4.82, abs=0.005) | ||||
| 161 | + assert e["Québec"]["ratio_2023T1_2026T3"] == pytest.approx(1.2632, abs=5e-5) and e["Québec"]["tcac_2023T1_2026T3_pct"] == pytest.approx(6.90, abs=0.005) | ||||
| 162 | + assert e["Composite"]["ratio_2023T1_2026T3"] == pytest.approx(1.1391, abs=5e-5) and e["Composite"]["tcac_2023T1_2026T3_pct"] == pytest.approx(3.79, abs=0.005) | ||||
| 163 | + assert e["Montréal"]["ratio_2019T3_2026T3"] == pytest.approx(1.6453, abs=5e-5) and e["Composite"]["ratio_2019T3_2026T3"] == pytest.approx(1.7406, abs=5e-5) | ||||
| 164 | + assert e["Québec"]["ratio_2019T3_2026T3"] is None and e["Composite"]["var_annuelle_pct"] == pytest.approx(2.67, abs=0.005) | ||||
| 165 | + assert 350000 * e["Québec"]["ratio_2023T1_2026T3"] == pytest.approx(442105, abs=1) | ||||
| 166 | + assert 350000 * e["Montréal"]["ratio_2023T1_2026T3"] == pytest.approx(412713, abs=1) | ||||
| 167 | + assert 350000 * e["Composite"]["ratio_2023T1_2026T3"] == pytest.approx(398671, abs=1) | ||||
| 168 | + assert e["Montréal"]["ratio_2023T1_2026T3"] / e["Québec"]["ratio_2023T1_2026T3"] - 1 == pytest.approx(-0.066, abs=5e-4) | ||||
| 169 | + | ||||
| 170 | + def test_ex6_couverture(self): | ||||
| 171 | + c = cas.exercice_couverture() | ||||
| 172 | + assert c["couverture"] == pytest.approx(0.696, abs=5e-4) and c["appariement"] == pytest.approx(0.881, abs=5e-4) | ||||
| 173 | + assert c["moyenne_marche"] == pytest.approx(493280, abs=0.01) and c["biais_courtier_dollars"] == pytest.approx(16720, abs=0.01) | ||||
| 174 | + assert c["biais_courtier_pct"] == pytest.approx(3.39, abs=0.005) | ||||
| 175 | + # identité de composition (eq. 13.6) | ||||
| 176 | + assert c["poids_courtier"] * 510000 + (1 - c["poids_courtier"]) * 455000 == pytest.approx(c["moyenne_marche"], rel=1e-12) | ||||
added
analysis/python/tests/test_ch25.py
+220 −0
@@ -0,0 +1,220 @@ | |||||
| 1 | +"""Tests du chapitre 25 — Évaluation du terrain : jeu synthétique de terrains (graine 20261031), modèle hédonique des terrains, | ||||
| 2 | +comparaison directe (grille et réconciliation), allocation et prix implicite marginal (cas 1), extraction (cinq comparables du ch. 16), | ||||
| 3 | +technique résiduelle (cas 3), lotissement actualisé, rente foncière, valeur retenue et exercices. | ||||
| 4 | +Tolérances : 1 $ sur les montants recalculés ; 0,5 $ ou 0,05 % sur les valeurs arrondies citées ; 1e-9 sur les identités.""" | ||||
| 5 | +import sys, pathlib, math | ||||
| 6 | +import numpy as np, pytest | ||||
| 7 | +sys.path.insert(0, str(pathlib.Path(__file__).resolve().parents[1] / "cases")) | ||||
| 8 | +import ch25_terrain as cas | ||||
| 9 | +from traite import finance as fin | ||||
| 10 | + | ||||
| 11 | + | ||||
| 12 | +@pytest.fixture(scope="module") | ||||
| 13 | +def S(): | ||||
| 14 | + return cas.synthese() | ||||
| 15 | + | ||||
| 16 | + | ||||
| 17 | +class TestJeuTerrains: | ||||
| 18 | + def test_reproductibilite(self, S): | ||||
| 19 | + df = S["comparaison"]["terrains"] | ||||
| 20 | + regen = cas.generer_terrains() | ||||
| 21 | + assert len(df) == 200 and len(regen) == 200 | ||||
| 22 | + assert int(df["desservi"].sum()) == 156 | ||||
| 23 | + assert df["prix_vente"].sum() == pytest.approx(52_123_500.0, abs=0.5) | ||||
| 24 | + assert np.allclose(df["prix_vente"].values, regen["prix_vente"].values) | ||||
| 25 | + assert df.iloc[0]["id_vente"] == "T001" and df.iloc[0]["prix_vente"] == 180_500.0 | ||||
| 26 | + assert (df["prix_vente"] % 500 == 0).all() | ||||
| 27 | + | ||||
| 28 | + def test_structure(self, S): | ||||
| 29 | + df = S["comparaison"]["terrains"] | ||||
| 30 | + assert df.groupby("secteur").size().to_dict() == {"Aylmer": 40, "Buckingham": 15, "Gatineau": 60, "Hull": 70, "Masson-Angers": 15} | ||||
| 31 | + assert df["date_vente"].min() >= np.datetime64("2023-01-01") and df["date_vente"].max() <= np.datetime64("2026-08-31") | ||||
| 32 | + # valeur unitaire décroissante avec la superficie, desservis plus chers au m² | ||||
| 33 | + d1, d0 = df[df["desservi"] == 1], df[df["desservi"] == 0] | ||||
| 34 | + assert d1["prix_m2"].median() > 2 * d0["prix_m2"].median() | ||||
| 35 | + assert np.corrcoef(np.log(d1["superficie_m2"]), np.log(d1["prix_m2"]))[0, 1] < -0.5 | ||||
| 36 | + | ||||
| 37 | + | ||||
| 38 | +class TestHedoniqueTerrains: | ||||
| 39 | + def test_recuperation_des_lois(self, S): | ||||
| 40 | + m = S["comparaison"]["modele"]; b = m["beta"] | ||||
| 41 | + assert m["n"] == 200 and 0.85 < m["r2"] < 0.95 | ||||
| 42 | + assert b["ln_T"] == pytest.approx(cas.ELAST_T, abs=0.07) | ||||
| 43 | + assert b["non_desservi"] == pytest.approx(cas.B_NON_DESSERVI, abs=0.08) | ||||
| 44 | + assert b["roc"] < b["pente"] < 0 and b["logements_sup"] > 0.08 | ||||
| 45 | + assert b["sect_Aylmer"] > 0 > b["sect_Buckingham"] and b["mois"] > 0 | ||||
| 46 | + assert b["ln_T"] == pytest.approx(0.5267, abs=5e-4) and b["mois"] == pytest.approx(0.0028, abs=5e-4) | ||||
| 47 | + | ||||
| 48 | + def test_prediction_sujet(self, S): | ||||
| 49 | + assert S["comparaison"]["prediction_hedonique"] == pytest.approx(253_412, abs=1) | ||||
| 50 | + | ||||
| 51 | + | ||||
| 52 | +class TestComparaison: | ||||
| 53 | + def test_entonnoir_et_selection(self, S): | ||||
| 54 | + sel = S["comparaison"]["selection"] | ||||
| 55 | + assert sel["etapes"] == {"total": 200, "fenetre": 101, "rayon": 29, "desservi_unifamilial": 21, "superficie": 20} | ||||
| 56 | + assert sel["comparables"]["id_vente"].tolist() == ["T059", "T004", "T030", "T038", "T049"] | ||||
| 57 | + assert (sel["comparables"]["secteur"] == "Hull").all() and (sel["comparables"]["desservi"] == 1).all() | ||||
| 58 | + | ||||
| 59 | + def test_grille_identites(self, S): | ||||
| 60 | + g = S["comparaison"]["grille"] | ||||
| 61 | + for _, r in g.iterrows(): | ||||
| 62 | + assert r["prix_ajuste"] == pytest.approx(r["prix_vente"] + sum(r[k] for k in cas.GROUPES), rel=1e-12) | ||||
| 63 | + assert r["ajust_net_pct"] == pytest.approx((r["prix_ajuste"] - r["prix_vente"]) / r["prix_vente"], rel=1e-9) | ||||
| 64 | + assert r["ajust_brut_pct"] >= abs(r["ajust_net_pct"]) - 1e-12 | ||||
| 65 | + assert (g["localisation"] == 0).all() # tous les comparables sont dans le secteur du sujet | ||||
| 66 | + assert g.set_index("id_vente").loc["T049", "forme"] == pytest.approx(9_046, abs=1) | ||||
| 67 | + assert g["prix_ajuste"].round(0).tolist() == [265_383, 259_943, 274_166, 294_813, 232_086] | ||||
| 68 | + | ||||
| 69 | + def test_reconciliation(self, S): | ||||
| 70 | + r = S["comparaison"]["reconciliation"] | ||||
| 71 | + assert sum(r["poids"]) == pytest.approx(1.0, abs=1e-12) | ||||
| 72 | + assert np.round(r["poids"], 3).tolist() == [0.402, 0.131, 0.217, 0.146, 0.104] | ||||
| 73 | + assert r["valeur_ponderee"] == pytest.approx(267_388, abs=1) | ||||
| 74 | + assert r["moyenne"] == pytest.approx(265_278, abs=1) and r["mediane"] == pytest.approx(265_383, abs=1) | ||||
| 75 | + assert r["min"] == pytest.approx(232_086, abs=1) and r["max"] == pytest.approx(294_813, abs=1) | ||||
| 76 | + assert r["etendue_pct"] == pytest.approx(0.235, abs=1e-3) | ||||
| 77 | + assert S["comparaison"]["valeur_m2"] == pytest.approx(431.3, abs=0.1) | ||||
| 78 | + | ||||
| 79 | + | ||||
| 80 | +class TestAllocationExtraction: | ||||
| 81 | + def test_allocation(self, S): | ||||
| 82 | + a = S["allocation"]; e = S["extraction"] | ||||
| 83 | + assert a["ratio"] == pytest.approx(0.482, abs=5e-4) and e["part_hull_q1"] == pytest.approx(0.424, abs=5e-4) and e["part_hull_q3"] == pytest.approx(0.543, abs=5e-4) | ||||
| 84 | + assert a["P_grille"] == pytest.approx(581_595, abs=1) and a["P_hed"] == pytest.approx(637_953, abs=1) | ||||
| 85 | + assert a["sur_grille"] == pytest.approx(280_412, abs=1) and a["sur_hedonique"] == pytest.approx(307_584, abs=1) | ||||
| 86 | + assert a["sur_grille"] == pytest.approx(a["ratio"] * a["P_grille"], rel=1e-12) | ||||
| 87 | + | ||||
| 88 | + def test_prix_implicite_marginal(self, S): | ||||
| 89 | + a = S["allocation"] | ||||
| 90 | + assert a["beta_ln_T"] == pytest.approx(0.0937, abs=5e-4) | ||||
| 91 | + assert a["prix_marginal_m2"] == pytest.approx(96.4, abs=0.1) | ||||
| 92 | + assert a["contribution_marginale"] == pytest.approx(59_750, abs=1) | ||||
| 93 | + assert a["prix_marginal_m2"] * 620 == pytest.approx(a["contribution_marginale"], rel=1e-12) | ||||
| 94 | + assert a["sujet_age_factor"] == pytest.approx(0.8852, abs=5e-4) and a["delta_marche_sujet"] == pytest.approx(0.208, abs=5e-4) | ||||
| 95 | + | ||||
| 96 | + def test_extraction_comparables(self, S): | ||||
| 97 | + e = S["extraction"]["comparables"].set_index("id_vente") | ||||
| 98 | + # identités : V_L = P − C_N(1 − δ) sous les deux conventions | ||||
| 99 | + for k, r in e.iterrows(): | ||||
| 100 | + assert r["V_L_agevie"] == pytest.approx(r["prix_vente"] - r["C_N"] * (1 - r["age"] / cas.VIE_ECONOMIQUE), rel=1e-12) | ||||
| 101 | + assert r["V_L_marche"] == pytest.approx(r["prix_vente"] - r["C_N"] * (1 - r["delta_marche"]), rel=1e-9) | ||||
| 102 | + assert r["V_L_marche"] == pytest.approx(r["P_neuf"] - r["C_N"], rel=1e-12) | ||||
| 103 | + g = e.loc["G0477"] | ||||
| 104 | + assert g["C_N"] == pytest.approx(391_729, abs=1) and g["delta_agevie"] == pytest.approx(0.40, abs=1e-9) | ||||
| 105 | + assert g["V_L_agevie"] == pytest.approx(302_963, abs=1) and g["V_L_marche"] == pytest.approx(207_093, abs=1) | ||||
| 106 | + assert g["P_neuf"] == pytest.approx(598_821, abs=1) and g["delta_marche"] == pytest.approx(0.155, abs=5e-4) | ||||
| 107 | + assert e.loc["G0574", "V_L_marche"] == pytest.approx(281_458, abs=1) and e.loc["G0404", "V_L_marche"] == pytest.approx(174_883, abs=1) | ||||
| 108 | + assert e.loc["G0575", "V_L_marche_m2"] == pytest.approx(618.7, abs=0.1) | ||||
| 109 | + assert S["extraction"]["indication_marche"] == pytest.approx(242_545, abs=1) | ||||
| 110 | + assert S["extraction"]["indication_agevie"] == pytest.approx(354_826, abs=1) | ||||
| 111 | + assert S["extraction"]["V_L_hull_mediane"] == pytest.approx(243_421, abs=1) | ||||
| 112 | + | ||||
| 113 | + def test_cout_neuf_comparable(self): | ||||
| 114 | + assert cas.cout_neuf_comparable(165, 3) == pytest.approx(cas.C_N_SUJET, rel=1e-12) | ||||
| 115 | + assert cas.cout_neuf_comparable(146, 4) == pytest.approx(391_729, abs=1) | ||||
| 116 | + | ||||
| 117 | + | ||||
| 118 | +class TestResiduelle: | ||||
| 119 | + def test_cas_de_base(self, S): | ||||
| 120 | + r = S["residuelle"] | ||||
| 121 | + assert r["noi"] == pytest.approx(89_955.75, abs=0.01) and r["R"] == pytest.approx(0.04415, abs=1e-6) | ||||
| 122 | + assert r["C_N"] == pytest.approx(2_375_000, abs=0.01) and r["C_B"] == pytest.approx(1_140_000, abs=0.01) | ||||
| 123 | + assert r["R_B"] == pytest.approx(0.0625, abs=1e-12) and r["revenu_batiment"] == pytest.approx(71_250, abs=0.01) | ||||
| 124 | + assert r["revenu_terrain"] == pytest.approx(18_705.75, abs=0.01) | ||||
| 125 | + assert r["V_L"] == pytest.approx(498_820, abs=1) and r["V_L_m2"] == pytest.approx(674.1, abs=0.1) | ||||
| 126 | + # identité de la bande d'investissement : RNE = R_L V_L + R_B C_B | ||||
| 127 | + assert r["R_L"] * r["V_L"] + r["R_B"] * r["C_B"] == pytest.approx(r["noi"], rel=1e-12) | ||||
| 128 | + assert r["somme"] == pytest.approx(1_638_820, abs=1) and r["ecart_vs_cap"] == pytest.approx(-0.196, abs=1e-3) | ||||
| 129 | + assert r["V_cap"] == pytest.approx(2_037_503, abs=1) and r["V_cap"] - r["C_B"] == pytest.approx(897_503, abs=1) | ||||
| 130 | + assert r["R_L_implicite"] == pytest.approx(0.0208, abs=5e-4) and r["part_terrain"] == pytest.approx(0.304, abs=5e-4) | ||||
| 131 | + | ||||
| 132 | + def test_sensibilite(self, S): | ||||
| 133 | + s = cas.sensibilite_residuelle(S["cas3"]).set_index(["taux_depreciation", "n_restante", "R_L"])["V_L"] | ||||
| 134 | + assert s.loc[(0.44, 30, 0.0425)] == pytest.approx(-256_531, abs=1) # valeur négative : la technique « casse » | ||||
| 135 | + assert s.loc[(0.52, 40, 0.0425)] == pytest.approx(306_018, abs=1) | ||||
| 136 | + assert s.loc[(0.52, 40, 0.0325)] == pytest.approx(750_946, abs=1) | ||||
| 137 | + assert s.loc[(0.60, 50, 0.0325)] == pytest.approx(1_233_254, abs=1) | ||||
| 138 | + assert s.loc[(0.52, 30, 0.0375)] == pytest.approx(245_487, abs=1) and s.loc[(0.52, 50, 0.0375)] == pytest.approx(650_820, abs=1) | ||||
| 139 | + # effet de levier : −50 pb sur R_L (3,75 → 4,25 %) retranche 38,6 % à V_L | ||||
| 140 | + assert s.loc[(0.52, 40, 0.0425)] / s.loc[(0.52, 40, 0.0375)] - 1 == pytest.approx(-0.386, abs=1e-3) | ||||
| 141 | + | ||||
| 142 | + | ||||
| 143 | +class TestLotissement: | ||||
| 144 | + def test_cas_de_base(self, S): | ||||
| 145 | + L = S["lotissement"]; p = L["params"] | ||||
| 146 | + assert p["n_lots"] * p["lot_m2"] + p["rue_m2"] + p["parc_m2"] == p["site_m2"] | ||||
| 147 | + assert p["parc_m2"] / p["site_m2"] == pytest.approx(0.10, abs=1e-12) # plafond de l'art. 117.4 LAU | ||||
| 148 | + assert L["prix_lot"] == pytest.approx(254_486, abs=1) and L["produit_brut"] == pytest.approx(3_053_830, abs=1) | ||||
| 149 | + assert L["n_ans"] == 3 and len(L["flux"]) == 4 | ||||
| 150 | + assert L["valeur_actualisee"] == pytest.approx(fin.van(L["flux"], p["taux"]), rel=1e-12) | ||||
| 151 | + assert L["valeur_actualisee"] == pytest.approx(1_230_878, abs=1) and L["valeur_m2"] == pytest.approx(123.1, abs=0.1) | ||||
| 152 | + assert L["valeur_statique"] == pytest.approx(1_579_602, abs=1) and L["valeur_statique_m2"] == pytest.approx(158.0, abs=0.1) | ||||
| 153 | + assert L["ratio_terrain_brut_sur_produit"] == pytest.approx(0.403, abs=1e-3) | ||||
| 154 | + d = L["detail"] | ||||
| 155 | + assert d["revenus"].sum() == pytest.approx(L["produit_brut"], rel=1e-12) | ||||
| 156 | + assert d.loc[1, "infrastructure"] == pytest.approx(780_000, abs=0.01) and d.loc[1, "profit"] == pytest.approx(152_692, abs=1) | ||||
| 157 | + assert d["flux"].round(0).tolist() == [-90_000, 32_534, 816_534, 820_534] | ||||
| 158 | + | ||||
| 159 | + def test_sensibilite(self, S): | ||||
| 160 | + sl = cas.sensibilite_lotissement(S["comparaison"]["modele"]) | ||||
| 161 | + assert sl["absorption"][2] == pytest.approx(963_545, abs=1) and sl["absorption"][6] == pytest.approx(1_331_556, abs=1) | ||||
| 162 | + assert sl["taux"][0.08] == pytest.approx(1_291_537, abs=1) and sl["taux"][0.15] == pytest.approx(1_095_222, abs=1) | ||||
| 163 | + assert sl["prix"][-0.10] == pytest.approx(1_025_828, abs=1) and sl["prix"][0.10] == pytest.approx(1_435_927, abs=1) | ||||
| 164 | + assert sl["infrastructure"][80_000] == pytest.approx(1_067_241, abs=1) and sl["profit"][0.20] == pytest.approx(1_104_304, abs=1) | ||||
| 165 | + # effet de levier du prix : ±10 % sur les lots → ±16,7 % sur le site brut | ||||
| 166 | + assert sl["prix"][0.10] / sl["base"] - 1 == pytest.approx(0.1666, abs=5e-4) | ||||
| 167 | + | ||||
| 168 | + | ||||
| 169 | +class TestRenteEtSynthese: | ||||
| 170 | + def test_rente(self, S): | ||||
| 171 | + r = S["rente"] | ||||
| 172 | + assert r["perpetuelle"] == pytest.approx(220_000, abs=0.01) and r["gordon"] == pytest.approx(366_667, abs=1) | ||||
| 173 | + assert r["bail_n"] == pytest.approx(294_278, abs=1) and r["va_reversion"] == pytest.approx(42_614, abs=1) and r["va_rentes"] == pytest.approx(251_664, abs=1) | ||||
| 174 | + assert r["gordon"] == pytest.approx(11_000 / (0.05 - 0.02), rel=1e-12) | ||||
| 175 | + | ||||
| 176 | + def test_valeur_retenue(self, S): | ||||
| 177 | + assert S["valeur_retenue"] == 265_000 | ||||
| 178 | + assert S["valeur_retenue"] / 620 == pytest.approx(427.4, abs=0.1) | ||||
| 179 | + assert S["part_retenue_grille"] == pytest.approx(0.456, abs=5e-4) and S["part_retenue_hed"] == pytest.approx(0.415, abs=5e-4) | ||||
| 180 | + # cohérence : la valeur retenue est encadrée par les indications d'extraction (marché) et d'allocation (grille) | ||||
| 181 | + assert S["extraction"]["indication_marche"] < S["valeur_retenue"] < S["allocation"]["sur_grille"] | ||||
| 182 | + | ||||
| 183 | + | ||||
| 184 | +class TestExercices: | ||||
| 185 | + def test_ex1_unites(self): | ||||
| 186 | + P, T, F = [240_000, 268_000, 227_500], [560, 720, 480], [17, 20, 15] | ||||
| 187 | + pm = [p / t for p, t in zip(P, T)]; pf = [p / f for p, f in zip(P, F)] | ||||
| 188 | + assert [round(x, 1) for x in pm] == [428.6, 372.2, 474.0] and [round(x) for x in pf] == [14_118, 13_400, 15_167] | ||||
| 189 | + assert float(np.median(pm)) * 620 == pytest.approx(265_714, abs=1) and float(np.median(pf)) * 20 == pytest.approx(282_353, abs=1) | ||||
| 190 | + | ||||
| 191 | + def test_ex2_allocation(self): | ||||
| 192 | + assert 0.45 * 560_000 == pytest.approx(252_000) and 180_000 / 480_000 == pytest.approx(0.375) | ||||
| 193 | + | ||||
| 194 | + def test_ex3_extraction(self, S): | ||||
| 195 | + g = S["extraction"]["comparables"].set_index("id_vente").loc["G0477"] | ||||
| 196 | + assert g["V_L_agevie"] == pytest.approx(302_963, abs=1) and g["V_L_marche"] == pytest.approx(207_093, abs=1) | ||||
| 197 | + assert g["V_L_agevie"] / 452 == pytest.approx(670.3, abs=0.1) and g["V_L_marche"] / 452 == pytest.approx(458.2, abs=0.1) | ||||
| 198 | + assert g["V_L_agevie_sujet"] == pytest.approx(354_826, abs=1) and g["V_L_marche_sujet"] == pytest.approx(242_545, abs=1) | ||||
| 199 | + | ||||
| 200 | + def test_ex4_residuelle(self, S): | ||||
| 201 | + r0 = S["residuelle"]; r1 = cas.residuelle_cas3({"R_L": 0.0425}, S["cas3"]) | ||||
| 202 | + assert r0["V_L"] == pytest.approx(498_820, abs=1) and r1["V_L"] == pytest.approx(306_018, abs=1) and r1["R_B"] == pytest.approx(0.0675, abs=1e-12) | ||||
| 203 | + assert r1["V_L"] / r0["V_L"] - 1 == pytest.approx(-0.386, abs=1e-3) | ||||
| 204 | + | ||||
| 205 | + def test_ex5_superficie(self): | ||||
| 206 | + assert 283_500 * (620 / 743.1) ** 0.5 == pytest.approx(258_956, abs=1) | ||||
| 207 | + assert 283_500 / 743.1 * 620 == pytest.approx(236_536, abs=1) | ||||
| 208 | + | ||||
| 209 | + def test_ex6_lotissement(self, S): | ||||
| 210 | + m = S["comparaison"]["modele"]; L = S["lotissement"] | ||||
| 211 | + L2 = cas.lotissement(m, {"lots_par_an": 2, "taux": 0.12}) | ||||
| 212 | + assert L2["n_ans"] == 6 and L2["valeur_actualisee"] == pytest.approx(877_093, abs=1) | ||||
| 213 | + assert L2["valeur_actualisee"] / L["valeur_actualisee"] - 1 == pytest.approx(-0.287, abs=1e-3) | ||||
| 214 | + perte_parc = 1.6 * L["prix_lot"] * (1 - 0.04 - 0.15) / 1.1 ** 3 | ||||
| 215 | + assert perte_parc == pytest.approx(247_794, abs=1) | ||||
| 216 | + | ||||
| 217 | + def test_ex7_rente(self, S): | ||||
| 218 | + r = cas.rente_fonciere(rente=11_000, R_L=0.05, g=0.02, n=40, valeur_reversion=300_000) | ||||
| 219 | + assert r["bail_n"] == pytest.approx(294_278, abs=1) | ||||
| 220 | + assert cas.rente_fonciere(g=0.0, n=40)["va_rentes"] == pytest.approx(11_000 * fin.facteur_va_annuite(0.05, 40), rel=1e-9) | ||||
modified
analysis/python/tests/test_ch32.py
+1 −1
@@ -111,7 +111,7 @@ def test_sensibilite(R): | |||||
| 111 | F = S["financement"] | 111 | F = S["financement"] | ||
| 112 | assert F["cout_net_mensuel"].iloc[4] > F["cout_net_mensuel"].iloc[0] # +100 pb coûte plus cher | 112 | assert F["cout_net_mensuel"].iloc[4] > F["cout_net_mensuel"].iloc[0] # +100 pb coûte plus cher | ||
| 113 | assert F["service_dette"].iloc[1] < F["service_dette"].iloc[0] # 30 ans < 25 ans | 113 | assert F["service_dette"].iloc[1] < F["service_dette"].iloc[0] # 30 ans < 25 ans | ||
| 114 | − T = S["taux"]; assert all(T["valeur"] == pytest.approx(R["base"]["rne"] / T["taux"])) | 114 | + T = S["taux"]; assert np.allclose(T["valeur"], R["base"]["rne"] / T["taux"]) | ||
| 115 | 115 | ||||
| 116 | 116 | ||||
| 117 | # ----------------------------------------------------------------------------- exercices (solutions/ch32.tex) | 117 | # ----------------------------------------------------------------------------- exercices (solutions/ch32.tex) | ||
added
analysis/python/tests/test_ch33.py
+137 −0
@@ -0,0 +1,137 @@ | |||||
| 1 | +"""Tests du chapitre 33 (immeubles de six logements et plus) : identités, cohérence avec traite.cas3/cas4 et le ch. 47, | ||||
| 2 | +lecture des tableaux SCHL (données réelles), valeurs citées dans le texte. Tolérances déclarées : montants ±1 $, | ||||
| 3 | +taux ±1e-5 (±0,1 pb), pourcentages ±1e-4.""" | ||||
| 4 | +import sys, pathlib | ||||
| 5 | +import numpy as np, pytest | ||||
| 6 | +sys.path.insert(0, str(pathlib.Path(__file__).resolve().parents[1] / "cases")) | ||||
| 7 | +from traite import cas3, cas4, finance as fin | ||||
| 8 | +import ch33_six_logements as ch | ||||
| 9 | + | ||||
| 10 | +@pytest.fixture(scope="module") | ||||
| 11 | +def R(): | ||||
| 12 | + return ch.calculer() | ||||
| 13 | + | ||||
| 14 | +# ----------------------------------------------------------------------------- SCHL (réel) | ||||
| 15 | + | ||||
| 16 | +def test_schl_lecture_coherente_avec_notes(R): | ||||
| 17 | + t = R["schl"]["taille"].set_index("categorie"); a = R["schl"]["annee"].set_index("categorie") | ||||
| 18 | + # valeurs consignées dans sources/notes-E.md (ch. 27 et 47) : 6-19 unités île : 2,2 % / 1 177 $ (2 ch.) / 1 162 $ (tous) | ||||
| 19 | + assert t.loc["6 à 19 unités", "inoccupation_tous"] == pytest.approx(2.2) and t.loc["6 à 19 unités", "loyer_2ch"] == 1177 and t.loc["6 à 19 unités", "loyer_tous"] == 1162 | ||||
| 20 | + assert t.loc["20 à 49 unités", "inoccupation_tous"] == pytest.approx(3.9) and t.loc["50 à 99 unités", "inoccupation_tous"] == pytest.approx(3.8) | ||||
| 21 | + assert t.loc["100 unités et +", "inoccupation_tous"] == pytest.approx(5.1) and t.loc["100 unités et +", "loyer_2ch"] == 1966 | ||||
| 22 | + assert t.loc["3 à 5 unités", "loyer_2ch"] == 1350 and t.loc["Tous les immeubles", "inoccupation_tous"] == pytest.approx(3.1) | ||||
| 23 | + assert a.loc["Avant 1940", "loyer_tous"] == 1238 and a.loc["1960 à 1974", "loyer_tous"] == 1186 and a.loc["2015 ou après", "loyer_tous"] == 1882 | ||||
| 24 | + assert a.loc["2015 ou après", "inoccupation_tous"] == pytest.approx(5.6) | ||||
| 25 | + assert list(t.index) == ["3 à 5 unités", "6 à 19 unités", "20 à 49 unités", "50 à 99 unités", "100 unités et +", "Tous les immeubles"] | ||||
| 26 | + | ||||
| 27 | +# ----------------------------------------------------------------------------- cas 4 : sommaire et identités | ||||
| 28 | + | ||||
| 29 | +def test_sommaire_cas4_identites(R): | ||||
| 30 | + g = R["sommaire"]["par_rmr"]; t = R["sommaire"]["total"]; pf = R["sommaire"]["portefeuille"] | ||||
| 31 | + assert t["n"] == 48 and t["logements"] == 888 and g["n"].sum() == 48 and g["logements"].sum() == 888 | ||||
| 32 | + assert g["valeur"].sum() == pytest.approx(t["valeur"]) and t["valeur"] == pytest.approx(143_363_000) | ||||
| 33 | + for r in g.index: | ||||
| 34 | + assert g.loc[r, "taux_pondere"] == pytest.approx(g.loc[r, "rne"] / g.loc[r, "valeur"]) | ||||
| 35 | + assert g.loc[r, "valeur_par_logement"] == pytest.approx(g.loc[r, "valeur"] / g.loc[r, "logements"]) | ||||
| 36 | + assert t["taux_pondere"] == pytest.approx(0.051945, abs=1e-5) and t["valeur"] / t["logements"] == pytest.approx(161_445, abs=1) | ||||
| 37 | + assert g.loc["Montréal", "valeur_par_logement"] == pytest.approx(206_237, abs=1) and g.loc["Gatineau", "valeur_par_logement"] == pytest.approx(184_173, abs=1) | ||||
| 38 | + assert g.loc["Québec", "valeur_par_logement"] == pytest.approx(125_455, abs=1) and g.loc["Saguenay", "valeur_par_logement"] == pytest.approx(101_969, abs=1) | ||||
| 39 | + assert g.loc["Montréal", "taux_pondere"] == pytest.approx(0.044948, abs=1e-5) and g.loc["Gatineau", "taux_pondere"] == pytest.approx(0.054359, abs=1e-5) | ||||
| 40 | + assert g.loc["Trois-Rivières", "taux_pondere"] == pytest.approx(0.062883, abs=1e-5) and g.loc["Saguenay", "taux_median"] == pytest.approx(0.0646, abs=1e-5) | ||||
| 41 | + # cohérence avec le module partagé | ||||
| 42 | + s = cas4.sommaire(pf) | ||||
| 43 | + assert s["total"]["taux_pondere"] == pytest.approx(t["taux_pondere"]) and (s["par_rmr"]["valeur_par_logement"].sort_index() == g["valeur_par_logement"].sort_index()).all() | ||||
| 44 | + | ||||
| 45 | +# ----------------------------------------------------------------------------- effet de taille | ||||
| 46 | + | ||||
| 47 | +def test_effet_taille(R): | ||||
| 48 | + et = R["effet_taille"] | ||||
| 49 | + assert et["cas3_n"] == 40 and et["cas3_mediane"] == pytest.approx(0.04415, abs=1e-6) | ||||
| 50 | + assert et["cas3_pente_pb_par_logement"] == pytest.approx(-2.27, abs=0.01) and et["d_pb_12_36_cas3"] == pytest.approx(-54.6, abs=0.1) | ||||
| 51 | + assert et["cas4_coef_ln"] == pytest.approx(-0.03153, abs=1e-4) and et["cas4_se_ln"] == pytest.approx(0.01222, abs=1e-4) | ||||
| 52 | + assert et["cas4_effet_doublement_pct"] == pytest.approx(np.exp(et["cas4_coef_ln"] * np.log(2)) - 1) and et["cas4_effet_doublement_pct"] == pytest.approx(-0.0216, abs=1e-4) | ||||
| 53 | + assert et["d_pb_12_36_cas4"] == pytest.approx(-15.7, abs=0.1) | ||||
| 54 | + # mêmes coefficients que traite.cas4.effets_regionaux | ||||
| 55 | + e = cas4.effets_regionaux(R["sommaire"]["portefeuille"]) | ||||
| 56 | + assert e.loc["ln_logements", "coef"] == pytest.approx(et["cas4_coef_ln"]) and e.loc["rmr_Gatineau", "effet_pct"] == pytest.approx(0.1962, abs=1e-4) | ||||
| 57 | + assert e.loc["rmr_Trois-Rivières", "effet_pct"] == pytest.approx(0.4017, abs=1e-4) and e.loc["etat", "effet_pct"] == pytest.approx(-0.0396, abs=1e-4) | ||||
| 58 | + | ||||
| 59 | +# ----------------------------------------------------------------------------- unités (cas 3) | ||||
| 60 | + | ||||
| 61 | +def test_unites_cas3(R): | ||||
| 62 | + u = R["unites"]; b = cas3.tout()["base"] | ||||
| 63 | + assert u["n"] == 12 and u["m2"] == 825 and u["chambres"] == 22 | ||||
| 64 | + assert u["par_logement"] == pytest.approx(2_060_000 / 12) and u["par_m2"] == pytest.approx(2_060_000 / 825) and u["par_chambre"] == pytest.approx(2_060_000 / 22) | ||||
| 65 | + assert u["par_logement"] == pytest.approx(171_667, abs=1) and u["par_m2"] == pytest.approx(2_497, abs=1) and u["par_chambre"] == pytest.approx(93_636, abs=1) | ||||
| 66 | + assert u["mrb"] == pytest.approx(2_060_000 / b["rbp_contrat"]) and u["mrb"] == pytest.approx(12.44, abs=0.01) and u["mrb_marche"] == pytest.approx(11.07, abs=0.01) | ||||
| 67 | + assert u["taux_implicite"] == pytest.approx(b["rne"] / 2_060_000) and u["taux_implicite"] == pytest.approx(0.04367, abs=1e-5) | ||||
| 68 | + assert u["valeur_cap"] == pytest.approx(2_037_502.89, abs=0.01) and u["rne_par_logement"] == pytest.approx(7_496.31, abs=0.01) | ||||
| 69 | + assert u["loyer_moyen_m2"] == pytest.approx(16.72, abs=0.01) | ||||
| 70 | + | ||||
| 71 | +def test_valeur_finale_ch47_coherente(): | ||||
| 72 | + """La valeur finale citée (2 060 000 $) est celle de la réconciliation du chapitre 47.""" | ||||
| 73 | + import ch47_dossier as c47 | ||||
| 74 | + D = c47.dossier(n_mc=200, graine=c47.GRAINE) | ||||
| 75 | + assert D["reconciliation"]["valeur_finale"] == ch.V_FINALE_CH47 | ||||
| 76 | + | ||||
| 77 | +# ----------------------------------------------------------------------------- P45 | ||||
| 78 | + | ||||
| 79 | +def test_p45_identites_et_valeurs(R): | ||||
| 80 | + p = R["p45"] | ||||
| 81 | + assert p["id"] == "P45" and p["n"] == 36 and p["rmr"] == "Gatineau" and p["etat"] == 2 and p["annee"] == 1954 | ||||
| 82 | + assert p["rne"] == pytest.approx(366_800) and p["rne_par_logement"] == pytest.approx(10_188.89, abs=0.01) | ||||
| 83 | + for k, R_ in p["taux"].items(): | ||||
| 84 | + assert p["valeurs"][k] == pytest.approx(fin.capitalisation_directe(p["rne"], R_)) and p["par_logement"][k] == pytest.approx(p["valeurs"][k] / 36) | ||||
| 85 | + assert p["taux"]["montreal_cas3_mediane"] == pytest.approx(0.04415, abs=1e-6) and p["valeurs"]["montreal_cas3_mediane"] == pytest.approx(8_308_041, abs=1) | ||||
| 86 | + assert p["taux"]["gatineau_pondere"] == pytest.approx(0.054359, abs=1e-5) and p["valeurs"]["gatineau_pondere"] == pytest.approx(6_747_739, abs=1) | ||||
| 87 | + assert p["taux"]["gatineau_median"] == pytest.approx(0.0571, abs=1e-6) and p["valeurs"]["gatineau_median"] == pytest.approx(6_423_818, abs=1) | ||||
| 88 | + assert p["taux"]["regression_sujet"] == pytest.approx(0.054611, abs=1e-5) and p["valeurs"]["regression_sujet"] == pytest.approx(6_716_534, abs=1) | ||||
| 89 | + assert p["taux"]["regression_si_montreal"] == pytest.approx(0.045654, abs=1e-5) and p["valeurs"]["regression_si_montreal"] == pytest.approx(8_034_343, abs=1) | ||||
| 90 | + assert p["taux"]["regression_si_12_logements"] == pytest.approx(0.056536, abs=1e-5) and p["valeurs"]["regression_si_12_logements"] == pytest.approx(6_487_875, abs=1) | ||||
| 91 | + assert p["taux"]["regression_si_etat_3"] == pytest.approx(0.052452, abs=1e-5) and p["valeurs"]["regression_si_etat_3"] == pytest.approx(6_993_820, abs=1) | ||||
| 92 | + assert p["valeur_fichier"] == 7_186_000 and p["valeur_fichier_par_logement"] == pytest.approx(199_611, abs=1) | ||||
| 93 | + assert p["ecart_montreal_vs_sujet"] == pytest.approx(0.237, abs=1e-3) | ||||
| 94 | + d = p["decomposition"] | ||||
| 95 | + assert d["effet_taille_pb"] == pytest.approx(-16.1, abs=0.1) and d["effet_rmr_pb"] == pytest.approx(89.6, abs=0.1) | ||||
| 96 | + # décomposition multiplicative exacte : R_sujet = R_mtl12 × (1 + effet taille) × (1 + effet RMR) | ||||
| 97 | + r12 = d["regression_montreal_12_log_etat2_age72"] | ||||
| 98 | + assert r12 + d["effet_taille_pb"] / 1e4 + d["effet_rmr_pb"] / 1e4 == pytest.approx(p["taux"]["regression_sujet"], abs=1e-9) | ||||
| 99 | + reg = p["regression"]; assert reg["n"] == 48 and reg["r2"] == pytest.approx(0.883, abs=1e-3) and reg["duan"] == pytest.approx(1.0011, abs=1e-4) | ||||
| 100 | + f = p["financement"] | ||||
| 101 | + assert f["service_dette"] == pytest.approx(fin.Hypotheque(5_416_000, 0.0517, 480).service_dette_annuel) and f["rcd"] == pytest.approx(366_800 / f["service_dette"]) | ||||
| 102 | + assert f["rcd"] == pytest.approx(1.15, abs=0.01) and f["rpv_fichier"] == pytest.approx(0.7537, abs=1e-4) | ||||
| 103 | + | ||||
| 104 | +# ----------------------------------------------------------------------------- sensibilité | ||||
| 105 | + | ||||
| 106 | +def test_sensibilite(R): | ||||
| 107 | + s = R["sensibilite"]; p = R["p45"] | ||||
| 108 | + G, T = s["grille_valeur_par_logement"], s["grille_taux"] | ||||
| 109 | + assert G.shape == (5, 6) and (G.values > 0).all() | ||||
| 110 | + assert G.loc["état 2", "Gatineau"] == pytest.approx(p["par_logement"]["regression_sujet"]) and T.loc["état 2", "Gatineau"] == pytest.approx(p["taux"]["regression_sujet"]) | ||||
| 111 | + assert (np.diff(T.values, axis=0) < 0).all() # un meilleur état abaisse le taux | ||||
| 112 | + assert (T["Montréal"] < T[["Québec", "Gatineau", "Sherbrooke", "Trois-Rivières", "Saguenay"]].min(axis=1)).all() # Montréal toujours le plus bas | ||||
| 113 | + c = s["courbe_taille"]; assert (np.diff(c["taux_gatineau"]) < 0).all() and c.loc[c["n"] == 36, "taux_gatineau"].iloc[0] == pytest.approx(p["taux"]["regression_sujet"]) | ||||
| 114 | + pb = s["taux_pb"].set_index("delta_pb") | ||||
| 115 | + assert pb.loc[0, "valeur"] == pytest.approx(p["valeurs"]["regression_sujet"]) and pb.loc[25, "variation_pct"] == pytest.approx(s["variation_25pb_pct"]) | ||||
| 116 | + assert s["variation_25pb_pct"] == pytest.approx(-0.0438, abs=1e-4) and pb.loc[-25, "variation_pct"] == pytest.approx(0.0480, abs=1e-4) | ||||
| 117 | + # élasticité dV/V = -dR/R en petite variation | ||||
| 118 | + R0 = p["taux"]["regression_sujet"]; assert (pb.loc[25, "valeur"] - pb.loc[-25, "valeur"]) / (50e-4) / pb.loc[0, "valeur"] == pytest.approx(-1 / R0, rel=0.01) | ||||
| 119 | + | ||||
| 120 | +# ----------------------------------------------------------------------------- exercices | ||||
| 121 | + | ||||
| 122 | +def test_exercices(R): | ||||
| 123 | + ex = R["exercices"] | ||||
| 124 | + assert ex["ex1"]["par_logement"] == pytest.approx(2_746_667, abs=1) and ex["ex1"]["par_m2"] == pytest.approx(2_596_848, abs=1) and ex["ex1"]["par_chambre"] == pytest.approx(2_434_545, abs=1) | ||||
| 125 | + assert ex["ex1"]["ecart_max_pct"] == pytest.approx(0.1282, abs=1e-4) | ||||
| 126 | + assert ex["ex2"]["taxe_5"] == pytest.approx(16_340.20, abs=0.01) and ex["ex2"]["taxe_6"] == pytest.approx(17_340.60, abs=0.01) | ||||
| 127 | + assert ex["ex2"]["ecart_taux_seul"] == pytest.approx(419.40, abs=0.01) and ex["ex2"]["ecart_total"] == pytest.approx(1_000.40, abs=0.01) and ex["ex2"]["effet_valeur_a_5pct"] == pytest.approx(7_625.45, abs=0.01) | ||||
| 128 | + assert ex["ex3"]["R36"] == pytest.approx(ex["ex3"]["R12"] - 54.592e-4, abs=1e-7) and ex["ex3"]["prime_pct"] == pytest.approx(0.1358, abs=1e-4) | ||||
| 129 | + assert ex["ex3"]["valeur_par_logement_12"] == pytest.approx(164_141, abs=1) and ex["ex3"]["valeur_par_logement_36"] == pytest.approx(186_426, abs=1) | ||||
| 130 | + assert ex["ex4"]["ecart"] == pytest.approx(1_591_507, abs=1) and ex["ex4"]["ecart_pct"] == pytest.approx(0.237, abs=1e-3) | ||||
| 131 | + assert ex["ex5"]["delta_rbp"] == 5_760 and ex["ex5"]["delta_rne"] == pytest.approx(5_319.48, abs=0.01) and ex["ex5"]["delta_valeur"] == pytest.approx(97_406, abs=1) and ex["ex5"]["delta_valeur_pct"] == pytest.approx(0.0145, abs=1e-4) | ||||
| 132 | + e6 = ex["ex6"]["par_rmr"] | ||||
| 133 | + assert e6["Montréal"]["taux"] == pytest.approx(0.0452, abs=1e-4) and e6["Trois-Rivières"]["taux"] == pytest.approx(0.0634, abs=1e-4) | ||||
| 134 | + assert e6["Gatineau"]["ic_lo"] < e6["Gatineau"]["effet_pct"] < e6["Gatineau"]["ic_hi"] and e6["Gatineau"]["effet_pct"] == pytest.approx(0.1962, abs=1e-4) | ||||
| 135 | + e7 = ex["ex7"] | ||||
| 136 | + assert e7["cout_2026"] == pytest.approx(6_988_800) and e7["cout_total"] == pytest.approx(8_088_800) and e7["rne"] == pytest.approx(365_124.10, abs=0.01) | ||||
| 137 | + assert e7["V_450"] == pytest.approx(8_113_869, abs=1) and e7["V_475"] == pytest.approx(7_686_823, abs=1) and e7["taux_implicite_cout"] == pytest.approx(0.0451, abs=1e-4) | ||||
modified
assets/figures/ch19/ch19-fig-carte-residus.pdf
+0 −0
Binary file not shown.
modified
assets/figures/ch19/ch19-fig-correlogramme.pdf
+0 −0
Binary file not shown.
modified
assets/figures/ch19/ch19-fig-gwr-bande.pdf
+0 −0
Binary file not shown.
modified
assets/figures/ch19/ch19-fig-gwr-coefficients.pdf
+0 −0
Binary file not shown.
modified
assets/figures/ch19/ch19-fig-krigeage.pdf
+0 −0
Binary file not shown.
modified
assets/figures/ch19/ch19-fig-sensibilite-W.pdf
+0 −0
Binary file not shown.
modified
assets/figures/ch19/ch19-fig-variogramme.pdf
+0 −0
Binary file not shown.
modified
assets/figures/ch25/ch25-fig-carte-terrains.pdf
+0 −0
Binary file not shown.
modified
assets/figures/ch25/ch25-fig-lotissement.pdf
+0 −0
Binary file not shown.
modified
assets/figures/ch25/ch25-fig-residuelle-sensibilite.pdf
+0 −0
Binary file not shown.
modified
assets/figures/ch25/ch25-fig-valeur-unitaire-superficie.pdf
+0 −0
Binary file not shown.
modified
assets/figures/ch28/ch28-fig-cascade.pdf
+0 −0
Binary file not shown.
modified
assets/figures/ch28/ch28-fig-evolution.pdf
+0 −0
Binary file not shown.
modified
assets/figures/ch28/ch28-fig-ratio-loyer.pdf
+0 −0
Binary file not shown.
modified
assets/figures/ch28/ch28-fig-sensibilite.pdf
+0 −0
Binary file not shown.
modified
assets/figures/ch28/ch28-fig-structure.pdf
+0 −0
Binary file not shown.
added
assets/figures/ch33/ch33-fig-p45-sensibilite.pdf
+0 −0
Binary file not shown.
added
assets/figures/ch33/ch33-fig-rmr.pdf
+0 −0
Binary file not shown.
added
assets/figures/ch33/ch33-fig-schl-typologie.pdf
+0 −0
Binary file not shown.
added
assets/figures/ch33/ch33-fig-taux-taille.pdf
+0 −0
Binary file not shown.
deleted
manuscript/_wrap_ch19.tex
+0 −12
@@ -1,12 +0,0 @@ | |||||
| 1 | −\providecommand{\BUILDVARIANT}{uqo}\providecommand{\BUILDMEDIA}{numerique} | ||||
| 2 | −\documentclass[10pt,twoside,openright]{book} | ||||
| 3 | −\newif\ifLogoAutorise\LogoAutorisefalse\def\PALETTE{uqo} | ||||
| 4 | −\usepackage{traite-qc} | ||||
| 5 | −\input{../manuscript/frontmatter/metadata.tex} | ||||
| 6 | −\input{/Users/simon-pierreboucher/Desktop/UQO/Traite-Evaluation-QC/build/ch19/_labels.tex} | ||||
| 7 | −\begin{document} | ||||
| 8 | −\setcounter{chapter}{18} | ||||
| 9 | −\input{chapters/ch19.tex} | ||||
| 10 | −\appendix\chapter{Solutions du chapitre}\input{../solutions/ch19.tex} | ||||
| 11 | −\printbibliography | ||||
| 12 | −\end{document} | ||||
modified
manuscript/chapters/ch13.tex
+18 −18
@@ -31,7 +31,7 @@ Une \emph{donnée officielle} est produite par un organisme public ou parapublic | |||||
| 31 | Le \cref{tab:13:inventaire} dresse l'inventaire des sources effectivement vérifiées pour cet ouvrage ; le \cref{tab:13:acces} en donne les conditions d'accès, la licence, le coût et l'adresse consultée. Les deux tableaux se lisent ensemble. La colonne « type » applique la distinction de la \cref{def:officielle} : [O] pour une donnée officielle, [I] pour une donnée d'industrie. Toutes les adresses ont été consultées le 31 octobre 2026 ; la date figure parce qu'une adresse ou une licence peut changer et qu'un rapport d'évaluation doit permettre au lecteur de retrouver ce que l'évaluateur a vu. | 31 | Le \cref{tab:13:inventaire} dresse l'inventaire des sources effectivement vérifiées pour cet ouvrage ; le \cref{tab:13:acces} en donne les conditions d'accès, la licence, le coût et l'adresse consultée. Les deux tableaux se lisent ensemble. La colonne « type » applique la distinction de la \cref{def:officielle} : [O] pour une donnée officielle, [I] pour une donnée d'industrie. Toutes les adresses ont été consultées le 31 octobre 2026 ; la date figure parce qu'une adresse ou une licence peut changer et qu'un rapport d'évaluation doit permettre au lecteur de retrouver ce que l'évaluateur a vu. | ||
| 32 | 32 | ||||
| 33 | \begin{footnotesize} | 33 | \begin{footnotesize} | ||
| 34 | −\begin{longtable}{@{}L{34mm}L{52mm}L{22mm}c@{}} | 34 | +\begin{longtable}{@{}L{32mm}L{52mm}L{22mm}c@{}} | ||
| 35 | \caption{Inventaire des sources de données utiles à l'évaluation résidentielle et multirésidentielle au Québec : contenu, couverture et périodicité (état au 31 octobre 2026)}\label{tab:13:inventaire}\\ | 35 | \caption{Inventaire des sources de données utiles à l'évaluation résidentielle et multirésidentielle au Québec : contenu, couverture et périodicité (état au 31 octobre 2026)}\label{tab:13:inventaire}\\ | ||
| 36 | \toprule | 36 | \toprule | ||
| 37 | Source (organisme) & Contenu et couverture & Périodicité & Type \\ | 37 | Source (organisme) & Contenu et couverture & Périodicité & Type \\ | ||
@@ -72,8 +72,8 @@ Bureau d'assurance du Canada (Infoassurance) & Prime moyenne d'assurance habitat | |||||
| 72 | \end{longtable} | 72 | \end{longtable} | ||
| 73 | \end{footnotesize} | 73 | \end{footnotesize} | ||
| 74 | 74 | ||||
| 75 | −\begin{footnotesize} | 75 | +\begingroup\footnotesize\urlstyle{same}\renewcommand{\UrlBreaks}{\do\/\do\-\do\.\do\_\do\?\do\=\do\&\do\a\do\b\do\c\do\d\do\e\do\f\do\g\do\h\do\i\do\j\do\k\do\l\do\m\do\n\do\o\do\p\do\q\do\r\do\s\do\t\do\u\do\v\do\w\do\x\do\y\do\z} | ||
| 76 | −\begin{longtable}{@{}L{30mm}L{36mm}L{26mm}L{44mm}@{}} | 76 | +\begin{longtable}{@{}L{25mm}L{33mm}L{25mm}L{39mm}@{}} | ||
| 77 | \caption{Accès, licence, coût et adresse consultée pour les sources du \cref{tab:13:inventaire} (consultation du 31 octobre 2026)}\label{tab:13:acces}\\ | 77 | \caption{Accès, licence, coût et adresse consultée pour les sources du \cref{tab:13:inventaire} (consultation du 31 octobre 2026)}\label{tab:13:acces}\\ | ||
| 78 | \toprule | 78 | \toprule | ||
| 79 | Source & Accès et coût & Licence & Adresse consultée \\ | 79 | Source & Accès et coût & Licence & Adresse consultée \\ | ||
@@ -102,7 +102,7 @@ Teranet--Banque Nationale & Communiqué mensuel PDF gratuit (adresse réutilisé | |||||
| 102 | CBRE & Rapport PDF sur inscription ; gratuit & Droit d'auteur ; valeurs ponctuelles citées avec attribution & \url{https://www.cbre.ca/insights/reports/canada-cap-rates-investment-insights-q3-2026} \\ | 102 | CBRE & Rapport PDF sur inscription ; gratuit & Droit d'auteur ; valeurs ponctuelles citées avec attribution & \url{https://www.cbre.ca/insights/reports/canada-cap-rates-investment-insights-q3-2026} \\ | ||
| 103 | Altus, Marshall \& Swift, RSMeans & Abonnement ou achat ; tableaux protégés & Droit d'auteur ; aucune reproduction sans licence & \url{https://www.altusgroup.com/featured-insights/canadian-cost-guide/} \\ | 103 | Altus, Marshall \& Swift, RSMeans & Abonnement ou achat ; tableaux protégés & Droit d'auteur ; aucune reproduction sans licence & \url{https://www.altusgroup.com/featured-insights/canadian-cost-guide/} \\ | ||
| 104 | \end{longtable} | 104 | \end{longtable} | ||
| 105 | −\end{footnotesize} | 105 | +\endgroup | ||
| 106 | 106 | ||||
| 107 | \subsection{Les registres : registre foncier, rôle d'évaluation, permis} | 107 | \subsection{Les registres : registre foncier, rôle d'évaluation, permis} | ||
| 108 | 108 | ||||
@@ -157,7 +157,7 @@ Une vente résidentielle laisse au moins trois traces documentaires, et l'évalu | |||||
| 157 | \begin{table}[tbp] | 157 | \begin{table}[tbp] | ||
| 158 | \caption{Champs d'une transaction résidentielle et sources qui les fournissent au Québec (\checkmark~: champ présent ; (\checkmark)~: présent mais déclaratif ou partiel)}\label{tab:13:champs} | 158 | \caption{Champs d'une transaction résidentielle et sources qui les fournissent au Québec (\checkmark~: champ présent ; (\checkmark)~: présent mais déclaratif ou partiel)}\label{tab:13:champs} | ||
| 159 | \centering\small | 159 | \centering\small | ||
| 160 | −\begin{tabularx}{\textwidth}{@{}Yccc@{}} | 160 | +\begin{tabularx}{\textwidth}{@{}YL{22mm}L{30mm}L{27mm}@{}} | ||
| 161 | \toprule | 161 | \toprule | ||
| 162 | Champ & Acte publié (registre foncier) & Fiche de courtage et déclarations du vendeur & Rôle (format ouvert) \\ | 162 | Champ & Acte publié (registre foncier) & Fiche de courtage et déclarations du vendeur & Rôle (format ouvert) \\ | ||
| 163 | \midrule | 163 | \midrule | ||
@@ -283,7 +283,7 @@ où $U_t$ est l'univers et $v_t$ le taux. L'\cref{eq:13:vacants} rappelle qu'un | |||||
| 283 | 283 | ||||
| 284 | \begin{table}[tbp] | 284 | \begin{table}[tbp] | ||
| 285 | \caption{Enquête sur les logements locatifs de la SCHL, octobre 2025 : six RMR du Québec, appartements d'initiative privée dans les immeubles de trois logements et plus. Lettres : indicateur de qualité de la SCHL (a excellent … d passable).}\label{tab:13:schl} | 285 | \caption{Enquête sur les logements locatifs de la SCHL, octobre 2025 : six RMR du Québec, appartements d'initiative privée dans les immeubles de trois logements et plus. Lettres : indicateur de qualité de la SCHL (a excellent … d passable).}\label{tab:13:schl} | ||
| 286 | −\centering\footnotesize\setlength{\tabcolsep}{3.5pt} | 286 | +\centering\scriptsize\setlength{\tabcolsep}{2.2pt} | ||
| 287 | \begin{tabular}{@{}l S[table-format=1.1] S[table-format=1.1] c S[table-format=4.0] S[table-format=4.0] c S[table-format=6.0] S[table-format=2.1] S[table-format=2.1] S[table-format=5.0]@{}} | 287 | \begin{tabular}{@{}l S[table-format=1.1] S[table-format=1.1] c S[table-format=4.0] S[table-format=4.0] c S[table-format=6.0] S[table-format=2.1] S[table-format=2.1] S[table-format=5.0]@{}} | ||
| 288 | \toprule | 288 | \toprule | ||
| 289 | & \multicolumn{3}{c}{Inoccupation, tous (\%)} & \multicolumn{3}{c}{Loyer moyen, 2 ch. (\$)} & {Univers} & \multicolumn{2}{c}{Var. loyer 2 ch. (\%)} & {Vacants} \\ | 289 | & \multicolumn{3}{c}{Inoccupation, tous (\%)} & \multicolumn{3}{c}{Loyer moyen, 2 ch. (\$)} & {Univers} & \multicolumn{2}{c}{Var. loyer 2 ch. (\%)} & {Vacants} \\ | ||
@@ -292,7 +292,7 @@ RMR & {2024} & {2025} & {Q} & {2024} & {2025} & {Q} & {tous, 2025} & {brute} & { | |||||
| 292 | \midrule | 292 | \midrule | ||
| 293 | Montréal & 2.1 & 2.9 & a & 1176 & 1346 & a & 667266 & 14.5 & 7.2 & 19351 \\ | 293 | Montréal & 2.1 & 2.9 & a & 1176 & 1346 & a & 667266 & 14.5 & 7.2 & 19351 \\ | ||
| 294 | Québec & 0.9 & 2.4 & a & 1159 & 1277 & a & 118693 & 10.2 & 6.1 & 2849 \\ | 294 | Québec & 0.9 & 2.4 & a & 1159 & 1277 & a & 118693 & 10.2 & 6.1 & 2849 \\ | ||
| 295 | −Gatineau (partie Québec) & 1.9 & 3.8 & c & 1353 & 1460 & a & 33553 & 7.9 & 4.7 & 1275 \\ | 295 | +Gatineau (partie Qc) & 1.9 & 3.8 & c & 1353 & 1460 & a & 33553 & 7.9 & 4.7 & 1275 \\ | ||
| 296 | Sherbrooke & 1.4 & 2.7 & a & 1002 & 1062 & a & 41949 & 6.0 & 9.8 & 1133 \\ | 296 | Sherbrooke & 1.4 & 2.7 & a & 1002 & 1062 & a & 41949 & 6.0 & 9.8 & 1133 \\ | ||
| 297 | Trois-Rivières & 0.9 & 2.7 & b & 885 & 1016 & a & 22505 & 14.8 & 6.6 & 608 \\ | 297 | Trois-Rivières & 0.9 & 2.7 & b & 885 & 1016 & a & 22505 & 14.8 & 6.6 & 608 \\ | ||
| 298 | Saguenay & 1.6 & 1.3 & a & 882 & 985 & a & 16241 & 11.7 & 10.9 & 211 \\ | 298 | Saguenay & 1.6 & 1.3 & a & 882 & 985 & a & 16241 & 11.7 & 10.9 & 211 \\ | ||
@@ -381,12 +381,12 @@ Les sections précédentes ont décrit des sources hétérogènes par leur conte | |||||
| 381 | \begin{figure}[tbp] | 381 | \begin{figure}[tbp] | ||
| 382 | \centering | 382 | \centering | ||
| 383 | \begin{tikzpicture}[ | 383 | \begin{tikzpicture}[ | ||
| 384 | − node distance=3mm and 6mm, font=\sffamily\footnotesize, | 384 | + node distance=3mm and 5mm, font=\sffamily\footnotesize, | ||
| 385 | − src/.style={draw=brandGray, fill=white, rounded corners=1pt, text width=27mm, minimum height=8mm, align=center, line width=0.5pt}, | 385 | + src/.style={draw=brandGray, fill=white, rounded corners=1pt, text width=23mm, minimum height=8mm, align=center, line width=0.5pt, font=\sffamily\scriptsize}, | ||
| 386 | − etape/.style={draw=brandPrimary, fill=brandLight, rounded corners=1pt, text width=30mm, minimum height=9mm, align=center, line width=0.6pt}, | 386 | + etape/.style={draw=brandPrimary, fill=brandLight, rounded corners=1pt, text width=27mm, minimum height=9mm, align=center, line width=0.6pt}, | ||
| 387 | − base/.style={draw=brandPrimary, fill=brandPrimary, text=white, rounded corners=1pt, text width=30mm, minimum height=9mm, align=center}, | 387 | + base/.style={draw=brandPrimary, fill=brandPrimary, text=white, rounded corners=1pt, text width=27mm, minimum height=9mm, align=center}, | ||
| 388 | − usage/.style={draw=brandDark, fill=white, rounded corners=1pt, text width=27mm, minimum height=8mm, align=center, line width=0.5pt}, | 388 | + usage/.style={draw=brandDark, fill=white, rounded corners=1pt, text width=23mm, minimum height=8mm, align=center, line width=0.5pt, font=\sffamily\scriptsize}, | ||
| 389 | − meta/.style={draw=brandAmber, dashed, fill=orange!5!white, rounded corners=1pt, text width=30mm, align=center, font=\sffamily\scriptsize}, | 389 | + meta/.style={draw=brandAmber, dashed, fill=orange!5!white, rounded corners=1pt, text width=27mm, align=center, font=\sffamily\scriptsize}, | ||
| 390 | fl/.style={-{Stealth[length=1.8mm]}, brandGray, line width=0.6pt}] | 390 | fl/.style={-{Stealth[length=1.8mm]}, brandGray, line width=0.6pt}] | ||
| 391 | \node[src] (s1) {Registre foncier\\ actes, index [O]}; | 391 | \node[src] (s1) {Registre foncier\\ actes, index [O]}; | ||
| 392 | \node[src, below=of s1] (s2) {Rôle d'évaluation\\ XML MAMH [O]}; | 392 | \node[src, below=of s1] (s2) {Rôle d'évaluation\\ XML MAMH [O]}; | ||
@@ -442,10 +442,10 @@ Une base n'est utilisable dans un rapport que si l'on peut dire, pour chaque chi | |||||
| 442 | 442 | ||||
| 443 | \section{Exemple intégral : lire quatre fichiers réels par script}\label{sec:13:exemple} | 443 | \section{Exemple intégral : lire quatre fichiers réels par script}\label{sec:13:exemple} | ||
| 444 | 444 | ||||
| 445 | −L'exemple qui suit n'utilise aucune donnée synthétique. Il lit, par le script \texttt{analysis/python/cases/ch13\_sources.py}, quatre fichiers réels déposés dans \texttt{data/raw/} avec leur adresse, leur date et leur licence (\texttt{data/raw/SOURCES.md}), et il en tire les chiffres cités dans ce chapitre ; le test \texttt{analysis/python/tests/test\_ch13.py} vérifie chacun d'eux. L'objectif pédagogique est double : montrer qu'une source officielle se lit dans son fichier brut, sans intermédiaire, et montrer ce que la lecture révèle qu'une page Web ne dit pas. | 445 | +L'exemple qui suit n'utilise aucune donnée synthétique. Il lit, par le script de cas du chapitre (\texttt{ch13\_sources.py}, dans \texttt{analysis/python/cases/}), quatre fichiers réels déposés dans le dossier des données brutes du dépôt avec leur adresse, leur date et leur licence (fichier \texttt{SOURCES.md}), et il en tire les chiffres cités dans ce chapitre ; le test \texttt{test\_ch13.py} vérifie chacun d'eux. L'objectif pédagogique est double : montrer qu'une source officielle se lit dans son fichier brut, sans intermédiaire, et montrer ce que la lecture révèle qu'une page Web ne dit pas. | ||
| 446 | 446 | ||||
| 447 | \begin{exemple}{Lecture de l'IPCB, du dictionnaire du rôle, de la richesse foncière uniformisée et de l'Enquête sur les logements locatifs}{13:lecture} | 447 | \begin{exemple}{Lecture de l'IPCB, du dictionnaire du rôle, de la richesse foncière uniformisée et de l'Enquête sur les logements locatifs}{13:lecture} | ||
| 448 | −\emph{Étape 1 : le tableau 18-10-0289-01 de Statistique Canada.} Le fichier \texttt{18100289.csv} est lu avec son séparateur point-virgule et son encodage ; ses \num{318954} lignes sont décrites au \cref{tab:13:ipcb}. La série des bâtiments résidentiels de Montréal, agrégat des divisions (vecteur v1617911460), compte 39 observations du premier trimestre de 2017 au troisième trimestre de 2026 ; elle passe de 65,5 à 117,8, soit un facteur de 1,798, et sa variation sur un an au troisième trimestre de 2026 est de 8,57~\% (108,5 à 117,8). La série équivalente de la RMR de Québec (vecteur v1617911076) ne compte que 15 observations, du premier trimestre de 2023 (98,8) au troisième trimestre de 2026 (124,8), soit un facteur de 1,263 sur quatorze trimestres et une variation annuelle de 9,19~\% ; sur la même période, Montréal passe de 99,9 à 117,8, un facteur de 1,179. Les coûts de construction résidentielle ont donc progressé plus vite à Québec qu'à Montréal depuis 2023, ce qu'un rapport qui indexerait un coût de Québec avec la série de Montréal sous-estimerait d'environ sept points. Le composite des quinze RMR, enfin, ne progresse que de 2,67~\% sur un an au troisième trimestre de 2026, contre 8,6 et 9,2~\% pour les deux RMR québécoises : la hausse récente est un phénomène québécois, non canadien, ce qui rend d'autant plus fautif l'usage d'une série nationale. | 448 | +\emph{Étape 1 : le tableau 18-10-0289-01 de Statistique Canada.} Le fichier \texttt{18100289.csv} est lu avec son séparateur point-virgule et son encodage ; ses \num{318954} lignes sont décrites au \cref{tab:13:ipcb}. La série des bâtiments résidentiels de Montréal, agrégat des divisions (vecteur v1617911460), compte 39 observations du premier trimestre de 2017 au troisième trimestre de 2026 ; elle passe de 65,5 à 117,8, soit un facteur de 1,798, et sa variation sur un an au troisième trimestre de 2026 est de 8,57~\% (108,5 à 117,8). La série équivalente de la RMR de Québec (vecteur v1617911076) ne compte que 15 observations, du premier trimestre de 2023 (98,8) au troisième trimestre de 2026 (124,8), soit un facteur de 1,263 sur quatorze trimestres et une variation annuelle de 9,19~\% ; sur la même période, Montréal passe de 99,9 à 117,8, un facteur de 1,179. Les coûts de construction résidentielle ont donc progressé plus vite à Québec qu'à Montréal depuis 2023, de sorte qu'un rapport qui indexerait un coût de Québec de 2023 avec la série de Montréal le sous-estimerait d'environ 6,6~\%. Le composite des quinze RMR, enfin, ne progresse que de 2,67~\% sur un an au troisième trimestre de 2026, contre 8,6 et 9,2~\% pour les deux RMR québécoises : la hausse récente est un phénomène québécois, non canadien, ce qui rend d'autant plus fautif l'usage d'une série nationale. | ||
| 449 | 449 | ||||
| 450 | \emph{Étape 2 : le dictionnaire du rôle en format ouvert.} Le Répertoire des renseignements prescrits du rôle d'évaluation foncière, version 2.5, est un document de deux pages daté du 24 mars 2022 \parencite{dqrepertoire}. Le script en extrait le texte et y dénombre 62 codes de renseignement distincts, répartis en cinq sections : identification de l'unité d'évaluation (21 codes, dont les dix composantes de l'adresse RL0101Ax à RL0101Jx, le matricule RL0104A à RL0104H, le code d'utilisation prédominante RL0105A et le numéro d'unité de voisinage RL0107A), propriétaire (2 codes conservés après caviardage : date initiale d'inscription et statut aux fins scolaires), caractéristiques de l'unité (17 codes, dont la superficie du terrain RL0302A, l'année de construction RL0307A et son caractère réel ou estimé RL0307B, l'aire d'étages RL0308A et le nombre de logements RL0311A), valeurs au rôle (5 codes : date des conditions du marché RL0401A, valeur du terrain RL0402A, du bâtiment RL0403A, de l'immeuble RL0404A et valeur au rôle antérieur RL0405A) et répartition fiscale (17 codes, dont la mention de terrain vague desservi RL0501A). Vingt-quatre codes portent le suffixe « x », qui signale un renseignement répétitif ; le \cref{tab:13:dico} en donne une sélection avec le type et la taille prescrits. L'index des rôles 2026 compte 1~134 lignes (code géographique, nom du territoire, adresse du fichier XML), et l'adresse du rôle de Gatineau y est \texttt{RL81017\_2026.xml}. Cette lecture dit trois choses au concepteur de base : la section 2 ne permet aucune identification du propriétaire ; l'aire d'étages et l'année de construction sont des renseignements facultatifs (colonne « obligatoirement présent » à N), de sorte qu'ils peuvent manquer ; et les valeurs du terrain et du bâtiment sont elles aussi facultatives, seule la valeur de l'immeuble étant obligatoire. | 450 | \emph{Étape 2 : le dictionnaire du rôle en format ouvert.} Le Répertoire des renseignements prescrits du rôle d'évaluation foncière, version 2.5, est un document de deux pages daté du 24 mars 2022 \parencite{dqrepertoire}. Le script en extrait le texte et y dénombre 62 codes de renseignement distincts, répartis en cinq sections : identification de l'unité d'évaluation (21 codes, dont les dix composantes de l'adresse RL0101Ax à RL0101Jx, le matricule RL0104A à RL0104H, le code d'utilisation prédominante RL0105A et le numéro d'unité de voisinage RL0107A), propriétaire (2 codes conservés après caviardage : date initiale d'inscription et statut aux fins scolaires), caractéristiques de l'unité (17 codes, dont la superficie du terrain RL0302A, l'année de construction RL0307A et son caractère réel ou estimé RL0307B, l'aire d'étages RL0308A et le nombre de logements RL0311A), valeurs au rôle (5 codes : date des conditions du marché RL0401A, valeur du terrain RL0402A, du bâtiment RL0403A, de l'immeuble RL0404A et valeur au rôle antérieur RL0405A) et répartition fiscale (17 codes, dont la mention de terrain vague desservi RL0501A). Vingt-quatre codes portent le suffixe « x », qui signale un renseignement répétitif ; le \cref{tab:13:dico} en donne une sélection avec le type et la taille prescrits. L'index des rôles 2026 compte 1~134 lignes (code géographique, nom du territoire, adresse du fichier XML), et l'adresse du rôle de Gatineau y est \texttt{RL81017\_2026.xml}. Cette lecture dit trois choses au concepteur de base : la section 2 ne permet aucune identification du propriétaire ; l'aire d'étages et l'année de construction sont des renseignements facultatifs (colonne « obligatoirement présent » à N), de sorte qu'ils peuvent manquer ; et les valeurs du terrain et du bâtiment sont elles aussi facultatives, seule la valeur de l'immeuble étant obligatoire. | ||
| 451 | 451 | ||||
@@ -457,9 +457,9 @@ L'exemple qui suit n'utilise aucune donnée synthétique. Il lit, par le script | |||||
| 457 | \begin{table}[tbp] | 457 | \begin{table}[tbp] | ||
| 458 | \caption{Extrait du Répertoire des renseignements prescrits du rôle d'évaluation foncière en format ouvert (version 2.5) : renseignements les plus utiles à l'évaluateur}\label{tab:13:dico} | 458 | \caption{Extrait du Répertoire des renseignements prescrits du rôle d'évaluation foncière en format ouvert (version 2.5) : renseignements les plus utiles à l'évaluateur}\label{tab:13:dico} | ||
| 459 | \centering\footnotesize | 459 | \centering\footnotesize | ||
| 460 | −\begin{tabular}{@{}l L{72mm} c l c@{}} | 460 | +\begin{tabular}{@{}l L{55mm} c L{24mm} c@{}} | ||
| 461 | \toprule | 461 | \toprule | ||
| 462 | −Code & Renseignement & Obligatoire & Type et taille & Section \\ | 462 | +Code & Renseignement & {Oblig.} & Type et taille & Sect. \\ | ||
| 463 | \midrule | 463 | \midrule | ||
| 464 | RL0101Gx & Nom de la voie publique de l'adresse & O & caractère 75 & 1 \\ | 464 | RL0101Gx & Nom de la voie publique de l'adresse & O & caractère 75 & 1 \\ | ||
| 465 | RL0104A--C & Matricule : division, section, emplacement & O & caractère 4, 2, 4 & 1 \\ | 465 | RL0104A--C & Matricule : division, section, emplacement & O & caractère 4, 2, 4 & 1 \\ | ||
@@ -514,7 +514,7 @@ Deux conventions de lecture des données, parmi celles exposées dans ce chapitr | |||||
| 514 | \figsource{calcul analytique, script \texttt{analysis/python/figures/ch13\_biais\_datation.py} ; la plage de croissances est illustrative.} | 514 | \figsource{calcul analytique, script \texttt{analysis/python/figures/ch13\_biais\_datation.py} ; la plage de croissances est illustrative.} | ||
| 515 | \end{figure} | 515 | \end{figure} | ||
| 516 | 516 | ||||
| 517 | −La seconde sensibilité est celle de la définition de la variation d'un loyer, mesurée sur les données réelles du \cref{tab:13:schl}. Un évaluateur qui indexe le loyer de marché d'un logement de deux chambres à Montréal d'octobre 2024 à octobre 2025 avec la variation brute du loyer moyen l'augmente de 14,5~\% ; avec la variation estimative, de 7,2~\%. Sur un loyer de \dollars{1300}, l'écart est de 95~\$ par mois, soit \dollars{1140} par année et par logement ; sur un immeuble de douze logements capitalisé à 4,5~\%, il représente près de \dollars{300000} de valeur. L'effet de composition est aussi grand à Trois-Rivières et il change de signe à Sherbrooke. Il n'y a pas ici de « bonne » définition dans l'absolu : la variation estimative mesure l'évolution du loyer d'un logement donné et convient à l'indexation d'un loyer de marché ; la variation brute mesure l'évolution du loyer moyen du parc et convient à l'analyse des revenus agrégés. L'erreur est de prendre l'une pour l'autre, et elle est fréquente parce que les communiqués publient la première et que les tableaux donnent les niveaux dont on déduit la seconde. | 517 | +La seconde sensibilité est celle de la définition de la variation d'un loyer, mesurée sur les données réelles du \cref{tab:13:schl}. Un évaluateur qui indexe le loyer de marché d'un logement de deux chambres à Montréal d'octobre 2024 à octobre 2025 avec la variation brute du loyer moyen l'augmente de 14,5~\% ; avec la variation estimative, de 7,2~\%. Sur un loyer de \dollars{1300}, l'écart est de 94~\$ par mois, soit \dollars{1132} par année et par logement ; sur un immeuble de douze logements capitalisé à 4,5~\%, il représente environ \dollars{300000} de valeur. L'effet de composition est aussi grand à Trois-Rivières et il change de signe à Sherbrooke. Il n'y a pas ici de « bonne » définition dans l'absolu : la variation estimative mesure l'évolution du loyer d'un logement donné et convient à l'indexation d'un loyer de marché ; la variation brute mesure l'évolution du loyer moyen du parc et convient à l'analyse des revenus agrégés. L'erreur est de prendre l'une pour l'autre, et elle est fréquente parce que les communiqués publient la première et que les tableaux donnent les niveaux dont on déduit la seconde. | ||
| 518 | 518 | ||||
| 519 | \begin{erreurs} | 519 | \begin{erreurs} | ||
| 520 | \begin{itemize} | 520 | \begin{itemize} | ||
modified
manuscript/chapters/ch14.tex
+528 −1
@@ -1,2 +1,529 @@ | |||||
| 1 | \chapter{Nettoyage, géocodage et qualité des données}\label{ch:14} | 1 | \chapter{Nettoyage, géocodage et qualité des données}\label{ch:14} | ||
| 2 | −\stubchapter | 2 | + | ||
| 3 | +Les méthodes des parties IV à VII supposent toutes une chose que le \cref{ch:13} a montrée fragile : que les ventes, les loyers et les attributs dont on dispose décrivent fidèlement des transactions sincères entre parties informées. Or une base de données immobilières, qu'elle provienne du registre foncier, d'un système de courtage ou d'un rôle d'évaluation, contient toujours des inscriptions en double, des prix qui ne sont pas des prix de marché, des superficies saisies dans la mauvaise unité, des dates permutées, des coordonnées impossibles et des champs vides. Laisser ces anomalies en place ne produit pas une estimation « un peu moins précise » : une poignée de ventes à un dollar suffit à réduire à néant le pouvoir explicatif d'un modèle hédonique estimé sur six cents observations, et une vente entre personnes liées glissée parmi cinq comparables déplace l'indication de valeur de plusieurs dizaines de milliers de dollars. Le présent chapitre traite le nettoyage comme une étape méthodologique à part entière, avec ses règles, ses statistiques, ses diagnostics et son journal, plutôt que comme une corvée préalable. Il construit, à partir du jeu propre du cas 1, un jeu « brut » dans lequel des anomalies de chaque type ont été injectées selon des lois déclarées, puis il montre comment une chaîne de traitement reproductible les détecte, les corrige ou les exclut, et dans quelle mesure le modèle hédonique de référence du \cref{ch:18} est retrouvé. Il traite ensuite du géocodage des adresses, de l'appariement des transactions avec le rôle d'évaluation et de l'imputation des valeurs manquantes, avant de conclure sur ce que la reproductibilité exige de l'évaluateur. | ||||
| 4 | + | ||||
| 5 | +\begin{objectifs} | ||||
| 6 | +À la fin de ce chapitre, le lecteur sait : | ||||
| 7 | +\begin{itemize} | ||||
| 8 | +\item distinguer une erreur de saisie, une transaction non représentative, une valeur aberrante et une observation influente, et mesurer l'effet de chacune sur un estimateur ; | ||||
| 9 | +\item écrire des règles déterministes de validation (doublons, unités, dates, prix symboliques, coordonnées, conditions de vente) qui corrigent ce qui peut l'être et excluent le reste, en journalisant chaque décision ; | ||||
| 10 | +\item calculer et interpréter le score robuste fondé sur la médiane et l'écart absolu médian, comprendre pourquoi il résiste au masquage et choisir son seuil ; | ||||
| 11 | +\item dériver le levier, le résidu studentisé et la distance de Cook d'une régression et s'en servir pour repérer les ventes qui ne se conforment pas au marché sans « nettoyer vers le modèle » ; | ||||
| 12 | +\item décrire les sources québécoises de géocodage et la hiérarchie de précision des techniques, puis quantifier l'effet d'une erreur de position sur les variables de distance et de voisinage ; | ||||
| 13 | +\item apparier des transactions au rôle d'évaluation par clé exacte, par clé normalisée et par concordance d'attributs, et mesurer le taux d'appariement ; | ||||
| 14 | +\item traiter les valeurs manquantes par suppression, médiane conditionnelle, régression ou indicateur, en explicitant l'hypothèse sur le mécanisme de manque ; | ||||
| 15 | +\item tenir un journal d'exclusions et fixer graine, versions et seuils pour qu'un tiers reproduise exactement le jeu nettoyé. | ||||
| 16 | +\end{itemize} | ||||
| 17 | +\end{objectifs} | ||||
| 18 | + | ||||
| 19 | +\section{Pourquoi le nettoyage est une étape d'estimation}\label{sec:14:pourquoi} | ||||
| 20 | + | ||||
| 21 | +\subsection{Quatre choses que l'on confond sous le mot « aberrant »} | ||||
| 22 | + | ||||
| 23 | +Le vocabulaire courant range sous une même étiquette des phénomènes qui appellent des traitements différents. Il faut d'abord distinguer l'\motcle{erreur de donnée}, c'est-à-dire une valeur qui ne correspond pas à la réalité de la transaction (une superficie de \num{1776} notée dans un champ en mètres carrés alors qu'elle a été relevée en pieds carrés), de la \motcle{transaction non représentative}, c'est-à-dire une valeur exacte mais qui ne renseigne pas sur la valeur marchande (un prix de \dollars{1} dans un acte qui règle une donation entre conjoints, ou un prix de \dollars{250000} pour une maison cédée par un père à sa fille). La première se corrige quand la règle qui l'a produite est connue ; la seconde s'exclut, ou s'ajuste si l'effet des conditions de vente est mesurable, comme on l'a vu au \cref{ch:16}. Il faut ensuite distinguer la \motcle{valeur aberrante} (\emph{outlier}), observation dont la valeur est éloignée de la masse des autres observations sur une ou plusieurs variables, de l'\motcle{observation influente}, dont la présence modifie sensiblement les résultats d'une estimation. Une maison de \msq{280} vendue \dollars{850000} est aberrante par rapport à des voisines de \msq{130} sans être erronée ni non représentative, et elle peut être très influente dans une régression parce qu'elle tire la pente de la superficie ; à l'inverse, une vente à prix dérisoire au cœur du nuage de points est non représentative et influente sans être aberrante sur aucune variable prise isolément. | ||||
| 24 | + | ||||
| 25 | +\begin{definition}{Anomalie, aberration, influence}{anomalies} | ||||
| 26 | +Dans une base de ventes, on appelle \emph{anomalie} toute inscription dont au moins un champ viole une contrainte de validité (unité, domaine, cohérence interne, unicité) ou dont les conditions de vente ne satisfont pas la définition de la valeur marchande. Une observation est \emph{aberrante} si sa distance au centre de la distribution, mesurée dans une métrique robuste, dépasse un seuil déclaré ; elle est \emph{influente} si l'estimateur calculé sans elle diffère sensiblement de l'estimateur calculé avec elle. Les trois notions sont logiquement indépendantes : une anomalie peut n'être ni aberrante ni influente, et une observation influente peut être parfaitement exacte. | ||||
| 27 | +\end{definition} | ||||
| 28 | + | ||||
| 29 | +Ces distinctions commandent l'ordre des traitements. Les anomalies détectables par une règle, parce qu'elles violent une contrainte connue, se traitent d'abord et sans statistique : il serait absurde de calculer un score robuste sur des prix dont certains sont des prix de meubles compris et d'autres des prix nets. Les aberrations se détectent ensuite, variable par variable, puis conditionnellement au modèle, parce qu'une valeur plausible en soi peut être impossible étant donné les autres caractéristiques du bien. L'influence se mesure en dernier, sur le modèle qui servira effectivement à l'évaluation, et elle ne conduit à l'exclusion que si elle s'accompagne d'une raison, statistique ou documentaire, de croire que l'observation n'appartient pas au marché étudié. \textcite{krauseLipscomb2016} ont proposé un protocole de préparation des données immobilières dont l'esprit est le même : expliciter, dans l'ordre, les règles, les filtres et les décisions, et conserver la trace de chacune. | ||||
| 30 | + | ||||
| 31 | +\subsection{L'effet d'une contamination sur les estimateurs usuels} | ||||
| 32 | + | ||||
| 33 | +Pour comprendre pourquoi quelques anomalies suffisent à ruiner une estimation, considérons le modèle de contamination le plus simple. Une proportion $1 - \varepsilon$ des observations provient de la loi des ventes sincères, de moyenne $\mu$ et d'écart-type $\sigma$ en logarithme du prix, et une proportion $\varepsilon$ provient d'une loi décalée de $\delta$ (par exemple $\delta = \ln 0{,}5 \approx -0{,}693$ pour des ventes conclues à la moitié du marché). L'espérance de la moyenne arithmétique des logarithmes est alors | ||||
| 34 | +\begin{equation}\label{eq:14:contamination} | ||||
| 35 | +\E[\bar y] = (1 - \varepsilon)\,\mu + \varepsilon\,(\mu + \delta) = \mu + \varepsilon\,\delta, | ||||
| 36 | +\end{equation} | ||||
| 37 | +et sa variance par observation passe de $\sigma^2$ à $\sigma^2 + \varepsilon(1-\varepsilon)\delta^2$. Le biais $\varepsilon\delta$ est proportionnel à la part des observations contaminées et à l'ampleur du décalage, sans borne : il suffit d'un $\delta$ assez grand pour qu'une seule observation emporte la moyenne, ce qui est exactement ce que fait un prix de \dollars{1} dont le logarithme vaut zéro au milieu de valeurs proches de treize. On dit que la moyenne a un \motcle{point de rupture} nul. La médiane, au contraire, n'est pas affectée tant que $\varepsilon < 1/2$, quelle que soit l'ampleur du décalage : son point de rupture est de cinquante pour cent, le maximum possible pour un estimateur de position. Les travaux de Hampel sur la fonction d'influence, dans les années 1970, ont donné à cette intuition un cadre général dont la \cref{sec:14:robustes} tire le score robuste. | ||||
| 38 | + | ||||
| 39 | +Les moindres carrés ordinaires héritent de la fragilité de la moyenne, et l'aggravent : chaque observation pèse sur les coefficients en proportion de son résidu \emph{et} de l'éloignement de ses régresseurs, comme le montrera la \cref{sec:14:regression}. Le \cref{tab:14:modeles} de l'exemple intégral en donne la mesure sur le jeu brut du cas 1 : avec cinq prix à \dollars{1} parmi \num{573} lignes complètes, le coefficient de déterminatio\-n du modèle hédonique tombe de 0,853 à 0,039, l'écart-type résiduel passe de 0,083 à 1,231 et l'élasticité du prix à la superficie, qui vaut 0,54 sur le jeu propre, est estimée à 0,20. Un modèle estimé sur des données non nettoyées n'est pas approximativement bon ; il est sans valeur. | ||||
| 40 | + | ||||
| 41 | +\begin{synthetique} | ||||
| 42 | +Le jeu brut de ce chapitre, \texttt{data/synthetic/cas1\_gatineau\_ventes\_brut.csv}, est construit par le script \texttt{analysis/python/cases/ch14\_nettoyage.py} (graine 20261031) à partir des 600 ventes synthétiques du cas 1 (\texttt{cas1\_gatineau\_ventes.csv}, \cref{ch:16}). Le script tire sans remise 109 lignes qu'il altère selon les lois du \cref{tab:14:anomalies}, puis ajoute 18 copies d'inscriptions, ce qui donne 618 inscriptions et 127 anomalies. Il écrit aussi la table de vérité (\texttt{cas1\_gatineau\_anomalies\_injectees.csv}), un extrait de rôle fictif (\texttt{cas1\_gatineau\_role\_extrait.csv}) et, après traitement, le journal d'exclusions (\texttt{cas1\_gatineau\_journal\_exclusions.csv}). Les matricules et les adresses sont fictifs et ne correspondent à aucune unité d'évaluation réelle ; les proportions d'anomalies, environ 18 \% des lignes, sont volontairement élevées pour que chaque mécanisme soit visible et ne mesurent pas la fréquence des anomalies dans une source réelle. Le jeu brut conserve une colonne de traçabilité pédagogique (\texttt{id\_vente\_origine}) qu'un vrai fichier n'aurait pas et que le pipeline ne lit jamais. Les lois sont documentées dans \texttt{data/synthetic/README-brut.md} ; tous les chiffres du chapitre sont imprimés par le script et vérifiés par \texttt{analysis/python/tests/test\_ch14.py}. | ||||
| 43 | +\end{synthetique} | ||||
| 44 | + | ||||
| 45 | +\begin{table}[htbp] | ||||
| 46 | +\caption{Anomalies injectées dans le jeu brut du cas 1 (données synthétiques)}\label{tab:14:anomalies} | ||||
| 47 | +\centering | ||||
| 48 | +\small | ||||
| 49 | +\begin{tabularx}{\textwidth}{lS[table-format=2.0]YY} | ||||
| 50 | +\toprule | ||||
| 51 | +Anomalie & {$n$} & Loi d'injection & Détection attendue \\ | ||||
| 52 | +\midrule | ||||
| 53 | +Doublon d'inscription & 18 & copie intégrale sous un nouvel identifiant ; pour 6 copies, date d'acte décalée de 1 à 3 jours & règle R1 \\ | ||||
| 54 | +Prix symbolique & 5 & prix remplacé par \dollars{1} & règle R4 \\ | ||||
| 55 | +Meubles inclus & 8 & montant de meubles $\sim U(\num{8000};\num{35000})$, arrondi à \dollars{500}, ajouté au prix & règle R3 (correction) \\ | ||||
| 56 | +Superficie en pi\textsuperscript{2} & 12 & superficie habitable multipliée par 10,7639 & règle R5 (correction) \\ | ||||
| 57 | +Dates inversées & 10 & permutation de la date de promesse et de la date d'acte & règle R2 (correction) \\ | ||||
| 58 | +Coordonnées nulles & 9 & latitude et longitude mises à zéro & règle R6, puis géocodage de repli G1 \\ | ||||
| 59 | +Coordonnées hors zone & 6 & signe de la longitude inversé ou latitude et longitude permutées & règle R6, puis G1 \\ | ||||
| 60 | +Vente liée déclarée & 8 & prix multiplié par $U(0{,}40;0{,}60)$ ; champ « type de transaction » renseigné (personnes liées, succession) & règle R7 \\ | ||||
| 61 | +Vente liée non déclarée & 6 & prix multiplié par $U(0{,}40;0{,}60)$ ; champ laissé à « ordinaire » & scores robustes S1 ou régression E1 \\ | ||||
| 62 | +Terrain manquant & 20 & superficie du terrain effacée & imputation I1 \\ | ||||
| 63 | +Qualité manquante & 15 & cote de qualité effacée & imputation I1 \\ | ||||
| 64 | +Année manquante & 10 & année de construction effacée & imputation I1 \\ | ||||
| 65 | +\bottomrule | ||||
| 66 | +\end{tabularx} | ||||
| 67 | +\tabsource{\synth{analysis/python/cases/ch14\_nettoyage.py, graine 20261031 ; lignes tirées sans remise, disjointes}} | ||||
| 68 | +\end{table} | ||||
| 69 | + | ||||
| 70 | +La \cref{fig:14:avant-apres} montre le jeu brut et le jeu nettoyé dans le plan superficie–prix. En échelle logarithmique, les cinq prix symboliques forment une ligne isolée tout en bas du graphique, les douze superficies en pieds carrés une grappe à droite ; les ventes liées, elles, se fondent dans la partie basse du nuage et ne se distinguent pas à l'œil. C'est la raison d'être des sections qui suivent : les anomalies grossières se voient et se règlent par des règles ; les anomalies fines exigent des statistiques conditionnelles. | ||||
| 71 | + | ||||
| 72 | +\begin{figure}[htbp] | ||||
| 73 | +\centering | ||||
| 74 | +\includegraphics[width=\textwidth]{ch14/ch14-fig-avant-apres.pdf} | ||||
| 75 | +\caption{Les 618 inscriptions du jeu brut (à gauche, échelles logarithmiques) et les 579 ventes du jeu nettoyé (à droite). Dans le jeu brut, les inscriptions corrigées par une règle (dates, meubles, unité, coordonnées) et celles qui seront exclues (doublons, prix symboliques, ventes non représentatives, aberrations) sont distinguées ; les prix à un dollar et les superficies saisies en pieds carrés sont immédiatement visibles, les ventes liées ne le sont pas.}\label{fig:14:avant-apres} | ||||
| 76 | +\figsource{\synth{analysis/python/figures/ch14\_figures.py, graine 20261031}} | ||||
| 77 | +\end{figure} | ||||
| 78 | + | ||||
| 79 | +\section{Les règles déterministes}\label{sec:14:regles} | ||||
| 80 | + | ||||
| 81 | +\subsection{Ce qu'une règle peut et ne peut pas faire} | ||||
| 82 | + | ||||
| 83 | +Une \motcle{règle de validation} est un test logique appliqué à chaque inscription, dont le résultat déclenche une action fixée d'avance : corriger, exclure, signaler. Sa force est d'être exacte, reproductible et explicable à un tiers ; sa limite est qu'elle ne détecte que ce qu'elle cherche. Une règle ne devrait corriger une valeur que lorsque le mécanisme de l'erreur est connu et que la correction est univoque : diviser par 10,7639 une superficie habitable de \msq{1776} suppose que l'on sait que cette valeur a été saisie en pieds carrés et non qu'il s'agit d'un manoir de \num{1776} mètres carrés ; dans le marché unifamilial du cas 1, où la plus grande maison du jeu propre mesure \msq{278}, le test « supérieure à \msq{450} et plausible une fois divisée » tranche sans ambiguïté, mais il devrait être reconsidéré pour un marché de propriétés de prestige. Lorsque le mécanisme n'est pas connu, la règle doit exclure ou signaler, jamais deviner. | ||||
| 84 | + | ||||
| 85 | +Le \cref{tab:14:regles} présente les sept règles appliquées au jeu brut du cas 1, dans l'ordre où elles le sont, avec leur effet sur le nombre d'inscriptions. L'ordre n'est pas indifférent. Les dates sont permutées avant que les doublons ne soient recherchés, parce que la clé de dédoublonnage contient la date de promesse ; la contrepartie des meubles est retranchée avant que le prix symbolique ne soit testé, parce qu'un prix de \dollars{15000} après meubles doit être comparé au même seuil que les autres ; l'unité de superficie est corrigée avant tout calcul de prix au mètre carré ; et les conditions de vente déclarées sont examinées en dernier, parce qu'elles excluent des inscriptions dont les autres champs ont pu servir, entre-temps, à repérer un doublon. | ||||
| 86 | + | ||||
| 87 | +\begin{table}[htbp] | ||||
| 88 | +\caption{Règles déterministes appliquées au jeu brut du cas 1 et effet sur le nombre d'inscriptions}\label{tab:14:regles} | ||||
| 89 | +\centering | ||||
| 90 | +\small | ||||
| 91 | +\begin{tabularx}{\textwidth}{lYlS[table-format=2.0]S[table-format=3.0]} | ||||
| 92 | +\toprule | ||||
| 93 | +Règle & Test & Action & {Touchées} & {Conservées} \\ | ||||
| 94 | +\midrule | ||||
| 95 | +{---} & lecture du fichier, typage, suppression des colonnes dérivées & {---} & {---} & 618 \\ | ||||
| 96 | +R2 & date d'acte antérieure à la date de promesse & permutation des deux dates & 10 & 618 \\ | ||||
| 97 | +R1 & même clé d'unité normalisée, même promesse, même prix ; puis mêmes attributs, même promesse, même prix & exclusion ; l'inscription la plus récente est conservée & 18 & 600 \\ | ||||
| 98 | +R3 & montant de meubles non nul & prix net = prix déclaré $-$ meubles & 8 & 600 \\ | ||||
| 99 | +R4 & prix net inférieur à \dollars{5000} & exclusion & 5 & 595 \\ | ||||
| 100 | +R5 & superficie habitable supérieure à \msq{450} et comprise entre 40 et \msq{400} une fois divisée par 10,7639 & division par 10,7639 & 12 & 595 \\ | ||||
| 101 | +R6 & coordonnées nulles ou hors de l'emprise du marché (latitude $45{,}20$--$45{,}80$, longitude $-76{,}10$ à $-75{,}20$) & invalidation, puis géocodage de repli (G1) & 15 & 595 \\ | ||||
| 102 | +R7 & type de transaction déclaré autre qu'ordinaire (personnes liées, succession, reprise) & exclusion & 8 & 587 \\ | ||||
| 103 | +\bottomrule | ||||
| 104 | +\end{tabularx} | ||||
| 105 | +\tabsource{\synth{analysis/python/cases/ch14\_nettoyage.py}} | ||||
| 106 | +\end{table} | ||||
| 107 | + | ||||
| 108 | +\subsection{Les pièges propres aux données de transaction} | ||||
| 109 | + | ||||
| 110 | +Les sept règles répondent à des pièges que le \cref{ch:13} a décrits et qu'il faut maintenant traduire en tests. Le \emph{doublon d'inscription} naît lorsqu'une même vente est saisie deux fois, par exemple parce que l'acte a été réinscrit après une correction ou parce que deux sources ont été fusionnées. La clé naturelle de dédoublonnage est l'unité d'évaluation, identifiée par son matricule, combinée à la date de la promesse et au prix ; mais le matricule est souvent absent ou saisi avec des séparateurs différents, de sorte qu'une seconde passe sur les attributs physiques est nécessaire, comme le montre la règle R1 qui, dans le jeu du cas 1, repère treize doublons par la clé normalisée et cinq autres par les attributs. L'\emph{inversion des dates} tient à la coexistence de deux dates dans toute vente : celle de l'acceptation de la promesse d'achat, qui fixe le prix, et celle de la signature de l'acte notarié, qui le publie. Le \cref{ch:16} a établi que la première est la date pertinente pour les conditions du marché ; une base qui ne contient que la date d'acte doit être corrigée d'un délai typique, et une base qui contient les deux doit vérifier leur ordre. Les \emph{meubles inclus} apparaissent lorsque l'acte déclare un prix global pour l'immeuble et des biens meubles ; la contrepartie attribuée aux meubles, souvent fixée pour des raisons fiscales, doit être retranchée avant toute comparaison, et sa vraisemblance vérifiée. Le \emph{prix symbolique} signale une donation, un transfert entre sociétés liées ou une régularisation de titre ; le seuil de \dollars{5000} retenu ici reprend la convention du règlement sur la proportion médiane, qui écarte des études de ratios les ventes d'un montant inférieur \parencite{reglpropmed}, et il est aussi celui qu'applique JLR dans ses statistiques tirées du registre foncier \parencite{jlr202609}. L'\emph{erreur d'unité} est la plus insidieuse des erreurs de saisie, parce que la valeur erronée est un nombre parfaitement plausible dans l'autre unité ; au Québec, où les fiches de courtage affichent couramment les superficies en pieds carrés et le rôle en mètres carrés, elle est fréquente lors des fusions de sources, et le \cref{ch:12} a montré qu'une erreur de superficie se propage directement à la valeur. Les \emph{coordonnées invalides} proviennent d'un géocodage échoué (zéro par défaut), d'une permutation des colonnes ou d'un signe perdu ; un test d'emprise suffit à les repérer, mais pas à les corriger, ce qui renvoie à la \cref{sec:14:geocodage}. Enfin, les \emph{conditions de vente déclarées} ne sont connues que si la source les enregistre : les déclarations faites dans l'acte aux fins des droits de mutation, l'historique de courtage ou l'entretien avec une partie peuvent révéler un lien entre les parties, une succession, une reprise de finance ; lorsque l'information existe, la règle R7 l'applique, et lorsqu'elle n'existe pas, seules les méthodes statistiques des sections suivantes peuvent repérer la vente. | ||||
| 111 | + | ||||
| 112 | +\begin{quebec}[Les sources québécoises et leurs champs de contrôle] | ||||
| 113 | +Le registre foncier publie l'acte de vente et son prix déclaré, les parties et la date de signature, mais ni la date de la promesse ni les inclusions ; sa consultation est tarifée à l'unité \parencite{registreFoncier}. En évaluation foncière municipale, le Manuel d'évaluation foncière du Québec impose la tenue d'un fichier des mutations immobilières (partie 2A) dont les ventes sont conservées au moins quatre ans, d'un dossier de propriété (2C) et d'un système d'information géographique fondé sur le matricule (2B) \parencite[art.~3--6]{reglrole}, de sorte que les données municipales comportent, par construction, une clé d'unité et une codification des conditions de vente qui facilitent les règles R1 et R7 ; le \cref{ch:09} décrit ce cadre. Le règlement sur la proportion médiane fournit, pour les études de ratios, une épuration codifiée : ventes d'au moins \dollars{5000}, puis retrait des ratios qui s'écartent de plus de deux écarts-types de la moyenne \parencite{reglpropmed}. Les données ouvertes du rôle diffusées par le ministère des Affaires municipales et de l'Habitation (1~140 fichiers XML, licence CC BY 4.0) contiennent les superficies, l'année de construction et les valeurs, mais les cadastres, les noms et les adresses postales des propriétaires y sont caviardés et leur réidentification est interdite \parencite{dqroles} ; elles servent de référence d'attributs, non de source d'adresses. Les statistiques de l'APCIQ et de JLR, enfin, sont diffusées sous des conditions d'utilisation qui exigent l'attribution et interdisent la reproduction des tableaux \parencite{apciqconditions,jlr202609}. Dates de consultation : 31 octobre 2026. | ||||
| 114 | +\end{quebec} | ||||
| 115 | + | ||||
| 116 | +\section{Les scores robustes}\label{sec:14:robustes} | ||||
| 117 | + | ||||
| 118 | +\subsection{Médiane, écart absolu médian et constante de cohérence} | ||||
| 119 | + | ||||
| 120 | +Une fois les règles appliquées, les anomalies restantes sont celles qu'aucune contrainte connue ne détecte : prix trop bas sans déclaration de lien, terrain anormalement petit ou grand pour son secteur, superficie incompatible avec le nombre de pièces. On les cherche d'abord variable par variable, en mesurant l'éloignement de chaque observation au centre de sa distribution. Le score classique $(x_i - \bar x)/s$ est inutilisable à cette fin, pour la raison vue à la \cref{sec:14:pourquoi} : les anomalies que l'on cherche gonflent $s$ et déplacent $\bar x$, de sorte qu'elles se masquent elles-mêmes et masquent leurs voisines. On remplace donc la moyenne par la médiane et l'écart-type par l'\motcle{écart absolu médian} (MAD, \emph{median absolute deviation}), | ||||
| 121 | +\begin{equation}\label{eq:14:mad} | ||||
| 122 | +\mathrm{MAD} = \operatorname{m\acute{e}d}_i \left| x_i - \operatorname{m\acute{e}d}_j x_j \right| , | ||||
| 123 | +\end{equation} | ||||
| 124 | +qui a lui aussi un point de rupture de cinquante pour cent. Le \motcle{score robuste} d'une observation est alors | ||||
| 125 | +\begin{equation}\label{eq:14:zrobuste} | ||||
| 126 | +z_i = \frac{x_i - \operatorname{m\acute{e}d}_j x_j}{1{,}4826\;\mathrm{MAD}} . | ||||
| 127 | +\end{equation} | ||||
| 128 | + | ||||
| 129 | +\begin{proposition}{Constante de cohérence du MAD}{mad} | ||||
| 130 | +Si $X$ suit une loi normale d'écart-type $\sigma$, alors $\E[\mathrm{MAD}] \to \sigma\,\Phi^{-1}(3/4) \approx 0{,}6745\,\sigma$ lorsque $n \to \infty$, de sorte que $1{,}4826\,\mathrm{MAD}$ est un estimateur convergent de $\sigma$ et que le score \eqref{eq:14:zrobuste} se lit, sous normalité, comme un score en unités d'écart-type. | ||||
| 131 | +\end{proposition} | ||||
| 132 | +\begin{proof} | ||||
| 133 | +Pour une loi normale de moyenne $\mu$ et d'écart-type $\sigma$, la médiane est $\mu$ et $|X - \mu|/\sigma$ suit la loi normale repliée, dont la médiane $m$ vérifie $\Pr(|Z| \le m) = 1/2$, soit $2\Phi(m) - 1 = 1/2$ et $m = \Phi^{-1}(3/4) = 0{,}6745$. La médiane empirique des écarts absolus converge vers $0{,}6745\,\sigma$, et $1/0{,}6745 = 1{,}4826$. | ||||
| 134 | +\end{proof} | ||||
| 135 | + | ||||
| 136 | +La constante $1{,}4826$ ne rend pas le score « normal » : elle le rend comparable à un score classique lorsque la masse des données est à peu près normale, ce qui permet d'utiliser les mêmes seuils. Les seuils usuels sont $2{,}5$ (sévère), $3$ (moyen) et $3{,}5$ (tolérant), et le choix dépend du coût relatif d'un faux positif, c'est-à-dire d'une vente sincère écartée, et d'un faux négatif, c'est-à-dire d'une anomalie conservée ; Leys et ses coauteurs, dans une note de 2013 souvent citée, recommandent $2{,}5$ par défaut tout en soulignant que le seuil doit être déclaré avant l'examen des données. Rousseeuw et Croux ont proposé en 1993 des estimateurs d'échelle plus efficaces que le MAD pour des distributions asymétriques ; le MAD reste la référence par sa simplicité et son point de rupture maximal. La règle de Tukey fondée sur l'écart interquartile, qui déclare aberrante toute valeur hors de $[Q_1 - 1{,}5\,(Q_3 - Q_1);\ Q_3 + 1{,}5\,(Q_3 - Q_1)]$, procède du même esprit ; elle correspond, sous normalité, à un seuil d'environ $2{,}7$ écarts-types. | ||||
| 137 | + | ||||
| 138 | +Le choix de la variable sur laquelle calculer le score compte autant que le seuil. Le prix lui-même varie légitimement d'un facteur quatre dans le jeu du cas 1 selon la taille et le secteur ; le logarithme du prix au mètre carré, calculé par secteur, neutralise les deux premières sources de variation et laisse apparaître les prix anormalement bas pour ce qu'ils sont. De la même façon, le logarithme du terrain est examiné par secteur, parce que les terrains de Buckingham et de Masson-Angers sont, par construction du jeu, deux fois plus grands que ceux de Hull. Un score robuste calculé sur une variable mal choisie produit des faux positifs à la pelle. | ||||
| 139 | + | ||||
| 140 | +\subsection{L'effet de masquage, mesuré} | ||||
| 141 | + | ||||
| 142 | +Le \cref{tab:14:masquage} compare, secteur par secteur, le score classique et le score robuste du logarithme du prix au mètre carré sur le jeu du cas 1 après les règles R1 à R3, c'est-à-dire pendant que les cinq prix symboliques sont encore présents. À Hull, où deux ventes à \dollars{1} subsistent parmi 193 inscriptions, l'écart-type classique du logarithme vaut 1,395 alors que l'écart-type robuste $1{,}4826\,\mathrm{MAD}$ vaut 0,181 : les deux anomalies ont multiplié par près de huit l'échelle de référence. Le score classique ne dépasse $3{,}5$ en valeur absolue que pour ces deux ventes, dont le score vaut $-9{,}5$ ; toutes les autres observations, y compris les ventes liées non déclarées, sont ramenées à l'intérieur de l'intervalle d'acceptation par l'inflation de l'écart-type. Le score robuste, lui, place les deux prix symboliques à $-74$ et signale huit autres ventes, dont les ventes liées du secteur. La \cref{fig:14:scores} montre les deux distributions : à gauche, une masse écrasée autour de zéro et deux points isolés ; à droite, une distribution dont la forme est celle du marché et dont les anomalies sont rejetées dans la queue gauche. | ||||
| 143 | + | ||||
| 144 | +\begin{table}[htbp] | ||||
| 145 | +\caption{Effet de masquage : scores classique et robuste du logarithme du prix au mètre carré, par secteur, avant le retrait des prix symboliques (données synthétiques)}\label{tab:14:masquage} | ||||
| 146 | +\centering | ||||
| 147 | +\small | ||||
| 148 | +\begin{tabular}{lS[table-format=3.0]S[table-format=1.3]S[table-format=1.3]S[table-format=2.0]S[table-format=2.0]S[table-format=1.0]} | ||||
| 149 | +\toprule | ||||
| 150 | +Secteur & {$n$} & {Écart-type $s$} & {$1{,}4826\,\mathrm{MAD}$} & {$|z_{\text{class.}}| > 3{,}5$} & {$|z_{\text{rob.}}| > 3{,}5$} & {Prix à 1 \$} \\ | ||||
| 151 | +\midrule | ||||
| 152 | +Hull & 193 & 1.395 & 0.181 & 2 & 10 & 2 \\ | ||||
| 153 | +Gatineau & 207 & 0.976 & 0.190 & 1 & 5 & 1 \\ | ||||
| 154 | +Aylmer & 126 & 1.662 & 0.184 & 2 & 4 & 2 \\ | ||||
| 155 | +Buckingham & 44 & 0.678 & 0.192 & 1 & 3 & 0 \\ | ||||
| 156 | +Masson-Angers & 48 & 0.354 & 0.206 & 1 & 1 & 0 \\ | ||||
| 157 | +\bottomrule | ||||
| 158 | +\end{tabular} | ||||
| 159 | +\tabsource{\synth{analysis/python/cases/ch14\_nettoyage.py (fonction \texttt{illustration\_masquage}) ; jeu après R1--R3}} | ||||
| 160 | +\end{table} | ||||
| 161 | + | ||||
| 162 | +\begin{figure}[htbp] | ||||
| 163 | +\centering | ||||
| 164 | +\includegraphics[width=\textwidth]{ch14/ch14-fig-scores-robustes.pdf} | ||||
| 165 | +\caption{Distribution du score classique (à gauche) et du score robuste (à droite) du logarithme du prix au mètre carré pour les 193 inscriptions du secteur Hull après les règles R1 à R3, deux prix à un dollar compris ; les lignes tiretées marquent le seuil de $\pm 3{,}5$ et les scores sont tronqués à $\pm 8$. L'écart-type classique, gonflé par les deux anomalies, masque toutes les autres ; l'échelle robuste les révèle.}\label{fig:14:scores} | ||||
| 166 | +\figsource{\synth{analysis/python/figures/ch14\_figures.py}} | ||||
| 167 | +\end{figure} | ||||
| 168 | + | ||||
| 169 | +Dans la chaîne de traitement du cas 1, les scores robustes interviennent après les règles et l'imputation, sur le jeu de 587 inscriptions, et ils portent sur trois variables : le logarithme du prix au mètre carré par secteur, le logarithme de la superficie habitable et le logarithme du terrain par secteur, avec un seuil de $3{,}5$. Six inscriptions sont signalées (\cref{tab:14:exclus}) : quatre sont des ventes liées non déclarées, dont les prix au mètre carré sont inférieurs de 40 à 60 \% à la médiane de leur secteur ; deux sont des ventes sincères, l'une parce qu'une très grande maison de plain-pied de \msq{241} à Hull affiche un prix unitaire bas (ce qui est l'effet attendu d'une élasticité inférieure à un, vu au \cref{ch:16}), l'autre parce que son terrain est exceptionnellement petit pour le secteur Gatineau. Ces deux faux positifs illustrent la limite d'un score univarié : il ne sait pas qu'un prix unitaire bas est normal pour une grande maison. C'est le rôle de la régression de le savoir. | ||||
| 170 | + | ||||
| 171 | +\section{Les diagnostics de régression}\label{sec:14:regression} | ||||
| 172 | + | ||||
| 173 | +\subsection{La matrice chapeau et le levier} | ||||
| 174 | + | ||||
| 175 | +Le modèle hédonique de référence du cas 1, $\ln P_i = \mathbf{x}_i\T\boldsymbol\beta + \varepsilon_i$ avec les seize régresseurs décrits au \cref{ch:18} et estimé par \texttt{traite.cas1.hedonique}, fournit la métrique conditionnelle qui manquait aux scores univariés : une vente y est anormale si son prix s'écarte de ce que ses caractéristiques, sa localisation et sa date laissent attendre. Les valeurs ajustées s'écrivent $\hat{\mathbf y} = \mathbf H \mathbf y$, où | ||||
| 176 | +\begin{equation}\label{eq:14:chapeau} | ||||
| 177 | +\mathbf H = \mathbf X (\mathbf X\T \mathbf X)^{-1} \mathbf X\T, \qquad h_{ii} = \mathbf x_i\T (\mathbf X\T \mathbf X)^{-1} \mathbf x_i, \qquad \sum_{i=1}^n h_{ii} = \operatorname{tr} \mathbf H = k , | ||||
| 178 | +\end{equation} | ||||
| 179 | +est la \motcle{matrice chapeau} et $h_{ii}$ le \motcle{levier} de l'observation $i$, compris entre $1/n$ et 1 lorsque le modèle contient une constante. Le levier mesure l'éloignement des régresseurs de l'observation par rapport au centre du nuage des régresseurs : une maison très grande, très vieille ou très excentrée a un levier élevé, indépendamment de son prix. Comme la trace vaut $k$, le levier moyen est $k/n$ et la pratique signale les observations dont le levier dépasse $2k/n$ ou $3k/n$ ; dans le jeu du cas 1, $k = 16$ et $n = 581$ à la première itération, de sorte que le seuil $2k/n$ vaut 0,055 et que dix-huit ventes le dépassent, sans qu'aucune ne soit pour autant erronée. | ||||
| 180 | + | ||||
| 181 | +\subsection{Les résidus studentisés} | ||||
| 182 | + | ||||
| 183 | +Le résidu brut $e_i = y_i - \hat y_i$ a pour variance $\sigma^2(1 - h_{ii})$ : les observations à fort levier ont des résidus mécaniquement plus petits, puisque la droite est attirée vers elles. Le \motcle{résidu studentisé interne} corrige cet effet, | ||||
| 184 | +\begin{equation}\label{eq:14:studentise} | ||||
| 185 | +r_i = \frac{e_i}{s\sqrt{1 - h_{ii}}}, \qquad s^2 = \frac{1}{n - k}\sum_{j=1}^n e_j^2 , | ||||
| 186 | +\end{equation} | ||||
| 187 | +mais il utilise une estimation $s^2$ de la variance qui contient le résidu que l'on examine. Le \motcle{résidu studentisé externe} l'en retire : | ||||
| 188 | +\begin{equation}\label{eq:14:externe} | ||||
| 189 | +t_i = \frac{e_i}{s_{(i)}\sqrt{1 - h_{ii}}}, \qquad s_{(i)}^2 = \frac{(n-k)\,s^2 - e_i^2/(1 - h_{ii})}{n - k - 1}, \qquad t_i = r_i \sqrt{\frac{n - k - 1}{n - k - r_i^2}} , | ||||
| 190 | +\end{equation} | ||||
| 191 | +où $s_{(i)}^2$ est la variance résiduelle du modèle estimé sans l'observation $i$. Sous normalité des erreurs, $t_i$ suit exactement une loi de Student à $n - k - 1$ degrés de liberté, ce qui justifie le seuil de $|t_i| > 3$ : la probabilité qu'une vente sincère le dépasse est d'environ 0,27 \%, soit une à deux fausses alertes attendues sur six cents ventes. La forme externe a un avantage pratique décisif pour le nettoyage : une anomalie énorme gonfle $s$ et se masque dans $r_i$, mais pas dans $t_i$, puisque $s_{(i)}$ ne la contient pas. | ||||
| 192 | + | ||||
| 193 | +\subsection{La distance de Cook} | ||||
| 194 | + | ||||
| 195 | +Le résidu dit si une vente est mal expliquée ; il ne dit pas si elle a pesé sur les coefficients. La \motcle{distance de Cook}, introduite par Cook en 1977, mesure le déplacement du vecteur des coefficients lorsque l'observation est retirée, dans la métrique de la précision de l'estimateur : | ||||
| 196 | +\begin{equation}\label{eq:14:cook} | ||||
| 197 | +D_i = \frac{(\hat{\boldsymbol\beta} - \hat{\boldsymbol\beta}_{(i)})\T\, \mathbf X\T \mathbf X\, (\hat{\boldsymbol\beta} - \hat{\boldsymbol\beta}_{(i)})}{k\, s^2} = \frac{r_i^2}{k}\cdot\frac{h_{ii}}{1 - h_{ii}} . | ||||
| 198 | +\end{equation} | ||||
| 199 | + | ||||
| 200 | +\begin{proposition}{Identité de la distance de Cook}{cook} | ||||
| 201 | +Les deux expressions de l'\cref{eq:14:cook} sont égales : la distance de Cook se calcule sans réestimer le modèle $n$ fois, comme le produit du carré du résidu studentisé interne par le rapport de levier $h_{ii}/(1 - h_{ii})$, divisé par $k$. | ||||
| 202 | +\end{proposition} | ||||
| 203 | +\begin{proof} | ||||
| 204 | +Soit $\mathbf A = \mathbf X\T\mathbf X$. Retirer la ligne $i$ donne $\mathbf A_{(i)} = \mathbf A - \mathbf x_i \mathbf x_i\T$, dont l'inverse, par la formule de Sherman--Morrison, est $\mathbf A^{-1} + \mathbf A^{-1}\mathbf x_i \mathbf x_i\T \mathbf A^{-1}/(1 - h_{ii})$. En écrivant $\hat{\boldsymbol\beta}_{(i)} = \mathbf A_{(i)}^{-1}(\mathbf X\T\mathbf y - \mathbf x_i y_i)$ et en développant, on obtient $\hat{\boldsymbol\beta} - \hat{\boldsymbol\beta}_{(i)} = \mathbf A^{-1}\mathbf x_i\, e_i/(1 - h_{ii})$. La forme quadratique du numérateur vaut alors $e_i^2\, \mathbf x_i\T \mathbf A^{-1}\mathbf A\mathbf A^{-1}\mathbf x_i/(1 - h_{ii})^2 = e_i^2 h_{ii}/(1 - h_{ii})^2$. En divisant par $k s^2$ et en reconnaissant $r_i^2 = e_i^2/(s^2(1 - h_{ii}))$, il vient $D_i = r_i^2 h_{ii}/(k(1 - h_{ii}))$. | ||||
| 205 | +\end{proof} | ||||
| 206 | + | ||||
| 207 | +L'identité éclaire la nature de l'influence : elle est le produit de l'anormalité du prix ($r_i^2$) et de l'éloignement des caractéristiques ($h_{ii}/(1-h_{ii})$). Une vente à prix dérisoire d'une maison ordinaire a un résidu énorme et un levier faible ; une maison exceptionnelle vendue au prix attendu a un levier élevé et un résidu nul ; aucune des deux n'est aussi influente qu'une maison exceptionnelle vendue à un prix inattendu. Les seuils courants sont $D_i > 4/n$ pour signaler, et $D_i > 1$ pour considérer qu'une observation déplace à elle seule les coefficients d'une erreur-type. La statistique voisine DFFITS, $t_i\sqrt{h_{ii}/(1-h_{ii})}$, mesure le déplacement de la valeur ajustée de l'observation elle-même. Le test \texttt{test\_ch14.py} vérifie numériquement l'identité en comparant, pour l'observation la plus influente du jeu propre, la forme fermée et la réestimation sans l'observation. | ||||
| 208 | + | ||||
| 209 | +\subsection{Nettoyer sans nettoyer « vers le modèle »} | ||||
| 210 | + | ||||
| 211 | +La règle de décision retenue dans la chaîne du cas 1 est d'exclure les ventes dont le résidu studentisé externe dépasse 3 en valeur absolue, de réestimer, et de répéter au plus une fois ; la distance de Cook et le levier sont calculés et journalisés, mais ne servent pas de critère d'exclusion. Ce choix mérite d'être justifié, parce qu'il touche à une objection sérieuse : écarter les observations que le modèle explique mal améliore mécaniquement l'ajustement du modèle, et un analyste qui exclurait sans retenue finirait par estimer un modèle parfait sur un échantillon qui ne ressemble plus au marché. Trois garde-fous répondent à l'objection. Le premier est le seuil : à $|t_i| > 3$, le nombre attendu de ventes sincères exclues est inférieur à deux sur six cents, et le \cref{tab:14:sensibilite} montre qu'abaisser le seuil à $2{,}5$ multiplie les faux positifs sans améliorer la détection. Le deuxième est le nombre d'itérations, limité à deux : une procédure qui converge vers un noyau d'observations parfaitement expliquées n'est plus un nettoyage. Le troisième est documentaire : chaque exclusion est inscrite au journal avec son résidu, sa distance de Cook et son levier, et l'évaluateur est tenu de chercher, pour chacune, une explication en dehors du modèle (vente liée, état exceptionnel, erreur de saisie non prévue) ; une vente qu'il ne peut expliquer autrement que par son résidu devrait être réintégrée, ou le modèle revu. Le levier et la distance de Cook, eux, servent à autre chose : ils désignent les ventes qui pèsent le plus sur les coefficients et qu'il faut donc vérifier avec le plus de soin, dans l'esprit de ce que le \cref{ch:16} disait des comparables les plus proches. | ||||
| 212 | + | ||||
| 213 | +La \cref{fig:14:levier} montre les 581 ventes de la première itération dans le plan levier–résidu, la taille des points étant proportionnelle à la distance de Cook. Deux ventes dépassent le seuil de résidu, avec des résidus externes de $-5{,}8$ et $-6{,}7$ ; ce sont les deux ventes liées non déclarées que les scores univariés avaient manquées, parce que leurs prix au mètre carré, bien que bas, restaient à l'intérieur de la dispersion de leur secteur. La plus influente des deux a une distance de Cook de 0,084, douze fois le seuil $4/n$, mais loin de 1 : aucune observation du jeu ne déplace à elle seule les coefficients de façon décisive, ce qui est attendu d'un jeu de six cents ventes homogènes. Les dix-huit ventes à levier élevé, à droite de la ligne pointillée, ont des résidus ordinaires : ce sont les maisons les plus grandes, les plus anciennes et les plus excentrées du jeu, exactes et conservées. Après exclusion des deux ventes, la seconde itération ne signale plus rien, et l'écart-type résiduel passe de 0,0897 à 0,0837. | ||||
| 214 | + | ||||
| 215 | +\begin{figure}[htbp] | ||||
| 216 | +\centering | ||||
| 217 | +\includegraphics[width=\textwidth]{ch14/ch14-fig-levier-cook.pdf} | ||||
| 218 | +\caption{Résidu studentisé externe en fonction du levier pour les 581 ventes soumises à la première itération du diagnostic de régression ; la taille des points est proportionnelle à la distance de Cook. Les deux ventes sous la ligne $t_i = -3$ sont les ventes liées non déclarées que les scores univariés n'avaient pas repérées ; les ventes à droite du seuil de levier $2k/n$ sont des maisons atypiques mais exactes.}\label{fig:14:levier} | ||||
| 219 | +\figsource{\synth{analysis/python/figures/ch14\_figures.py}} | ||||
| 220 | +\end{figure} | ||||
| 221 | + | ||||
| 222 | +\begin{table}[htbp] | ||||
| 223 | +\caption{Les huit ventes exclues par les scores robustes (S1) et par la régression (E1), avec leur nature réelle dans la table de vérité (données synthétiques)}\label{tab:14:exclus} | ||||
| 224 | +\centering | ||||
| 225 | +\small\setlength{\tabcolsep}{4pt} | ||||
| 226 | +\begin{tabular}{llS[table-format=3.0]S[table-format=6.0]S[table-format=-1.2]S[table-format=-1.2]S[table-format=-1.2]S[table-format=1.3]l} | ||||
| 227 | +\toprule | ||||
| 228 | +Inscription & Secteur & {Sup. (m\textsuperscript{2})} & {Prix (\$)} & {$z$ prix/m\textsuperscript{2}} & {$z$ terrain} & {$t_i$} & {$D_i$} & Nature réelle \\ | ||||
| 229 | +\midrule | ||||
| 230 | +\multicolumn{9}{l}{\textit{Étape S1 — scores robustes, seuil 3,5}} \\ | ||||
| 231 | +B0173 & Hull & 121 & 155500 & -6.50 & 0.37 & {---} & {---} & vente liée non déclarée \\ | ||||
| 232 | +B0006 & Aylmer & 160 & 231500 & -5.47 & -0.34 & {---} & {---} & vente liée non déclarée \\ | ||||
| 233 | +B0105 & Hull & 116 & 179000 & -5.32 & 0.26 & {---} & {---} & vente liée non déclarée \\ | ||||
| 234 | +B0003 & Hull & 241 & 492000 & -3.51 & -2.06 & {---} & {---} & vente sincère (faux positif) \\ | ||||
| 235 | +B0021 & Aylmer & 165 & 334000 & -3.50 & 1.05 & {---} & {---} & vente liée non déclarée \\ | ||||
| 236 | +B0558 & Gatineau & 174 & 622000 & 0.19 & -3.92 & {---} & {---} & vente sincère (faux positif) \\ | ||||
| 237 | +\addlinespace | ||||
| 238 | +\multicolumn{9}{l}{\textit{Étape E1 — résidu studentisé externe, seuil 3, première itération ($n = 581$, $k = 16$)}} \\ | ||||
| 239 | +B0410 & Hull & 99 & 249000 & {---} & {---} & -6.70 & 0.048 & vente liée non déclarée \\ | ||||
| 240 | +B0039 & Gatineau & 150 & 282500 & {---} & {---} & -5.84 & 0.084 & vente liée non déclarée \\ | ||||
| 241 | +\bottomrule | ||||
| 242 | +\end{tabular} | ||||
| 243 | +\tabsource{\synth{analysis/python/cases/ch14\_nettoyage.py ; les scores $z$ sont calculés par secteur sur le logarithme}} | ||||
| 244 | +\end{table} | ||||
| 245 | + | ||||
| 246 | +\section{Le géocodage}\label{sec:14:geocodage} | ||||
| 247 | + | ||||
| 248 | +\subsection{De l'adresse à la coordonnée} | ||||
| 249 | + | ||||
| 250 | +Les méthodes spatiales du \cref{ch:19}, la sélection par rayon du \cref{ch:16} et les variables de distance du modèle hédonique exigent que chaque vente ait des coordonnées. Le \motcle{géocodage} est l'opération qui associe une coordonnée à une adresse, et sa précision dépend de la technique et de la source. La technique la plus précise attribue à l'adresse un \emph{point d'adresse} relevé sur le bâtiment ou l'entrée ; la suivante prend le \emph{centroïde de la parcelle} cadastrale ; la troisième, historiquement la plus répandue, \emph{interpole} la position le long du segment de rue à partir des tranches de numéros civiques de ses deux extrémités ; la dernière, faute de mieux, affecte à l'adresse le centroïde de son \emph{code postal} ou d'une autre unité géographique. \textcite{zandbergen2008} a comparé ces techniques sur des adresses réelles et établi que l'erreur de position croît dans cet ordre, l'interpolation le long de la rue produisant des erreurs de plusieurs dizaines de mètres en milieu urbain et bien davantage en milieu rural, où les segments sont longs et les numéros irréguliers ; \textcite{ratcliffe2001} avait montré auparavant que ces erreurs suffisent à affecter une proportion non négligeable d'adresses à la mauvaise parcelle ou à la mauvaise unité de recensement. Pour l'évaluateur, la conséquence est double : une variable de distance (au centre, à une école, à une nuisance) hérite de l'erreur de position, et une structure de voisinage (les $k$ plus proches ventes, le rayon de recherche) peut changer de composition. | ||||
| 251 | + | ||||
| 252 | +\begin{quebec}[Les sources québécoises de géocodage] | ||||
| 253 | +Le ministère des Ressources naturelles et des Forêts diffuse sur Données Québec, sous licence CC BY 4.0, la gamme \emph{Adresses Québec}, géobase routière couvrant tout le territoire, qui comprend le réseau routier avec ses odonymes officiels (AQréseau), les adresses par tranches et par points, les codes postaux, un service Web d'adresses (AQgéobâti) et un service de géocodage ; la fiche du jeu de données annonce une transition de cette gamme vers le \emph{Référentiel québécois des adresses} et le \emph{Référentiel québécois du transport terrestre} jusqu'à la fin de 2026. Le Référentiel québécois des adresses, mis à jour mensuellement, rassemble l'ensemble des adresses municipales avec leur numéro, leur suffixe, leur unité, leur odonyme, leur municipalité, leur code postal, leur usage principal et leurs coordonnées ; il est produit avec les municipalités, Élections Québec, le ministère des Affaires municipales et de l'Habitation et le ministère des Transports et de la Mobilité durable (fiches Données Québec consultées le 31 octobre 2026 ; références complètes dans le registre du chapitre). Les versions géoréférencées du rôle d'évaluation en format ouvert (FGDB, GeoPackage, GeoJSON) fournissent la géométrie des unités d'évaluation, donc des centroïdes de parcelle, mais sans adresse de propriétaire \parencite{dqroles}. Les grandes villes publient en outre leurs propres jeux de points d'adresses, comme la Ville de Québec. Quant au code postal canadien, ses trois premiers caractères désignent une région de tri d'acheminement et les trois derniers une unité de distribution locale ; en milieu urbain dense, une unité de distribution correspond souvent à un côté d'îlot, en milieu rural à un vaste territoire, de sorte que la précision d'un centroïde de code postal varie de quelques dizaines de mètres à plusieurs kilomètres. Le fichier de conversion des codes postaux de Statistique Canada et les coordonnées de la Société canadienne des postes sont diffusés sous licence et n'ont pas été consultés pour cet ouvrage ; aucun chiffre de précision n'est donc avancé ici pour ces produits. | ||||
| 254 | +\end{quebec} | ||||
| 255 | + | ||||
| 256 | +\subsection{Une simulation sur les coordonnées du cas 1} | ||||
| 257 | + | ||||
| 258 | +Faute d'adresses réelles à géocoder, on peut mesurer ce que coûte une erreur de position en perturbant les coordonnées propres du cas 1 par un bruit gaussien isotrope d'écart-type $\sigma_g$ par axe, dont la norme suit une loi de Rayleigh de médiane $\sigma_g\sqrt{2\ln 2} \approx 1{,}177\,\sigma_g$. Les cinq valeurs de $\sigma_g$ du \cref{tab:14:geocodage}, de 5 mètres à 1 kilomètre, sont des hypothèses pédagogiques qui respectent la hiérarchie établie par \textcite{zandbergen2008} sans prétendre reproduire ses mesures. Trois conséquences sont calculées : la part des 600 ventes dont l'appartenance au rayon de 3 kilomètres autour du sujet (103 ventes dans le jeu propre) change ; la part des huit plus proches voisins de chaque vente, au sens de la matrice de poids du \cref{ch:19}, qui est conservée ; et le coefficient de la distance au centre dans le modèle hédonique. | ||||
| 259 | + | ||||
| 260 | +\begin{table}[htbp] | ||||
| 261 | +\caption{Effet simulé d'une erreur de position sur les variables spatiales du cas 1, par technique de géocodage (écarts-types hypothétiques)}\label{tab:14:geocodage} | ||||
| 262 | +\centering | ||||
| 263 | +\small | ||||
| 264 | +\begin{tabular}{lS[table-format=4.0]S[table-format=4.0]S[table-format=4.0]S[table-format=1.2]S[table-format=2.1]S[table-format=-1.4]} | ||||
| 265 | +\toprule | ||||
| 266 | +Technique & {$\sigma_g$ (m)} & {Erreur médiane (m)} & {95\textsuperscript{e} centile (m)} & {Rayon 3 km modifié (\%)} & {Voisins conservés (\%)} & {$\hat\beta_{\text{dist}}$} \\ | ||||
| 267 | +\midrule | ||||
| 268 | +Point d'adresse & 5 & 6 & 12 & 0.00 & 99.1 & -0.0036 \\ | ||||
| 269 | +Centroïde de parcelle & 15 & 18 & 35 & 0.00 & 97.1 & -0.0036 \\ | ||||
| 270 | +Interpolation le long de la rue & 40 & 47 & 97 & 0.33 & 93.1 & -0.0036 \\ | ||||
| 271 | +Centroïde de code postal, urbain & 150 & 177 & 368 & 1.33 & 76.1 & -0.0036 \\ | ||||
| 272 | +Centroïde de code postal, périurbain & 1000 & 1199 & 2364 & 6.67 & 17.6 & -0.0003 \\ | ||||
| 273 | +\bottomrule | ||||
| 274 | +\end{tabular} | ||||
| 275 | +\tabsource{\synth{analysis/python/cases/ch14\_nettoyage.py (fonction \texttt{simulation\_geocodage}) ; coefficient de référence $-0{,}0036$ ; les $\sigma_g$ sont des hypothèses, non des mesures}} | ||||
| 276 | +\end{table} | ||||
| 277 | + | ||||
| 278 | +\begin{figure}[htbp] | ||||
| 279 | +\centering | ||||
| 280 | +\includegraphics[width=\textwidth]{ch14/ch14-fig-geocodage.pdf} | ||||
| 281 | +\caption{À gauche, fonction de répartition de l'erreur de position simulée pour cinq techniques de géocodage (écarts-types hypothétiques de 5 m à 1 km) ; à droite, part des 600 ventes dont les huit plus proches voisins sont conservés et dont l'appartenance au rayon de 3 km du sujet est inchangée. La structure de voisinage se dégrade bien avant que le coefficient de distance du modèle hédonique ne bouge.}\label{fig:14:geocodage} | ||||
| 282 | +\figsource{\synth{analysis/python/figures/ch14\_figures.py}} | ||||
| 283 | +\end{figure} | ||||
| 284 | + | ||||
| 285 | +La lecture du tableau tient en une phrase : les variables lisses résistent, les structures discrètes non. Le coefficient de la distance au centre, qui agit sur une échelle de kilomètres, est insensible à des erreurs de quelques dizaines de mètres et ne s'efface qu'avec le centroïde périurbain ; l'appartenance au rayon de recherche ne change que pour les ventes situées près de la frontière du cercle, soit moins de 2 \% jusqu'au centroïde urbain. Mais la composition des huit plus proches voisins, qui fonde les matrices de poids des modèles spatiaux, se dégrade dès l'interpolation de rue (7 \% des voisins remplacés) et s'effondre avec les centroïdes de code postal (un quart puis quatre cinquièmes des voisins remplacés). Un modèle spatial estimé sur des coordonnées de code postal mesure donc une dépendance spatiale entre de mauvais voisins ; la \cref{sec:14:journal} recommande de conserver, pour chaque vente, la technique de géocodage dans une colonne de précision, comme le fait le pipeline du cas 1 avec ses quinze coordonnées de repli placées au centre de leur secteur. | ||||
| 286 | + | ||||
| 287 | +\section{L'appariement des transactions au rôle}\label{sec:14:appariement} | ||||
| 288 | + | ||||
| 289 | +\subsection{Clés, normalisation et blocage} | ||||
| 290 | + | ||||
| 291 | +Une base de ventes gagne considérablement à être enrichie des attributs du rôle d'évaluation : superficies mesurées selon une convention uniforme, année de construction, nombre de logements, valeur au rôle qui servira d'indicateur de qualité au \cref{ch:09}. L'opération est un \motcle{appariement d'enregistrements} (\emph{record linkage}) entre deux fichiers qui ne partagent pas toujours une clé fiable. La clé idéale est le matricule de l'unité d'évaluation, identifiant unique au sein d'une municipalité ; mais il est saisi avec ou sans tirets, avec ou sans espaces, parfois tronqué ou mal frappé, et il manque dans une partie des transactions. L'adresse civique est la clé de rechange, dont la variabilité d'écriture est pire encore (abréviations, accents, numéros d'unité, odonymes renommés) ; les renvois d'odonymes du Référentiel québécois des adresses existent précisément pour suivre les changements de noms de rues. | ||||
| 292 | + | ||||
| 293 | +L'appariement procède par paliers de confiance décroissante. Le premier palier apparie sur la clé exacte. Le deuxième normalise la clé (chiffres seulement pour un matricule ; casse, accents, abréviations et ponctuation unifiées pour une adresse) et apparie sur la forme normalisée. Le troisième, lorsque la clé est absente ou erronée, compare les attributs : on restreint d'abord la recherche à un \motcle{bloc} de candidats plausibles (même secteur, même année de construction), puis on exige la concordance d'attributs continus à une tolérance près (superficie du terrain à 2 \% près), et l'on n'accepte l'appariement que s'il est unique. La théorie de Fellegi et Sunter, publiée en 1969, formalise ce troisième palier : pour chaque champ $j$, on note $m_j$ la probabilité que les deux enregistrements concordent s'ils décrivent la même unité et $u_j$ la probabilité qu'ils concordent par hasard s'ils décrivent des unités différentes ; le poids d'une paire est | ||||
| 294 | +\begin{equation}\label{eq:14:fellegi} | ||||
| 295 | +w = \sum_{j} w_j, \qquad w_j = \begin{cases} \log_2 \dfrac{m_j}{u_j} & \text{si le champ } j \text{ concorde,} \\[2ex] \log_2 \dfrac{1 - m_j}{1 - u_j} & \text{sinon,} \end{cases} | ||||
| 296 | +\end{equation} | ||||
| 297 | +et l'on déclare la paire appariée au-dessus d'un seuil supérieur, non appariée sous un seuil inférieur, et à vérifier manuellement entre les deux. Un champ très discriminant (le matricule, pour lequel $u_j$ est minuscule) apporte un poids élevé ; un champ peu discriminant (le secteur, que partagent des centaines d'unités) n'apporte presque rien. La variante déterministe du cas 1, qui exige la concordance de tous les champs du bloc et l'unicité du candidat, revient à fixer des poids infinis ; elle est plus simple à expliquer et suffit lorsque les attributs continus sont précis. | ||||
| 298 | + | ||||
| 299 | +\subsection{Résultats sur le cas 1} | ||||
| 300 | + | ||||
| 301 | +Le script du chapitre construit un extrait de rôle fictif de 600 unités et des transactions dont la clé est altérée dans 44 \% des cas (espaces, séparateurs absents, chiffre erroné, clé manquante). Le \cref{tab:14:appariement} donne le résultat des trois paliers sur les 618 inscriptions brutes : 59,4 \% s'apparient sur la clé exacte, 32,0 \% de plus sur la clé normalisée, 7,3 \% sur les attributs, et 1,3 \% restent sans appariement ; trois inscriptions ont trouvé plusieurs candidats au troisième palier et n'ont pas été appariées, conformément à la règle d'unicité. Parce que la vérité est connue, on peut vérifier qu'aucun des 610 appariements n'est faux : la normalisation et le blocage, lorsqu'ils sont stricts, ajoutent de la couverture sans ajouter d'erreur. Dans une base réelle, la vérité n'est pas connue ; on l'approche en vérifiant manuellement un échantillon de paires de chaque palier, et le taux de faux appariements de cet échantillon est inscrit au journal avec le taux de couverture. | ||||
| 302 | + | ||||
| 303 | +\begin{table}[htbp] | ||||
| 304 | +\caption{Appariement des 618 inscriptions brutes du cas 1 à l'extrait de rôle fictif, par palier (données synthétiques)}\label{tab:14:appariement} | ||||
| 305 | +\centering | ||||
| 306 | +\small | ||||
| 307 | +\begin{tabular}{llS[table-format=3.0]S[table-format=2.1]S[table-format=1.0]} | ||||
| 308 | +\toprule | ||||
| 309 | +Palier & Critère & {Inscriptions} & {Part (\%)} & {Faux appariements} \\ | ||||
| 310 | +\midrule | ||||
| 311 | +1 & matricule identique, caractère pour caractère & 367 & 59.4 & 0 \\ | ||||
| 312 | +2 & matricule normalisé (chiffres seulement) & 198 & 32.0 & 0 \\ | ||||
| 313 | +3 & secteur, année de construction et terrain à 2 \% près ; candidat unique & 45 & 7.3 & 0 \\ | ||||
| 314 | +{---} & non apparié (dont 3 cas ambigus au palier 3) & 8 & 1.3 & {---} \\ | ||||
| 315 | +\bottomrule | ||||
| 316 | +\end{tabular} | ||||
| 317 | +\tabsource{\synth{analysis/python/cases/ch14\_nettoyage.py (fonction \texttt{appariement\_role}) ; la vérité est connue par construction}} | ||||
| 318 | +\end{table} | ||||
| 319 | + | ||||
| 320 | +\begin{quebec}[Appariement et renseignements personnels] | ||||
| 321 | +Les rôles d'évaluation en format ouvert sont diffusés sans le nom ni l'adresse postale des propriétaires, en vertu d'une disposition réglementaire qui autorise cette diffusion caviardée \parencite[art.~20]{reglrole}, et la licence du jeu interdit expressément de réidentifier les renseignements personnels caviardés \parencite{dqroles}. Apparier une base de ventes nominative au rôle ouvert pour en tirer des attributs physiques est licite ; reconstituer le nom d'un propriétaire à partir du croisement ne l'est pas. L'évaluateur agréé est par ailleurs tenu par le règlement sur la tenue des dossiers de son ordre de conserver les dossiers au moins cinq ans et d'en assurer la confidentialité \parencite[art.~6--7]{tenuedossiersoeaq} ; le journal d'appariement, qui contient des clés d'unité, fait partie du dossier. | ||||
| 322 | +\end{quebec} | ||||
| 323 | + | ||||
| 324 | +\section{Les données manquantes}\label{sec:14:manquantes} | ||||
| 325 | + | ||||
| 326 | +\subsection{Trois mécanismes de manque} | ||||
| 327 | + | ||||
| 328 | +Les champs vides ne sont pas tous équivalents. La distinction introduite par Rubin en 1976 sépare les cas où la probabilité qu'une valeur manque ne dépend de rien (\emph{missing completely at random}, MCAR), les cas où elle dépend de variables observées mais pas de la valeur manquante elle-même (\emph{missing at random}, MAR), | ||||
| 329 | +\begin{equation}\label{eq:14:mar} | ||||
| 330 | +\Pr(R_i = 1 \mid y_i^{\text{obs}}, y_i^{\text{mis}}) = \Pr(R_i = 1 \mid y_i^{\text{obs}}), | ||||
| 331 | +\end{equation} | ||||
| 332 | +où $R_i$ indique le manque, et les cas où elle dépend de la valeur manquante (\emph{missing not at random}, MNAR). Dans une base de ventes, une superficie de terrain absente parce qu'un fichier source ne la transmettait pas pour un secteur entier est MAR conditionnellement au secteur ; une cote de qualité absente parce que l'inspecteur a jugé l'immeuble trop délabré pour la noter est MNAR, et aucune imputation fondée sur les autres champs ne la restituera sans biais. La suppression des lignes incomplètes (\emph{listwise deletion}) est sans biais sous MCAR seulement et perd de l'information dans tous les cas ; dans le jeu du cas 1, elle retire 45 ventes, près de 8 \% de l'échantillon, pour trois champs incomplets. \textcite{wooldridge2010} traite rigoureusement les conséquences de la sélection de l'échantillon sur les estimateurs, et \textcite{gelmanHill2007} donnent un exposé pratique des méthodes d'imputation. | ||||
| 333 | + | ||||
| 334 | +\subsection{Imputation par la médiane conditionnelle, par régression, avec indicateur} | ||||
| 335 | + | ||||
| 336 | +L'\motcle{imputation} remplace la valeur manquante par une valeur plausible. La plus simple est la \emph{médiane conditionnelle} : la médiane de la variable dans la cellule définie par des variables observées (ici le secteur et le type de bâtiment), qui respecte les différences de niveau entre cellules et résiste aux aberrations. La \emph{régression auxiliaire} prédit la valeur manquante à partir d'un modèle estimé sur les lignes complètes, | ||||
| 337 | +\begin{equation}\label{eq:14:imputation} | ||||
| 338 | +\hat x_{ij} = \mathbf z_i\T \hat{\boldsymbol\gamma}_j , | ||||
| 339 | +\end{equation} | ||||
| 340 | +où $\mathbf z_i$ rassemble les autres caractéristiques (superficie, secteur, type, année, terrain) ; elle exploite plus d'information mais produit des valeurs trop régulières, puisqu'elle impute une espérance conditionnelle sans son bruit, ce qui réduit artificiellement la variance de la variable imputée et surestime la précision des coefficients qui en dépendent. L'\emph{indicateur de manquant} ajoute au modèle hédonique une variable binaire par champ imputé, qui absorbe un éventuel décalage systématique des ventes aux champs manquants et signale, par son coefficient, si le manque est informatif. L'imputation multiple, qui tire plusieurs valeurs imputées et combine les estimations, est la méthode de référence lorsque l'incertitude de l'imputation doit être propagée aux intervalles ; elle dépasse le cadre de ce chapitre, mais le \cref{ch:39} y revient dans un cadre bayésien. | ||||
| 341 | + | ||||
| 342 | +Le \cref{tab:14:imputation} compare les quatre traitements sur le cas 1, toute la chaîne étant identique par ailleurs. Les trois imputations donnent des résultats indiscernables entre eux et de la référence : le coefficient du terrain vaut 0,0941 ou 0,0945 contre 0,0937 sur le jeu propre, avec une erreur-type de 0,011 ; la suppression par liste, qui réduit l'échantillon à 535 ventes, s'en écarte davantage (0,0969) et déplace la prédiction du sujet de près de \dollars{4000}. Les coefficients des indicateurs de manquant sont tous inférieurs, en valeur absolue, à deux erreurs-types, ce qui est cohérent avec le mécanisme d'injection, qui est MCAR par construction. Dans une base réelle, un coefficient d'indicateur significatif est un signal d'alarme : les ventes aux champs manquants ne se vendent pas comme les autres, et il faut comprendre pourquoi avant d'imputer. | ||||
| 343 | + | ||||
| 344 | +\begin{table}[htbp] | ||||
| 345 | +\caption{Quatre traitements des 45 valeurs manquantes du jeu brut du cas 1 et leur effet sur le modèle hédonique (données synthétiques)}\label{tab:14:imputation} | ||||
| 346 | +\centering | ||||
| 347 | +\small | ||||
| 348 | +\begin{tabular}{lS[table-format=3.0]S[table-format=1.4]S[table-format=1.4]S[table-format=1.4]S[table-format=1.4]S[table-format=6.0]} | ||||
| 349 | +\toprule | ||||
| 350 | +Traitement & {$n$} & {$\sigma$} & {$\hat\beta_{\ln T}$} & {e.-t.} & {$\hat\beta_{\text{qualité}}$} & {Prédiction sujet (\$)} \\ | ||||
| 351 | +\midrule | ||||
| 352 | +Suppression par liste & 535 & 0.0809 & 0.0969 & 0.0112 & 0.0613 & 640921 \\ | ||||
| 353 | +Médiane conditionnelle (secteur $\times$ type) & 579 & 0.0837 & 0.0941 & 0.0113 & 0.0598 & 637017 \\ | ||||
| 354 | +Régression auxiliaire & 579 & 0.0837 & 0.0940 & 0.0113 & 0.0598 & 637166 \\ | ||||
| 355 | +Médiane + indicateurs de manquant & 579 & 0.0837 & 0.0945 & 0.0112 & 0.0603 & 638354 \\ | ||||
| 356 | +\midrule | ||||
| 357 | +Jeu propre de référence (\cref{ch:18}) & 600 & 0.0830 & 0.0937 & 0.0110 & 0.0611 & 637953 \\ | ||||
| 358 | +\bottomrule | ||||
| 359 | +\end{tabular} | ||||
| 360 | +\tabsource{\synth{analysis/python/cases/ch14\_nettoyage.py (fonction \texttt{comparer\_imputations}) ; coefficients des indicateurs : terrain $-0{,}022$, qualité $0{,}014$, année $-0{,}043$}} | ||||
| 361 | +\end{table} | ||||
| 362 | + | ||||
| 363 | +\section{Exemple intégral : la chaîne de traitement du cas 1 et son effet sur le modèle}\label{sec:14:exemple} | ||||
| 364 | + | ||||
| 365 | +\begin{exemple}{Du jeu brut au modèle hédonique retrouvé}{pipeline14} | ||||
| 366 | +La chaîne de traitement enchaîne les étapes des sections précédentes dans l'ordre que la \cref{fig:14:pipeline} schématise : règles R1 à R7, géocodage de repli G1, imputation I1, scores robustes S1, régression E1, journal. Son effet est mesuré en réestimant le modèle hédonique de référence après chaque étape et en le comparant au modèle estimé sur le jeu propre (\cref{tab:14:modeles}). | ||||
| 367 | + | ||||
| 368 | +\emph{Étape 1 : lecture et règles.} Les 618 inscriptions sont lues, les dates typées, les colonnes dérivées (âge, distance au centre) supprimées pour être recalculées. La règle R2 permute dix couples de dates. La règle R1 exclut dix-huit doublons, treize par la clé d'unité normalisée et cinq par les attributs, en conservant chaque fois l'inscription la plus récente : il reste 600 inscriptions, exactement le nombre de ventes du jeu propre. La règle R3 retranche la contrepartie des meubles de huit prix, pour des montants de \dollars{8000} à \dollars{35000}. La règle R4 exclut cinq prix de \dollars{1}, la règle R5 divise douze superficies par 10,7639 et la règle R6 invalide quinze couples de coordonnées. La règle R7 exclut huit ventes déclarées entre personnes liées ou successorales. Il reste 587 inscriptions ; 30 corrections ont été appliquées. | ||||
| 369 | + | ||||
| 370 | +\emph{Étape 2 : géocodage de repli et imputation.} Les quinze inscriptions sans coordonnées valides reçoivent le centre de leur secteur, avec une précision marquée « centre de secteur » dans une colonne dédiée ; leur distance au centre est recalculée. Les 45 valeurs manquantes (20 terrains, 15 cotes de qualité, 10 années de construction) sont imputées par la médiane de leur cellule secteur $\times$ type. Le modèle hédonique estimé à ce stade a un $R^2$ de 0,755 et un écart-type résiduel de 0,113 : les anomalies grossières ont disparu, mais les six ventes liées non déclarées, à prix divisé par deux, pèsent encore. | ||||
| 371 | + | ||||
| 372 | +\emph{Étape 3 : scores robustes.} Les scores robustes du logarithme du prix au mètre carré par secteur, du logarithme de la superficie et du logarithme du terrain par secteur, au seuil de 3,5, signalent six inscriptions : quatre ventes liées et deux ventes sincères (\cref{tab:14:exclus}). Il reste 581 inscriptions ; l'écart-type résiduel tombe à 0,090. | ||||
| 373 | + | ||||
| 374 | +\emph{Étape 4 : régression.} Le modèle de référence est estimé sur les 581 ventes ; deux résidus studentisés externes dépassent 3 en valeur absolue ($-5{,}84$ et $-6{,}70$), et ce sont les deux dernières ventes liées non déclarées. Elles sont exclues ; la seconde itération ne signale plus rien. Le jeu nettoyé compte 579 ventes : les 600 ventes propres moins les 14 ventes liées, moins les 5 prix symboliques, moins les 2 faux positifs des scores robustes. | ||||
| 375 | + | ||||
| 376 | +\emph{Étape 5 : comparaison des modèles.} Le \cref{tab:14:modeles} aligne cinq estimations. Sur le jeu brut réduit à ses lignes complètes, sans autre traitement, le modèle est détruit : $R^2$ de 0,039, écart-type de 1,231, élasticité de la superficie de 0,20, prédiction du sujet de \dollars{565471}, inférieure de 11 \% à celle du modèle de référence. Les règles seules ramènent l'élasticité à 0,543 et la prédiction à \dollars{634782}, mais laissent un écart-type de 0,113 et un effet temporel surestimé (0,42 \% par mois au lieu de 0,36 \%) parce que les ventes liées se répartissent au hasard dans le temps et bruitent la tendance. Les scores robustes puis la régression achèvent le travail : le modèle nettoyé a un $R^2$ de 0,850 contre 0,853, un écart-type de 0,0837 contre 0,0830, une élasticité de 0,5335 contre 0,5391, et prédit pour le sujet \dollars{637017} contre \dollars{637953}, soit un écart de 0,15 \%. Sur les seize coefficients, l'écart entre le modèle nettoyé et le modèle de référence ne dépasse jamais 0,44 erreur-type ; il tient aux deux faux positifs, aux imputations et aux quinze coordonnées de repli. Le nettoyage n'a pas retrouvé le jeu propre, ce qui est impossible sans la table de vérité ; il a retrouvé le modèle, ce qui est l'objectif. | ||||
| 377 | +\end{exemple} | ||||
| 378 | + | ||||
| 379 | +\begin{figure}[htbp] | ||||
| 380 | +\centering | ||||
| 381 | +\begin{tikzpicture}[node distance=3.2mm, every node/.style={font=\sffamily\small}, boite/.style={draw=brandPrimary, fill=brandLight, rounded corners=1pt, minimum width=110mm, minimum height=7.5mm, align=center}, fleche/.style={-{Stealth[length=2mm]}, brandGray, thick}] | ||||
| 382 | +\node[boite] (a) {Jeu brut : 618 inscriptions, 23 champs}; | ||||
| 383 | +\node[boite, below=of a] (b) {Règles déterministes R1--R7 : 18 + 5 + 8 exclusions, 30 corrections \hfill $n = 587$}; | ||||
| 384 | +\node[boite, below=of b] (c) {Géocodage de repli G1 (15) et imputation I1 (45) \hfill $n = 587$}; | ||||
| 385 | +\node[boite, below=of c] (d) {Scores robustes S1 ($|z| > 3{,}5$) : 6 exclusions \hfill $n = 581$}; | ||||
| 386 | +\node[boite, below=of d] (e) {Régression E1 ($|t_i| > 3$, deux itérations) : 2 exclusions \hfill $n = 579$}; | ||||
| 387 | +\node[boite, below=of e, fill=brandSecondary!30] (f) {Jeu nettoyé + journal (144 lignes : étape, inscription, action, motif, avant, après)}; | ||||
| 388 | +\foreach \i/\j in {a/b, b/c, c/d, d/e, e/f} \draw[fleche] (\i) -- (\j); | ||||
| 389 | +\node[right=2mm of b, text=brandGray, font=\sffamily\footnotesize, align=left] {exact, explicable}; | ||||
| 390 | +\node[right=2mm of d, text=brandGray, font=\sffamily\footnotesize, align=left] {univarié}; | ||||
| 391 | +\node[right=2mm of e, text=brandGray, font=\sffamily\footnotesize, align=left] {conditionnel}; | ||||
| 392 | +\end{tikzpicture} | ||||
| 393 | +\caption{La chaîne de traitement du cas 1 : des règles exactes vers des statistiques de plus en plus conditionnelles, chaque étape étant journalisée. Les effectifs sont ceux de l'exemple intégral.}\label{fig:14:pipeline} | ||||
| 394 | +\figsource{schéma de l'auteur ; effectifs de \texttt{analysis/python/cases/ch14\_nettoyage.py}.} | ||||
| 395 | +\end{figure} | ||||
| 396 | + | ||||
| 397 | +\begin{table}[htbp] | ||||
| 398 | +\caption{Le modèle hédonique de référence réestimé à chaque étape du nettoyage et sur le jeu propre (données synthétiques)}\label{tab:14:modeles} | ||||
| 399 | +\centering | ||||
| 400 | +\small\setlength{\tabcolsep}{4pt} | ||||
| 401 | +\begin{tabular}{lS[table-format=3.0]S[table-format=1.3]S[table-format=1.4]S[table-format=1.4]S[table-format=1.4]S[table-format=1.4]S[table-format=1.2]S[table-format=1.4]S[table-format=6.0]} | ||||
| 402 | +\toprule | ||||
| 403 | +Jeu & {$n$} & {$R^2$} & {$\sigma$} & {$\hat\beta_{\ln S}$} & {e.-t.} & {$\hat\beta_{\text{qual.}}$} & {Mois (\%)} & {$\hat\beta_{\text{Aylmer}}$} & {Prédiction (\$)} \\ | ||||
| 404 | +\midrule | ||||
| 405 | +Brut, lignes complètes & 573 & 0.039 & 1.2311 & 0.2009 & 0.0757 & 0.0569 & 0.18 & 0.0212 & 565471 \\ | ||||
| 406 | +Après règles, G1 et I1 & 587 & 0.755 & 0.1132 & 0.5432 & 0.0161 & 0.0536 & 0.42 & 0.1166 & 634782 \\ | ||||
| 407 | +Après scores robustes S1 & 581 & 0.832 & 0.0897 & 0.5377 & 0.0144 & 0.0570 & 0.36 & 0.1008 & 636062 \\ | ||||
| 408 | +Après régression E1 (nettoyé) & 579 & 0.850 & 0.0837 & 0.5335 & 0.0132 & 0.0598 & 0.36 & 0.0841 & 637017 \\ | ||||
| 409 | +\midrule | ||||
| 410 | +Jeu propre de référence & 600 & 0.853 & 0.0830 & 0.5391 & 0.0127 & 0.0611 & 0.36 & 0.0854 & 637953 \\ | ||||
| 411 | +\bottomrule | ||||
| 412 | +\end{tabular} | ||||
| 413 | +\tabsource{\synth{analysis/python/cases/ch14\_nettoyage.py (fonction \texttt{comparer\_modeles}) ; modèle \texttt{traite.cas1.hedonique}, erreurs-types HC1 ; prédiction du sujet avec correction de Duan}} | ||||
| 414 | +\end{table} | ||||
| 415 | + | ||||
| 416 | +\section{Journalisation et reproductibilité}\label{sec:14:journal} | ||||
| 417 | + | ||||
| 418 | +Le nettoyage modifie les données sur lesquelles reposent toutes les conclusions du rapport ; il doit donc être aussi traçable qu'un calcul de valeur. Le \motcle{journal d'exclusions} est le document qui rend cette traçabilité possible. Celui du cas 1 compte 144 lignes et sept champs : la version de la chaîne de traitement, l'étape, l'identifiant de l'inscription, l'action (exclusion, correction, imputation), le motif en clair, le champ modifié, et les valeurs avant et après. Il permet de répondre à trois questions que posera tout réviseur. Pourquoi cette vente n'est-elle pas dans l'analyse ? Le journal donne la règle ou le score qui l'a écartée. Pourquoi ce prix diffère-t-il de l'acte ? Le journal montre la contrepartie des meubles retranchée. Combien d'observations ont été imputées, et comment ? Le journal les énumère. La reproductibilité exige en outre que trois choses soient fixées et déclarées : la \emph{graine} de tout tirage aléatoire (ici 20261031, utilisée pour construire le jeu brut et pour la simulation de géocodage), les \emph{versions} des données sources et du code (la date d'extraction, la version de la chaîne inscrite dans chaque ligne du journal, les versions des bibliothèques), et les \emph{seuils} (\dollars{5000}, \msq{450}, 3,5, 3, deux itérations) arrêtés avant l'examen des données et non après. Le test automatisé \texttt{test\_ch14.py} vérifie que le jeu brut se régénère à l'identique, que les effectifs de chaque étape sont ceux du texte et que les identités algébriques des diagnostics tiennent ; c'est la forme la plus exigeante de la reproductibilité, et la seule qui survive au départ de l'analyste. | ||||
| 419 | + | ||||
| 420 | +\begin{pratique} | ||||
| 421 | +Un dossier de nettoyage défendable comporte : la description des sources avec leur date d'extraction et leur licence ; la liste ordonnée des règles, avec le test, l'action et le nombre d'inscriptions touchées ; les variables, l'échelle et les seuils des scores robustes ; le modèle utilisé pour les diagnostics de régression, le seuil et le nombre d'itérations ; la technique de géocodage de chaque vente et le taux d'appariement au rôle par palier ; la méthode d'imputation et le nombre de valeurs imputées par champ ; le journal d'exclusions ; la graine et les versions ; et une analyse de sensibilité aux seuils. Les Normes de pratique professionnelle de l'Ordre exigent que le rapport permette au lecteur de comprendre et de vérifier le raisonnement \parencite{oeaqNormes}, et le règlement sur la tenue des dossiers que les pièces soient conservées \parencite{tenuedossiersoeaq} ; le journal est la pièce qui satisfait l'une et l'autre pour la partie « données » du mandat. | ||||
| 422 | +\end{pratique} | ||||
| 423 | + | ||||
| 424 | +\section{Sensibilité aux seuils}\label{sec:14:sensibilite} | ||||
| 425 | + | ||||
| 426 | +Les seuils des scores robustes et des résidus studentisés sont des décisions, et le \cref{tab:14:sensibilite} mesure ce qu'elles coûtent. La chaîne du cas 1 a été réexécutée pour quatre seuils de score robuste (2,5 ; 3 ; 3,5 ; 4) et trois seuils de résidu (2,5 ; 3 ; 3,5), et pour chaque combinaison on compte les exclusions des étapes S1 et E1, les ventes liées non déclarées détectées (sur six), les ventes sincères exclues à tort, et l'on relève l'écart-type résiduel et la prédiction du sujet. La \cref{fig:14:sensibilite} en trace l'essentiel. | ||||
| 427 | + | ||||
| 428 | +\begin{table}[htbp] | ||||
| 429 | +\caption{Sensibilité de la chaîne de traitement aux seuils du score robuste et du résidu studentisé (données synthétiques)}\label{tab:14:sensibilite} | ||||
| 430 | +\centering | ||||
| 431 | +\small | ||||
| 432 | +\begin{tabular}{S[table-format=1.1]S[table-format=1.1]S[table-format=2.0]S[table-format=2.0]S[table-format=1.0]S[table-format=2.0]S[table-format=3.0]S[table-format=1.4]S[table-format=6.0]} | ||||
| 433 | +\toprule | ||||
| 434 | +{Seuil $|z|$} & {Seuil $|t_i|$} & {Exclues S1} & {Exclues E1} & {Liées détectées / 6} & {Faux positifs} & {$n$ final} & {$\sigma$} & {Prédiction (\$)} \\ | ||||
| 435 | +\midrule | ||||
| 436 | +2.5 & 2.5 & 33 & 8 & 6 & 22 & 546 & 0.0783 & 633813 \\ | ||||
| 437 | +2.5 & 3.0 & 33 & 1 & 6 & 19 & 553 & 0.0816 & 633841 \\ | ||||
| 438 | +3.0 & 2.5 & 11 & 10 & 6 & 7 & 566 & 0.0796 & 637527 \\ | ||||
| 439 | +3.0 & 3.0 & 11 & 1 & 6 & 3 & 575 & 0.0836 & 636573 \\ | ||||
| 440 | +3.5 & 2.5 & 6 & 10 & 6 & 6 & 571 & 0.0802 & 638159 \\ | ||||
| 441 | +3.5 & 3.0 & 6 & 2 & 6 & 2 & 579 & 0.0837 & 637017 \\ | ||||
| 442 | +4.0 & 2.5 & 3 & 10 & 6 & 3 & 574 & 0.0806 & 638476 \\ | ||||
| 443 | +4.0 & 3.0 & 3 & 3 & 6 & 0 & 581 & 0.0838 & 637349 \\ | ||||
| 444 | +\bottomrule | ||||
| 445 | +\end{tabular} | ||||
| 446 | +\tabsource{\synth{analysis/python/cases/ch14\_nettoyage.py (fonction \texttt{sensibilite\_seuils}) ; les combinaisons avec un seuil de résidu de 3,5 coïncident avec celles à 3,0 et sont omises ; ligne de référence du chapitre : 3,5 et 3,0}} | ||||
| 447 | +\end{table} | ||||
| 448 | + | ||||
| 449 | +\begin{figure}[htbp] | ||||
| 450 | +\centering | ||||
| 451 | +\includegraphics[width=\textwidth]{ch14/ch14-fig-sensibilite-seuils.pdf} | ||||
| 452 | +\caption{À gauche, faux positifs et ventes liées détectées selon le seuil du score robuste, pour deux seuils de résidu studentisé ; à droite, écart-type résiduel du modèle nettoyé. Les six ventes liées sont détectées quels que soient les seuils ; des seuils plus sévères n'achètent qu'une baisse artificielle de l'écart-type au prix de ventes sincères écartées.}\label{fig:14:sensibilite} | ||||
| 453 | +\figsource{\synth{analysis/python/figures/ch14\_figures.py}} | ||||
| 454 | +\end{figure} | ||||
| 455 | + | ||||
| 456 | +Deux enseignements se dégagent. Le premier est rassurant : les six ventes liées non déclarées sont détectées pour toutes les combinaisons, parce que le relais entre scores univariés et diagnostics conditionnels est robuste au seuil de chacun ; ce qu'un seuil tolérant laisse passer à l'étape S1, l'étape E1 le rattrape. Le second est une mise en garde : les seuils sévères n'améliorent pas la détection, ils fabriquent des faux positifs, vingt-deux pour la combinaison la plus sévère, et l'écart-type résiduel qui en résulte, 0,078 au lieu de 0,083, n'est pas une mesure plus précise du marché mais une mesure d'un marché amputé de ses ventes les plus dispersées. Un évaluateur qui rapporterait cet écart-type sous-estimerait l'incertitude de ses prédictions. Entre les seuils 3 et 4 pour le score et 3 et 3,5 pour le résidu, la prédiction du sujet varie de \dollars{636573} à \dollars{637349}, soit 0,1 \% ; c'est la plage dans laquelle le choix des seuils est à peu près indifférent, et c'est là qu'il faut se placer. Le seuil de résidu de 2,5 est, dans ce jeu, clairement trop bas : il exclut dix ventes à l'étape E1, dont au moins sept sincères, et il faudrait une raison documentée pour chacune. | ||||
| 457 | + | ||||
| 458 | +\begin{erreurs} | ||||
| 459 | +\begin{itemize} | ||||
| 460 | +\item \emph{Détecter les aberrations avec la moyenne et l'écart-type.} Les anomalies gonflent l'écart-type et se masquent ; dans le secteur Hull du cas 1, le score classique ne repère que les deux prix à un dollar, le score robuste en signale dix. Toujours la médiane et le MAD. | ||||
| 461 | +\item \emph{Calculer un score sur la mauvaise variable.} Un score sur le prix total confond taille et anomalie ; un score sur le prix au mètre carré sans distinguer les secteurs confond localisation et anomalie. La variable doit être celle dont la dispersion légitime est la plus faible. | ||||
| 462 | +\item \emph{Corriger sans connaître le mécanisme.} Diviser par 10,7639 toute superficie « trop grande » sans vérifier que le résultat est plausible, ou remplacer une coordonnée nulle par une moyenne sans le marquer, transforme une erreur visible en erreur invisible. | ||||
| 463 | +\item \emph{Oublier la contrepartie des meubles et la date de la promesse.} Le prix de l'acte n'est pas toujours le prix de l'immeuble, et la date de l'acte n'est pas la date du prix. | ||||
| 464 | +\item \emph{Nettoyer vers le modèle.} Exclure itérativement tout ce que le modèle explique mal produit un écart-type résiduel flatteur et une sous-estimation de l'incertitude ; seuil déclaré, itérations bornées, explication documentée pour chaque exclusion. | ||||
| 465 | +\item \emph{Traiter l'influence comme une faute.} Une maison atypique à fort levier et au prix conforme au marché est une observation précieuse, pas une anomalie ; la distance de Cook désigne ce qu'il faut vérifier, pas ce qu'il faut exclure. | ||||
| 466 | +\item \emph{Géocoder au code postal pour un modèle spatial.} Les trois quarts des voisins changent avec un centroïde urbain ; la matrice de poids ne décrit plus le voisinage réel. | ||||
| 467 | +\item \emph{Supprimer les lignes incomplètes par défaut.} La suppression par liste perd 8 \% de l'échantillon du cas 1 et n'est sans biais que si le manque est complètement aléatoire ; imputer et déclarer. | ||||
| 468 | +\end{itemize} | ||||
| 469 | +\end{erreurs} | ||||
| 470 | + | ||||
| 471 | +\begin{limites} | ||||
| 472 | +\begin{itemize} | ||||
| 473 | +\item Le jeu brut est synthétique et ses anomalies ont été injectées selon des lois simples et connues ; les anomalies réelles sont plus variées (prix incluant des travaux à venir, ventes multiples en un acte, copropriétés indivises, erreurs de secteur) et leurs proportions ne sont pas celles du jeu. Aucune statistique publique sur la fréquence des anomalies dans les bases québécoises n'a été trouvée ; les proportions utilisées sont pédagogiques. | ||||
| 474 | +\item Les écarts-types d'erreur de position du \cref{tab:14:geocodage} sont des hypothèses respectant la hiérarchie des techniques décrite dans la littérature, non des mesures sur des géocodeurs québécois ; la précision réelle d'Adresses Québec, du Référentiel québécois des adresses et des centroïdes de code postal n'a pas été mesurée pour cet ouvrage. | ||||
| 475 | +\item Le seuil de \dollars{5000} et la règle d'épuration à deux écarts-types proviennent du règlement sur la proportion médiane, conçu pour les études de ratios de l'évaluation municipale ; leur transposition à l'évaluation privée est une convention, non une exigence. | ||||
| 476 | +\item La chaîne applique l'imputation avant les scores robustes et la régression ; l'ordre inverse est défendable et donnerait des effectifs légèrement différents. L'imputation multiple n'a pas été mise en œuvre. | ||||
| 477 | +\item Les fiches Données Québec consultées pour Adresses Québec et le Référentiel québécois des adresses annoncent une transition de produits jusqu'à la fin de 2026 ; les noms et l'offre de services décrits ici peuvent avoir changé à la lecture. | ||||
| 478 | +\item Les références de Hampel (1974), Cook (1977), Fellegi et Sunter (1969), Rubin (1976), Rousseeuw et Croux (1993) et Leys et coauteurs (2013) ont été vérifiées par leur identifiant numérique d'objet mais ne figurent pas encore dans la bibliographie générale de l'ouvrage ; elles sont consignées dans le registre du chapitre. | ||||
| 479 | +\end{itemize} | ||||
| 480 | +\end{limites} | ||||
| 481 | + | ||||
| 482 | +\begin{synthese} | ||||
| 483 | +\begin{itemize} | ||||
| 484 | +\item Erreur de donnée, transaction non représentative, valeur aberrante et observation influente sont quatre choses différentes ; la première se corrige, la deuxième s'exclut ou s'ajuste, la troisième se détecte dans une métrique robuste, la quatrième se vérifie. | ||||
| 485 | +\item Une contamination de proportion $\varepsilon$ et d'ampleur $\delta$ biaise la moyenne de $\varepsilon\delta$ sans borne ; la médiane et le MAD ont un point de rupture de 50 \%. Le score robuste $z = (x - \text{méd})/(1{,}4826\,\text{MAD})$ est comparable à un score classique sous normalité et ne se masque pas. | ||||
| 486 | +\item Les règles déterministes viennent d'abord et corrigent seulement ce dont le mécanisme est connu ; les scores robustes repèrent les aberrations univariées ; les résidus studentisés externes repèrent les ventes anormales conditionnellement au modèle ; la distance de Cook $D_i = r_i^2 h_{ii}/(k(1-h_{ii}))$ désigne les ventes à vérifier. | ||||
| 487 | +\item Sur le cas 1, cinq prix à un dollar suffisent à détruire le modèle ($R^2$ de 0,04) ; la chaîne complète le retrouve à moins de 0,44 erreur-type sur chaque coefficient et à 0,15 \% sur la prédiction du sujet. | ||||
| 488 | +\item La précision du géocodage compte peu pour les variables de distance et beaucoup pour les structures de voisinage ; la technique doit être conservée par vente. | ||||
| 489 | +\item L'appariement au rôle procède par paliers (clé exacte, clé normalisée, attributs avec blocage et unicité) ; la couverture passe de 59 à 99 \% sans faux appariement sur le cas 1 ; les données caviardées ne doivent pas être réidentifiées. | ||||
| 490 | +\item Les valeurs manquantes s'imputent par médiane conditionnelle, régression ou avec indicateur, après réflexion sur le mécanisme de manque ; la suppression par liste est le pire choix par défaut. | ||||
| 491 | +\item Graine, versions, seuils déclarés d'avance et journal d'exclusions sont les conditions de la reproductibilité ; une analyse de sensibilité aux seuils fait partie du dossier. | ||||
| 492 | +\end{itemize} | ||||
| 493 | +\end{synthese} | ||||
| 494 | + | ||||
| 495 | +\section*{Exercices} | ||||
| 496 | +\addcontentsline{toc}{section}{Exercices} | ||||
| 497 | + | ||||
| 498 | +\begin{exercice}[1]{Score robuste et score classique}{ex:14:1} | ||||
| 499 | +Neuf ventes d'un même secteur ont les prix au mètre carré habitable suivants : \num{3150}, \num{3320}, \num{3080}, \num{3410}, \num{3260}, \num{3190}, \num{3370}, \num{3240} et \num{5980} \$/m\textsuperscript{2}. Calculez la médiane, l'écart absolu médian et le score robuste \eqref{eq:14:zrobuste} de chaque vente, puis la moyenne, l'écart-type et le score classique. Laquelle des deux méthodes signale la neuvième vente au seuil de 3,5 ? Expliquez l'écart entre les deux scores de cette vente. | ||||
| 500 | +\end{exercice} | ||||
| 501 | + | ||||
| 502 | +\begin{exercice}[1]{Règles et journal}{ex:14:2} | ||||
| 503 | +Pour chacune des inscriptions suivantes, indiquez la règle du \cref{tab:14:regles} qui s'applique, l'action (correction, exclusion, signalement) et la ligne de journal à écrire : (a) prix déclaré de \dollars{1} ; (b) superficie habitable de \num{1776} dans un champ en mètres carrés, pour une maison de quatre chambres ; (c) date d'acte du 15 mars 2026 et date de promesse du 2 mai 2026 ; (d) prix de \dollars{515000} dont \dollars{15000} de meubles déclarés ; (e) latitude et longitude égales à zéro ; (f) mention « succession » dans le type de transaction. Quelle superficie en mètres carrés la correction (b) produit-elle ? | ||||
| 504 | +\end{exercice} | ||||
| 505 | + | ||||
| 506 | +\begin{exercice}[2]{Levier, résidu studentisé et distance de Cook}{ex:14:3} | ||||
| 507 | +Dans une régression semi-logarithmique de $n = 600$ ventes et $k = 16$ régresseurs, d'écart-type résiduel $s = 0{,}083$, une vente a un résidu brut $e_i = -0{,}25$ et un levier $h_{ii} = 0{,}04$. Calculez son résidu studentisé interne, son résidu studentisé externe et sa distance de Cook ; comparez-les aux seuils 3, 3 et $4/n$. La vente serait-elle exclue par la règle E1 du chapitre ? Que faudrait-il faire avant de l'exclure ? | ||||
| 508 | +\end{exercice} | ||||
| 509 | + | ||||
| 510 | +\begin{exercice}[2]{Contamination et point de rupture}{ex:14:4} | ||||
| 511 | +Dans un marché où le logarithme du prix a un écart-type de 0,085, 5 \% des ventes d'une base sont des ventes liées conclues à la moitié du prix de marché. À l'aide de l'\cref{eq:14:contamination}, calculez le biais de la moyenne des logarithmes et l'effet correspondant en pourcentage sur le niveau de prix, puis l'écart-type de l'échantillon contaminé. Qu'en est-il de la médiane ? Quelle proportion de ventes liées faudrait-il pour déplacer la médiane ? | ||||
| 512 | +\end{exercice} | ||||
| 513 | + | ||||
| 514 | +\begin{exercice}[2]{Poids d'appariement de Fellegi--Sunter}{ex:14:5} | ||||
| 515 | +Trois champs servent à apparier des ventes au rôle : le matricule ($m = 0{,}98$, $u = 0{,}001$), l'année de construction ($m = 0{,}95$, $u = 0{,}05$) et le secteur ($m = 0{,}90$, $u = 0{,}20$). Calculez les poids de concordance et de discordance de chaque champ selon l'\cref{eq:14:fellegi}, puis le poids total d'une paire dont les trois champs concordent, d'une paire dont le matricule et l'année concordent mais pas le secteur, et d'une paire dont le matricule discorde mais dont l'année et le secteur concordent. Si le seuil d'acceptation est fixé à 8 et le seuil de rejet à 0, classez les trois paires. | ||||
| 516 | +\end{exercice} | ||||
| 517 | + | ||||
| 518 | +\begin{exercice}[3]{Sensibilité aux seuils}{ex:14:6} | ||||
| 519 | +À l'aide de \texttt{analysis/python/cases/ch14\_nettoyage.py} (fonction \texttt{pipeline}, arguments \texttt{seuil\_mad} et \texttt{seuil\_t}), réexécutez la chaîne du cas 1 avec un seuil de score robuste de 3 et un seuil de résidu de 2,5, puis avec 4 et 3. Pour chaque variante, rapportez le nombre de ventes exclues aux étapes S1 et E1, le nombre de ventes liées non déclarées détectées, le nombre de ventes sincères exclues à tort (en vous servant de la table de vérité), l'écart-type résiduel et la prédiction du sujet. Rédigez une note de 150 mots sur le choix des seuils que vous recommanderiez pour un mandat réel, où la table de vérité n'existe pas. | ||||
| 520 | +\end{exercice} | ||||
| 521 | + | ||||
| 522 | +\begin{exercice}[3]{Mécanisme de manque et imputation}{ex:14:7} | ||||
| 523 | +Modifiez la fonction \texttt{generer\_brut} du script pour que les vingt terrains manquants ne soient plus tirés au hasard mais choisis parmi les vingt plus petits terrains du jeu (mécanisme MNAR), puis réexécutez \texttt{comparer\_imputations}. Comparez le coefficient du terrain et la prédiction du sujet sous les quatre traitements à ceux du \cref{tab:14:imputation}. Le coefficient de l'indicateur de terrain manquant change-t-il de signe ou d'ampleur ? Expliquez pourquoi la suppression par liste et l'imputation par la médiane conditionnelle sont toutes deux biaisées dans ce cas, et laquelle l'est le plus. | ||||
| 524 | +\end{exercice} | ||||
| 525 | + | ||||
| 526 | +\section*{Pour aller plus loin} | ||||
| 527 | +\addcontentsline{toc}{section}{Pour aller plus loin} | ||||
| 528 | + | ||||
| 529 | +Le protocole de préparation des données immobilières de \textcite{krauseLipscomb2016} est le point de départ naturel : il passe en revue, pour un public d'évaluateurs et de chercheurs, les étapes de collecte, de nettoyage, de géocodage et de documentation, et il insiste sur la traçabilité des décisions. Sur le géocodage, \textcite{zandbergen2008} compare les techniques par point d'adresse, par parcelle et par interpolation de rue et quantifie leurs erreurs, tandis que \textcite{ratcliffe2001} montre ce que ces erreurs font aux affectations cadastrales et censitaires ; les deux articles sont indispensables avant d'estimer un modèle spatial, et \textcite{dubin1998} fournit l'introduction à l'autocorrélation spatiale qui explique pourquoi la composition du voisinage importe tant. La segmentation du marché, qui conditionne les cellules dans lesquelles les scores robustes et les médianes conditionnelles sont calculés, est traitée par \textcite{goodmanThibodeau1998} et \textcite{bourassa1999} et développée au \cref{ch:15}. Pour l'inférence en présence de données manquantes et de sélection, \textcite{wooldridge2010} est la référence théorique et \textcite{gelmanHill2007} le guide pratique de l'imputation. Les normes de l'évaluation de masse, \textcite{iaaomass2025} et \textcite{iaaoratio2013}, codifient l'épuration des ventes pour les études de ratios et sont le pendant international du règlement québécois sur la proportion médiane \parencite{reglpropmed} ; \textcite{gloudemansAlmy2011} en donnent l'exposé pédagogique. Enfin, les articles fondateurs de la statistique robuste et des diagnostics de régression, Hampel (1974) sur la fonction d'influence, Cook (1977) sur la distance qui porte son nom, Rousseeuw et Croux (1993) sur les estimateurs d'échelle, ainsi que Fellegi et Sunter (1969) sur l'appariement et Rubin (1976) sur les mécanismes de manque, sont consignés avec leurs identifiants dans le registre du chapitre en vue de leur intégration à la bibliographie générale. | ||||
modified
manuscript/chapters/ch15.tex
+534 −1
@@ -1,2 +1,535 @@ | |||||
| 1 | \chapter{Études de marché et segmentation}\label{ch:15} | 1 | \chapter{Études de marché et segmentation}\label{ch:15} | ||
| 2 | −\stubchapter | 2 | + | ||
| 3 | +Avant de choisir un comparable, d'estimer un prix implicite ou de capitaliser un revenu, l'évaluateur doit répondre à une question que les chapitres de méthode supposent résolue : de quel marché le sujet relève-t-il, et dans quel état ce marché se trouve-t-il à la date d'évaluation ? La définition de la valeur marchande parle d'un « marché libre et ouvert à la concurrence » et d'une « mise en vente d'une durée suffisante » ; ces mots n'ont de contenu que si l'on sait quels biens se font concurrence, qui les achète et à quel rythme ils s'écoulent. Le présent chapitre clôt la partie consacrée aux données en montrant comment passer des statistiques publiques, décrites aux \cref{ch:13,ch:14}, à une connaissance opératoire du marché du sujet. Il délimite d'abord le marché et ses sous-marchés par des critères économiques, puis il mesure l'équilibre entre l'offre et la demande par des indicateurs de flux et de stock, avant d'aborder la question qui relie l'étude de marché à l'économétrie des chapitres suivants : les sous-marchés que l'on distingue par habitude correspondent-ils à des structures de prix différentes, ou une seule équation suffit-elle ? Les méthodes de classification et le test de Chow donnent à cette question une réponse chiffrée, illustrée sur les 600 ventes synthétiques du cas 1. Le chapitre se termine par l'étude de marché locatif de l'immeuble de douze logements du cas 3, où les mêmes principes s'appliquent aux loyers, à l'inoccupation et à la concurrence du parc neuf. | ||||
| 4 | + | ||||
| 5 | +\begin{objectifs} | ||||
| 6 | +À la fin de ce chapitre, le lecteur sait : | ||||
| 7 | +\begin{itemize} | ||||
| 8 | +\item délimiter le marché et les sous-marchés d'un bien par des critères de substituabilité, d'acheteur type et de géographie, et distinguer une segmentation a priori d'une segmentation révélée par les données ; | ||||
| 9 | +\item conduire une étude de marché en six étapes à partir des sources publiques québécoises, en citant chaque chiffre avec son organisme, sa période et ses conditions d'utilisation ; | ||||
| 10 | +\item calculer et interpréter les indicateurs de conjoncture d'un marché de la revente, mois d'inventaire, taux d'absorption, délai de vente et ratio du prix vendu au prix demandé, et comprendre pourquoi un indicateur de stock et un indicateur de flux ne disent pas la même chose ; | ||||
| 11 | +\item appliquer les méthodes de classification, k-moyennes et classification hiérarchique de Ward, à des ventes décrites par leurs attributs et leurs coordonnées, choisir le nombre de segments par la silhouette et juger de la concordance avec les secteurs de marché ; | ||||
| 12 | +\item dériver et appliquer le test de Chow de stabilité des coefficients d'un modèle hédonique entre segments, dans sa version classique et dans sa version robuste, et en tirer une décision motivée sur l'usage d'une équation unique ; | ||||
| 13 | +\item construire l'étude de marché locatif d'un immeuble de logements : univers, structure des loyers, inoccupation, rotation, écart entre loyers en place et loyers de marché, concurrence de l'offre neuve. | ||||
| 14 | +\end{itemize} | ||||
| 15 | +\end{objectifs} | ||||
| 16 | + | ||||
| 17 | +\section{Délimiter le marché et ses sous-marchés}\label{sec:15:delimitation} | ||||
| 18 | + | ||||
| 19 | +\subsection{Le marché comme ensemble de substituts} | ||||
| 20 | + | ||||
| 21 | +Le mot « marché » désigne, en évaluation, l'ensemble des biens qui se font concurrence pour une même demande. Deux maisons appartiennent au même marché si l'acheteur qui en visite une visiterait vraisemblablement l'autre, de sorte que leurs prix sont tenus l'un par l'autre selon le principe de substitution exposé au \cref{ch:16}. Cette définition est économique avant d'être géographique : une maison de \msq{400} et une maison de \msq{110} situées dans la même rue n'appartiennent pas au même marché, parce qu'aucun acheteur ne les met en balance ; inversement, deux cottages semblables de Hull et d'Aylmer, distants de dix kilomètres, peuvent appartenir au même marché si les acheteurs de l'ouest de Gatineau arbitrent couramment entre les deux secteurs. La délimitation d'un marché consiste donc à identifier l'\motcle{acheteur type} du sujet, c'est-à-dire le profil de ménage ou d'investisseur le plus susceptible de l'acquérir, puis à recenser l'ensemble des biens que cet acheteur considère comme substituables, dans l'espace, dans le temps et dans l'espace des caractéristiques. | ||||
| 22 | + | ||||
| 23 | +\begin{definition}{Marché et sous-marché}{sousmarche} | ||||
| 24 | +Le \motcle{marché} d'un bien est l'ensemble des biens substituables pour son acheteur type, dont les prix sont liés par la concurrence. Un \motcle{sous-marché} (\emph{submarket}) est une partition de ce marché à l'intérieur de laquelle la relation entre le prix et les caractéristiques est homogène et entre les parties de laquelle elle diffère. Formellement, si $s(i)$ désigne le sous-marché du bien $i$, l'espérance conditionnelle du prix s'écrit | ||||
| 25 | +\begin{equation}\label{eq:15:sousmarche} | ||||
| 26 | +\E\left[\ln P_i \mid \mathbf{x}_i, s(i) = g\right] = \alpha_g + \mathbf{x}_i\T \boldsymbol{\beta}_g , | ||||
| 27 | +\end{equation} | ||||
| 28 | +et les sous-marchés sont distincts dès que les $\boldsymbol{\beta}_g$ diffèrent. Lorsque seules les constantes $\alpha_g$ diffèrent, les sous-marchés ne sont que des niveaux de prix différents à l'intérieur d'une même structure, et une seule équation avec des effets de localisation suffit. | ||||
| 29 | +\end{definition} | ||||
| 30 | + | ||||
| 31 | +La distinction entre une différence de niveau et une différence de structure est le fil conducteur du chapitre. Elle a des conséquences directes pour la méthode de comparaison : si le secteur d'Aylmer ne se distingue de Hull que par une prime de localisation, un comparable d'Aylmer est utilisable pour un sujet de Hull moyennant un ajustement de localisation, et les ajustements de superficie, d'âge ou de qualité tirés d'Aylmer sont transférables ; si au contraire la superficie est rémunérée différemment dans les deux secteurs, un ajustement de superficie estimé à Aylmer est biaisé à Hull, et il faut soit restreindre les comparables au secteur du sujet, soit estimer des prix implicites propres à chaque sous-marché. La littérature économétrique a abordé la question dès les années 1990. \textcite{goodmanThibodeau1998} ont proposé une construction hiérarchique des sous-marchés qui regroupe les quartiers dont les coefficients hédoniques ne diffèrent pas significativement, et ils ont montré ensuite que cette segmentation améliore la précision des prédictions hors échantillon \parencite{goodmanThibodeau2003}. \textcite{bourassa1999} ont comparé, sur les données de Sydney et de Melbourne, les sous-marchés définis a priori par les autorités et ceux révélés par l'analyse en composantes principales et la classification ; ils ont trouvé que les deux approches sont utiles mais que les sous-marchés a priori, fondés sur la connaissance du terrain, prédisent souvent aussi bien que les sous-marchés statistiques, résultat confirmé par \textcite{bourassaHoesliPeng2003}, pour qui l'essentiel est d'inclure les sous-marchés dans le modèle plutôt que de les raffiner à l'excès. Au Québec, \textcite{kestensTheriaultDesrosiers2006} ont montré sur le marché de Québec que l'hétérogénéité des prix implicites tient aussi aux profils des acheteurs, âge, revenu et composition du ménage, et non seulement à la localisation, et \textcite{desrosiersDubeTheriault2011} ont établi que la valeur d'une maison dépend de celle de ses voisines immédiates, ce qui plaide pour des sous-marchés fins. Ces travaux justifient la démarche en deux temps adoptée ici : une délimitation a priori fondée sur les critères du \cref{tab:15:criteres}, puis une vérification statistique de son bien-fondé. | ||||
| 32 | + | ||||
| 33 | +\subsection{Les critères de délimitation} | ||||
| 34 | + | ||||
| 35 | +Le \cref{tab:15:criteres} recense les critères qu'un évaluateur combine pour délimiter le marché d'un sujet résidentiel ou multirésidentiel. Aucun ne suffit seul. Le type de propriété et le mode de détention sont les premiers : une copropriété divise, une maison en pleine propriété et un plex de trois logements relèvent de marchés différents parce que leurs acheteurs types diffèrent, le premier étant souvent un premier acheteur ou un investisseur locatif, le second un ménage familial, le troisième un propriétaire occupant qui finance son logement par deux loyers ou un petit investisseur ; le \cref{ch:32} développe ce dernier cas. La fourchette de prix vient ensuite, parce qu'elle détermine la capacité d'emprunt de l'acheteur type et donc le bassin des ménages concernés : au Québec, le seuil de l'assurance hypothécaire, les règles de mise de fonds et les tranches des droits de mutation créent des discontinuités de demande autour de certains prix. La géographie, enfin, est le critère le plus visible, mais il faut la lire à la bonne échelle : pour une maison de banlieue, le marché est souvent le secteur ou la municipalité ; pour un condominium du centre-ville, il peut se réduire à quelques rues ou même à un immeuble ; pour un immeuble de vingt logements, il s'étend à l'ensemble de l'île de Montréal, parce que l'investisseur type arbitre entre arrondissements. | ||||
| 36 | + | ||||
| 37 | +\begin{table}[htbp] | ||||
| 38 | +\caption{Critères de délimitation du marché et des sous-marchés d'un bien résidentiel ou multirésidentiel}\label{tab:15:criteres} | ||||
| 39 | +\centering\small | ||||
| 40 | +\begin{tabularx}{\textwidth}{@{}L{30mm}YY@{}} | ||||
| 41 | +\toprule | ||||
| 42 | +Critère & Question à poser & Exemples de frontières au Québec \\ | ||||
| 43 | +\midrule | ||||
| 44 | +Type et mode de détention & L'acheteur type du sujet considère-t-il l'autre type comme un substitut ? & Unifamiliale, copropriété divise, copropriété indivise, plex de 2 à 5 logements, immeuble de 6 logements et plus ; catégories statistiques de l'APCIQ et du Recensement \\ | ||||
| 45 | +Fourchette de prix et financement & Le même ménage peut-il financer les deux biens ? & Seuils de l'assurance hypothécaire et de la mise de fonds ; tranches des droits de mutation ; prix médian du secteur comme repère \\ | ||||
| 46 | +Géographie & À quelle échelle l'acheteur type arbitre-t-il ? & Secteurs Centris (ex. Hull, Aylmer, Gatineau, Buckingham/Masson-Angers, périphérie) ; zones SCHL ; arrondissements ; quartiers et rues ; bassins scolaires et axes de transport \\ | ||||
| 47 | +Caractéristiques physiques & La taille, l'âge ou la qualité changent-ils le profil d'acheteur ? & Plain-pied vs à étages ; neuf vs ancien ; maison patrimoniale ; terrain riverain \\ | ||||
| 48 | +Temps & Les conditions de marché de la période des comparables sont-elles celles de la date d'évaluation ? & Avant/après un changement de taux ; avant/après le dépôt d'un rôle ; fenêtre de 12 à 24 mois selon la vitesse des prix \\ | ||||
| 49 | +Droits et contraintes & Les biens transmettent-ils le même faisceau de droits ? & Baux en place et encadrement des loyers ; servitudes ; zonage ; copropriété avec restrictions de location \\ | ||||
| 50 | +Acheteur type & Qui achète ce bien, avec quel horizon et quel financement ? & Propriétaire occupant, premier acheteur, investisseur locatif, promoteur, acheteur institutionnel \\ | ||||
| 51 | +\bottomrule | ||||
| 52 | +\end{tabularx} | ||||
| 53 | +\tabsource{synthèse de l'auteur d'après \textcite{appraisal2026}, \textcite{bourassa1999} et \textcite{kestensTheriaultDesrosiers2006}.} | ||||
| 54 | +\end{table} | ||||
| 55 | + | ||||
| 56 | +\begin{quebec} | ||||
| 57 | +Les sources publiques québécoises imposent leurs propres découpages, qui ne coïncident ni entre eux ni avec les frontières économiques. L'APCIQ publie ses statistiques Centris par région métropolitaine, par agglomération et par « secteur » de courtage : pour la RMR de Gatineau, cinq secteurs, Aylmer, Hull, Gatineau, Buckingham/Masson-Angers et la périphérie, avec, au troisième trimestre de 2026, respectivement 201, 174, 346, 108 et 215 ventes résidentielles et des prix médians d'unifamiliales de \dollars{530000}, \dollars{475000}, \dollars{464900}, \dollars{395000} et \dollars{530000} \parencite{apciqgatineaut32026}. La SCHL découpe les mêmes territoires en zones de l'Enquête sur les logements locatifs qui ne suivent pas les secteurs de courtage : la RMR de Gatineau compte quatre zones, Hull, Aylmer, Gatineau et périphérie, et celle de Montréal trente-neuf, dont la zone 9, Rosemont/La Petite-Patrie, où se situe l'immeuble du cas 3 \parencite{schlrmltables2025}. Les rôles d'évaluation foncière, enfin, raisonnent par unités de voisinage, et le Recensement par secteurs de recensement et aires de diffusion. L'évaluateur qui construit une étude de marché doit expliciter la correspondance entre ces découpages et le marché du sujet, et il ne doit citer chaque chiffre qu'avec son découpage d'origine. Les conditions d'utilisation de l'APCIQ exigent que toute reproduction mentionne la source, « APCIQ par le système Centris », et interdisent l'usage commercial sans consentement écrit ; celles de la SCHL autorisent la citation de chiffres isolés avec attribution mais ne constituent pas une licence ouverte, de sorte que les tableaux ne doivent pas être redistribués tels quels \parencite{apciqconditions,schlLocatif2025}. Sources consultées le 31 octobre 2026. | ||||
| 58 | +\end{quebec} | ||||
| 59 | + | ||||
| 60 | +\subsection{Segmentation a priori et segmentation révélée} | ||||
| 61 | + | ||||
| 62 | +Deux voies mènent à une partition du marché. La \motcle{segmentation a priori} applique les critères du \cref{tab:15:criteres} à partir de la connaissance du terrain : l'évaluateur sait que la rivière des Outaouais sépare des marchés, que tel boulevard marque la frontière entre deux bassins scolaires, que les maisons d'un ancien village annexé n'attirent pas les mêmes acheteurs que celles du lotissement voisin. Cette connaissance est précieuse, mais elle a deux faiblesses : elle n'est pas reproductible d'un évaluateur à l'autre, et elle peut survivre aux changements du marché, une frontière qui comptait il y a vingt ans n'ayant plus de sens après l'ouverture d'un pont ou d'une ligne de transport. La \motcle{segmentation révélée} cherche dans les données elles-mêmes les regroupements de biens semblables, par des méthodes de classification non supervisée, puis vérifie si ces regroupements correspondent à des structures de prix différentes. Elle est reproductible et actuelle, mais elle ne connaît que les variables qu'on lui donne et elle peut regrouper des biens semblables par leurs attributs qui n'appartiennent pas au même marché, parce qu'elle ignore l'acheteur type. La pratique raisonnable, que recommandent \textcite{bourassaHoesliPeng2003} et que suivent les manuels d'évaluation de masse \parencite{gloudemansAlmy2011,iaaomass2025}, consiste à partir d'une segmentation a priori, à la confronter aux données par la classification et par les tests de stabilité des coefficients, et à ne retenir une partition plus fine ou différente que si elle améliore la prédiction hors échantillon. C'est le programme des \cref{sec:15:classification,sec:15:chow}. | ||||
| 63 | + | ||||
| 64 | +\section{L'étude de marché : offre, demande et absorption}\label{sec:15:etude} | ||||
| 65 | + | ||||
| 66 | +\subsection{Six étapes et leurs sources} | ||||
| 67 | + | ||||
| 68 | +L'\motcle{étude de marché} (\emph{market analysis}) d'un dossier d'évaluation répond à trois questions dans l'ordre : quelle est la demande structurelle pour le type de bien du sujet dans son territoire, quelle est l'offre qui lui fait concurrence, et à quel rythme l'offre et la demande se rencontrent-elles à la date d'évaluation. Le \cref{ch:04} en a donné l'exemple pour deux régions métropolitaines ; le \cref{tab:15:etapes} systématise la démarche en six étapes, avec pour chacune les indicateurs à calculer et les sources québécoises qui les fournissent. Les deux premières étapes décrivent les fondamentaux, les deux suivantes la conjoncture de la revente et des prix, la cinquième le marché locatif, et la sixième tire la lecture d'ensemble qui conditionne les choix méthodologiques : fenêtre temporelle des comparables, signe de l'ajustement de conditions du marché, provision pour inoccupation, prudence de la fourchette de valeur. Les modèles d'offre et de demande qui donnent leur sens à ces indicateurs, en particulier le schéma à quatre quadrants de \textcite{dipasqualeWheaton1992} et la dynamique stock-flux de \textcite{wheaton1999}, ont été exposés au \cref{ch:03} ; on se concentre ici sur la mesure. | ||||
| 69 | + | ||||
| 70 | +\begin{table}[htbp] | ||||
| 71 | +\caption{Les six étapes d'une étude de marché résidentiel au Québec : indicateurs et sources}\label{tab:15:etapes} | ||||
| 72 | +\centering\small | ||||
| 73 | +\begin{tabularx}{\textwidth}{@{}L{26mm}YL{46mm}@{}} | ||||
| 74 | +\toprule | ||||
| 75 | +Étape & Indicateurs & Sources publiques (découpage, périodicité) \\ | ||||
| 76 | +\midrule | ||||
| 77 | +1. Demande structurelle & Population et ménages, croissance, part des locataires, revenu, projections & Statistique Canada (Recensement, estimations annuelles par RMR) ; ISQ (projections) \\ | ||||
| 78 | +2. Prix et volumes & Médianes par type, ventes, variation annuelle, hiérarchie des segments & APCIQ/Centris (RMR, agglomération, secteur ; trimestriel) ; JLR (Registre foncier ; mensuel) \\ | ||||
| 79 | +3. Conjoncture de la revente & Inscriptions en vigueur, mois d'inventaire, taux d'absorption, délai de vente, ratio prix vendu/demandé & APCIQ/Centris (trimestriel) ; données internes des courtiers pour le ratio prix vendu/demandé \\ | ||||
| 80 | +4. Tendance des prix & Indices de prix (ventes répétées, prix des logements neufs), accélération ou décélération & Teranet--Banque Nationale (RMR ; mensuel) ; Statistique Canada, IPLN ; rôles d'évaluation (triennal) \\ | ||||
| 81 | +5. Marché locatif & Univers, loyers par taille, inoccupation par taille de logement et d'immeuble, variation « même échantillon », rotation, offre neuve & SCHL, Enquête sur les logements locatifs (RMR, zone ; octobre, publiée en décembre) ; Perspectives du marché de l'habitation \\ | ||||
| 82 | +6. Lecture & Phase du cycle, direction de l'ajustement de conditions du marché, fenêtre temporelle, provision d'inoccupation, largeur de la fourchette & Synthèse de l'évaluateur, documentée au rapport \\ | ||||
| 83 | +\bottomrule | ||||
| 84 | +\end{tabularx} | ||||
| 85 | +\tabsource{synthèse de l'auteur ; voir \textcite{apciqt32026}, \textcite{schlLocatif2025}, \textcite{teranet202609} et \textcite{jlr202609} pour les publications de l'automne 2026.} | ||||
| 86 | +\end{table} | ||||
| 87 | + | ||||
| 88 | +\subsection{Indicateurs de flux et indicateurs de stock} | ||||
| 89 | + | ||||
| 90 | +Les indicateurs de la troisième étape méritent une formalisation, parce qu'ils sont souvent cités sans que l'on sache ce qu'ils mesurent. Le marché de la revente est un système de files d'attente : des propriétés entrent dans l'inventaire lorsqu'elles sont inscrites, elles en sortent lorsqu'elles sont vendues ou retirées, et à tout instant un stock de propriétés attend preneur. Trois grandeurs décrivent ce système : le flux de ventes $V$, mesuré par mois ou par trimestre ; le stock d'\motcle{inscriptions en vigueur} $I$, mesuré à une date ; et la durée de séjour d'une propriété dans l'inventaire. Le \motcle{nombre de mois d'inventaire}, déjà introduit aux \cref{ch:03,ch:04}, rapporte le stock au flux : | ||||
| 91 | +\begin{equation}\label{eq:15:mi} | ||||
| 92 | +\mathit{MI} = \frac{I}{V_{\text{mois}}} = \frac{I}{V_{\text{trim}}/3}, | ||||
| 93 | +\end{equation} | ||||
| 94 | +et son inverse, le \motcle{taux d'absorption} mensuel, mesure la part du stock qui s'écoule chaque mois : | ||||
| 95 | +\begin{equation}\label{eq:15:absorption} | ||||
| 96 | +a = \frac{V_{\text{mois}}}{I} = \frac{1}{\mathit{MI}} . | ||||
| 97 | +\end{equation} | ||||
| 98 | +Ces deux indicateurs sont des quotients d'un stock par un flux ; ils ont la dimension d'un temps, ou de l'inverse d'un temps, et c'est ce qui leur donne leur interprétation. Si le système était en régime stationnaire et si toute propriété inscrite finissait par se vendre, la relation de Little, connue en théorie des files d'attente, dirait que le stock moyen égale le flux de sorties multiplié par la durée moyenne de séjour, | ||||
| 99 | +\begin{equation}\label{eq:15:little} | ||||
| 100 | +I = V_{\text{mois}} \times \bar{D}, \qquad\text{d'où}\qquad \mathit{MI} = \bar{D}, | ||||
| 101 | +\end{equation} | ||||
| 102 | +et le nombre de mois d'inventaire serait exactement la durée moyenne passée dans l'inventaire par une propriété. Or le \motcle{délai de vente} médian publié par l'APCIQ, qui mesure le temps écoulé entre l'inscription et la promesse d'achat acceptée pour les propriétés \emph{vendues} au cours du trimestre, est presque toujours très inférieur au nombre de mois d'inventaire. Au troisième trimestre de 2026, le délai médian d'une unifamiliale était de 40 jours à Montréal, soit 1,3 mois, alors que l'inventaire représentait 6,6 mois de ventes \parencite{apciqt32026} ; le rapport entre les deux est de cinq. L'écart a deux causes, et toutes deux instruisent l'évaluateur. La première est la censure : le délai de vente n'est observé que pour les propriétés qui se sont vendues, et il ignore celles qui attendent encore, qui seront retirées sans vente ou qui seront réinscrites après une baisse de prix ; la durée de séjour de l'ensemble des inscriptions est donc nécessairement plus longue que celle des seules propriétés vendues. La seconde est l'hétérogénéité : dans un même marché, les propriétés bien évaluées et bien situées se vendent en quelques semaines, tandis que les propriétés surévaluées ou atypiques s'accumulent dans l'inventaire ; le rapport du nombre de mois d'inventaire au délai médian, que l'on peut appeler ratio stock sur flux, mesure l'importance de cette queue d'inscriptions qui ne trouvent pas preneur au prix demandé. Un ratio élevé signale un marché où une large part de l'offre est hors du prix, ce qui précède souvent une baisse des prix demandés et, avec retard, des prix vendus. | ||||
| 103 | + | ||||
| 104 | +Le \motcle{ratio du prix vendu au prix demandé} complète ces indicateurs en mesurant la marge de négociation : | ||||
| 105 | +\begin{equation}\label{eq:15:rvd} | ||||
| 106 | +\rho_j = \frac{P_j}{P^{\text{dem}}_j}, \qquad \bar\rho = \operatorname{méd}_j\, \rho_j , | ||||
| 107 | +\end{equation} | ||||
| 108 | +où $P^{\text{dem}}_j$ est le prix demandé de la propriété $j$ et $P_j$ son prix de vente. Un ratio médian inférieur à l'unité indique un marché où les acheteurs négocient ; un ratio supérieur à l'unité, observé au Québec en 2021 et au début de 2022, signale des surenchères. La définition cache une ambiguïté : le prix demandé peut être le prix initial à l'inscription ou le dernier prix affiché après révisions, et les deux conventions donnent des ratios différents, le premier étant plus bas dans un marché où les vendeurs révisent à la baisse. L'APCIQ ne publie pas ce ratio dans ses communiqués et ses baromètres trimestriels, et aucune source publique québécoise consultée pour cet ouvrage ne le diffuse ; il provient des bases de données des courtiers et des services d'évaluation qui y ont accès. Lorsque l'évaluateur en dispose, il doit déclarer la convention de prix demandé, la période et le segment ; lorsqu'il n'en dispose pas, il décrit la marge de négociation qualitativement, à partir des délais et de l'inventaire, sans inventer de chiffre. | ||||
| 109 | + | ||||
| 110 | +\subsection{Les marchés métropolitains du Québec à l'automne 2026} | ||||
| 111 | + | ||||
| 112 | +Le \cref{tab:15:indicateurs} applique ces définitions aux chiffres publiés par l'APCIQ pour le troisième trimestre de 2026, et la \cref{fig:15:inventaire} les représente. Les mois d'inventaire vont de 3,1 à Québec à 6,6 à Montréal ; le taux d'absorption mensuel correspondant va de \pct{32.7} à \pct{15.2}, ce qui veut dire qu'un tiers du stock de la RMR de Québec trouve preneur chaque mois contre un sixième de celui de Montréal. Le ratio stock sur flux, calculé pour les trois RMR dont le délai de vente est publié, est de 3,2 à Québec, de 5,0 à Montréal et de 5,8 à Gatineau : c'est à Gatineau que la queue d'inscriptions hors du prix est la plus longue relativement aux ventes qui se concluent, ce qui est cohérent avec une hausse de \pct{42} des inscriptions sur un an et une baisse de \pct{3} du prix médian des unifamiliales \parencite{apciqgatineaut32026}. Pour l'évaluateur du cas 1, dont la date d'évaluation est le 1\ier{} septembre 2026, ces indicateurs ont trois conséquences : la fenêtre temporelle des comparables doit être courte et l'ajustement de conditions du marché, s'il est appliqué à des ventes de 2025, doit être nul ou légèrement négatif plutôt que positif ; le délai d'exposition raisonnable à mentionner au rapport est de l'ordre d'un à deux mois pour une propriété correctement évaluée, mais le risque d'un délai beaucoup plus long existe si le prix demandé excède le marché ; et la fourchette de valeur doit être plus large qu'en marché tendu, parce que la dispersion des prix autour de la valeur croît avec la marge de négociation. | ||||
| 113 | + | ||||
| 114 | +\begin{table}[htbp] | ||||
| 115 | +\caption{Indicateurs de conjoncture de la revente, troisième trimestre de 2026, propriétés résidentielles vendues par courtier}\label{tab:15:indicateurs} | ||||
| 116 | +\centering\footnotesize\setlength{\tabcolsep}{4pt} | ||||
| 117 | +\begin{tabular}{@{}lS[table-format=1.1]S[table-format=2.1]S[table-format=2.0]S[table-format=2.0]S[table-format=2.0]S[table-format=1.1]@{}} | ||||
| 118 | +\toprule | ||||
| 119 | +Territoire & {Mois d'inv.} & {Absorption (\%/mois)} & {Délai unif. (j)} & {Délai copro. (j)} & {Délai plex (j)} & {Stock/flux} \\ | ||||
| 120 | +\midrule | ||||
| 121 | +Province de Québec & 6.1 & 16.5 & 45 & 58 & 48 & 4.1 \\ | ||||
| 122 | +RMR de Montréal & 6.6 & 15.2 & 40 & 61 & 51 & 5.0 \\ | ||||
| 123 | +RMR de Québec & 3.1 & 32.7 & 29 & 34 & 30 & 3.2 \\ | ||||
| 124 | +RMR de Gatineau & 6.5 & 15.4 & 34 & 36 & 38 & 5.8 \\ | ||||
| 125 | +RMR de Sherbrooke & 4.3 & 23.0 & {---} & {---} & {---} & {---} \\ | ||||
| 126 | +RMR de Trois-Rivières & 3.6 & 27.7 & {---} & {---} & {---} & {---} \\ | ||||
| 127 | +RMR de Saguenay & 4.0 & 24.8 & {---} & {---} & {---} & {---} \\ | ||||
| 128 | +\bottomrule | ||||
| 129 | +\end{tabular} | ||||
| 130 | +\tabsource{ventes, inscriptions en vigueur et délais de vente médians : APCIQ par le système Centris, communiqué du 14 octobre 2026 et baromètres du troisième trimestre de 2026 \parencite{apciqt32026,apciqgatineaut32026}, consultés le 31 octobre 2026 ; mois d'inventaire (\cref{eq:15:mi}), taux d'absorption (\cref{eq:15:absorption}) et ratio stock sur flux (mois d'inventaire divisés par le délai médian de l'unifamiliale converti en mois) : calculs de l'auteur, \texttt{analysis/python/cases/ch15\_segmentation.py}. Les délais ne sont pas publiés pour les trois plus petites RMR dans les documents consultés.} | ||||
| 131 | +\end{table} | ||||
| 132 | + | ||||
| 133 | +\begin{figure}[htbp] | ||||
| 134 | +\centering | ||||
| 135 | +\includegraphics[width=\textwidth]{ch15/ch15-fig-mois-inventaire.pdf} | ||||
| 136 | +\caption{Mois d'inventaire des sept marchés métropolitains du Québec au troisième trimestre de 2026, avec le délai de vente médian de l'unifamiliale lorsqu'il est publié. Les bandes rappellent les seuils d'usage, qui sont des conventions de métier et non des normes ; Montréal et Gatineau ont franchi le seuil de six mois tandis que Québec reste nettement en deçà de quatre.}\label{fig:15:inventaire} | ||||
| 137 | +\figsource{APCIQ par le système Centris, communiqué du 14 octobre 2026 et baromètres T3 2026 \parencite{apciqt32026,apciqgatineaut32026}, consultés le 31 octobre 2026 ; calculs de l'auteur, script \texttt{analysis/python/figures/ch15\_figures.py}.} | ||||
| 138 | +\end{figure} | ||||
| 139 | + | ||||
| 140 | +Les seuils qui délimitent les bandes de la \cref{fig:15:inventaire}, environ quatre mois en deçà desquels le marché est dit favorable aux vendeurs et six mois au-delà desquels il est dit favorable aux acheteurs, sont des usages de la pratique canadienne du courtage ; ils ne reposent sur aucune norme et ils varient selon le segment, un marché de condominiums neufs supportant un inventaire plus long qu'un marché d'unifamiliales. Ils sont néanmoins utiles comme repères, à condition de les présenter comme tels dans le rapport et d'y joindre la tendance : un marché à cinq mois d'inventaire dont l'offre augmente de \pct{40} par année n'est pas dans la même situation qu'un marché à cinq mois dont l'offre diminue. | ||||
| 141 | + | ||||
| 142 | +\subsection{Descendre à l'échelle du sous-marché} | ||||
| 143 | + | ||||
| 144 | +Les indicateurs métropolitains sont nécessaires mais insuffisants : le sujet se vend dans un secteur, non dans une RMR. Le baromètre de l'APCIQ pour Gatineau donne les ventes et les médianes par secteur, mais ni les inscriptions ni les délais, de sorte que les mois d'inventaire ne peuvent pas être calculés au niveau du secteur à partir des seules sources publiques ; il faut pour cela l'accès aux données de courtage. Ce que les chiffres publics permettent, c'est de situer le sous-marché du sujet dans la hiérarchie des prix et des volumes. Le \cref{tab:15:parts} compare la répartition des 1\,044 ventes résidentielles du troisième trimestre de 2026 entre les secteurs de Gatineau à celle des 600 ventes du jeu synthétique du cas 1. Le secteur Gatineau pèse un tiers des ventes dans les deux cas ; Aylmer un cinquième ; Buckingham et Masson-Angers réunis un dixième dans le marché réel et un septième dans le jeu synthétique ; Hull, en revanche, représente \pct{16.7} des ventes réelles mais \pct{31} des ventes synthétiques, et la périphérie, qui compte pour un cinquième du marché réel, n'existe pas dans le jeu. Cette surreprésentation de Hull est un choix de construction, le sujet y étant situé et le \cref{ch:16} ayant besoin d'un bassin suffisant de candidats dans son secteur ; elle doit être connue du lecteur avant que les segments statistiques des sections suivantes ne soient interprétés, parce qu'un segment qui regroupe des ventes de Hull et du secteur Gatineau reflète en partie cette composition. | ||||
| 145 | + | ||||
| 146 | +\begin{table}[htbp] | ||||
| 147 | +\caption{Répartition des ventes résidentielles entre les secteurs de la RMR de Gatineau : marché réel du troisième trimestre de 2026 et jeu synthétique du cas 1}\label{tab:15:parts} | ||||
| 148 | +\centering\small | ||||
| 149 | +\begin{tabular}{@{}lS[table-format=3.0]S[table-format=2.1]S[table-format=3.0]S[table-format=2.1]S[table-format=6.0]@{}} | ||||
| 150 | +\toprule | ||||
| 151 | +Secteur & {Ventes T3 2026} & {Part (\%)} & {Ventes synth.} & {Part (\%)} & {Médiane unif. T3 2026 (\$)} \\ | ||||
| 152 | +\midrule | ||||
| 153 | +Gatineau & 346 & 33.1 & 200 & 33.3 & 464900 \\ | ||||
| 154 | +Hull & 174 & 16.7 & 186 & 31.0 & 475000 \\ | ||||
| 155 | +Aylmer & 201 & 19.3 & 125 & 20.8 & 530000 \\ | ||||
| 156 | +Buckingham / Masson-Angers & 108 & 10.3 & 89 & 14.8 & 395000 \\ | ||||
| 157 | +Périphérie & 215 & 20.6 & 0 & 0.0 & 530000 \\ | ||||
| 158 | +\midrule | ||||
| 159 | +Total & 1044 & 100.0 & 600 & 100.0 & {---} \\ | ||||
| 160 | +\bottomrule | ||||
| 161 | +\end{tabular} | ||||
| 162 | +\tabsource{ventes et médianes réelles : APCIQ par le système Centris, baromètre de la RMR de Gatineau, T3 2026 \parencite{apciqgatineaut32026} ; ventes synthétiques : \synth{\texttt{data/synthetic/cas1\_gatineau\_ventes.csv}, janvier 2023 à août 2026, graine 20261031} ; calculs : \texttt{ch15\_segmentation.py}.} | ||||
| 163 | +\end{table} | ||||
| 164 | + | ||||
| 165 | +\begin{pratique} | ||||
| 166 | +L'étude de marché d'un rapport d'évaluation résidentiel tient en une ou deux pages, mais chaque phrase y est sourcée. Elle indique le découpage retenu pour le marché du sujet et la raison de ce choix ; les volumes et les médianes du dernier trimestre publié, avec leur variation annuelle ; les mois d'inventaire et le délai de vente, avec la convention de calcul ; la tendance des prix selon au moins une source indépendante du courtage ; et, pour un immeuble de revenu, les loyers, l'inoccupation et la rotation de la zone. Elle se termine par les conséquences méthodologiques : fenêtre temporelle des comparables, signe attendu de l'ajustement de conditions du marché, délai d'exposition raisonnable, largeur de la fourchette. Les définitions professionnelles de la valeur marchande supposent une « mise en vente d'une durée suffisante » \parencite[Intro-11]{oeaqNormes} : l'étude de marché est ce qui permet de dire ce que « suffisante » veut dire à la date d'évaluation. | ||||
| 167 | +\end{pratique} | ||||
| 168 | + | ||||
| 169 | +\section{La segmentation statistique du marché}\label{sec:15:classification} | ||||
| 170 | + | ||||
| 171 | +\begin{synthetique} | ||||
| 172 | +Les sections qui suivent utilisent les 600 ventes synthétiques du cas 1, décrites dans \texttt{data/synthetic/cas1\_gatineau\_ventes.csv} et générées par \texttt{analysis/python/traite/synth.py} (graine 20261031) selon les lois déclarées dans \texttt{data/synthetic/README.md} : le logarithme du prix est une fonction commune à tous les secteurs des attributs (superficie, terrain, âge, qualité, garage, sous-sol, piscine, type), plus une prime de secteur calibrée sur les médianes publiées par l'APCIQ, plus une tendance temporelle, plus un bruit d'écart-type 0,085. Les coordonnées sont fictives. Cette construction est importante pour la lecture des résultats : \emph{par construction}, les coefficients des attributs sont identiques d'un secteur à l'autre et seules les constantes diffèrent, de sorte que l'on connaît la réponse que le test de Chow devrait donner. Tous les chiffres sont reproduits par \texttt{analysis/python/cases/ch15\_segmentation.py} ; les figures par \texttt{analysis/python/figures/ch15\_figures.py}. | ||||
| 173 | +\end{synthetique} | ||||
| 174 | + | ||||
| 175 | +\subsection{Pourquoi segmenter un modèle de prix} | ||||
| 176 | + | ||||
| 177 | +Le modèle hédonique de référence de l'ouvrage, estimé au \cref{ch:18} sur les 600 ventes et fourni par \texttt{traite.cas1.hedonique}, explique le logarithme du prix par les attributs, des indicatrices de secteur et une tendance mensuelle ; il atteint un $R^2$ de 0,853 et un écart-type résiduel de 0,0830. Il suppose que le prix d'un mètre carré supplémentaire, d'une année d'âge ou d'un échelon de qualité est le même à Aylmer, à Hull et à Masson-Angers, et que seul le niveau général des prix diffère. Segmenter le modèle, c'est relâcher cette hypothèse en estimant l'\cref{eq:15:sousmarche} séparément dans chaque sous-marché $g$ : | ||||
| 178 | +\begin{equation}\label{eq:15:segmente} | ||||
| 179 | +\ln P_i = \alpha_{g(i)} + \mathbf{x}_i\T \boldsymbol{\beta}_{g(i)} + \tau\, t_i + \varepsilon_i, \qquad i \in g . | ||||
| 180 | +\end{equation} | ||||
| 181 | +Le gain est une réduction du biais si les structures diffèrent réellement ; le coût est une augmentation de la variance, puisque chaque équation est estimée sur une fraction de l'échantillon. Dans le cas 1, le secteur de Buckingham compte 42 ventes et celui de Masson-Angers 47, pour douze coefficients à estimer : les prix implicites qui en sortiraient auraient des erreurs-types trois à cinq fois plus grandes que celles du modèle commun. L'arbitrage est le même que celui du \cref{ch:16} pour le nombre de comparables : il faut segmenter autant que les structures l'exigent et pas davantage, et la décision doit s'appuyer sur deux outils, un test de l'hypothèse de coefficients communs et une mesure de la précision hors échantillon. | ||||
| 182 | + | ||||
| 183 | +Avant de tester, il faut toutefois disposer d'une partition. La segmentation a priori par secteur en fournit une ; la classification statistique en propose d'autres, construites à partir de la ressemblance des biens plutôt que des frontières administratives. Les deux familles de méthodes les plus utilisées en évaluation, les k-moyennes et la classification hiérarchique ascendante, sont exposées ci-dessous. | ||||
| 184 | + | ||||
| 185 | +\subsection{Les k-moyennes et la classification hiérarchique} | ||||
| 186 | + | ||||
| 187 | +Soit $\mathbf{z}_i \in \mathbb{R}^p$ le vecteur des variables de classification du bien $i$, centrées et réduites pour que chaque variable pèse du même poids quelle que soit son unité. L'algorithme des \motcle{k-moyennes} (\emph{k-means}), formalisé par MacQueen en 1967, cherche la partition en $k$ groupes $C_1, \dots, C_k$ qui minimise l'inertie intra-groupe, c'est-à-dire la somme des carrés des distances de chaque point au centre de son groupe : | ||||
| 188 | +\begin{equation}\label{eq:15:kmeans} | ||||
| 189 | +\min_{C_1,\dots,C_k}\ \sum_{g=1}^{k} \sum_{i \in C_g} \norm{\mathbf{z}_i - \bar{\mathbf{z}}_g}^2, \qquad \bar{\mathbf{z}}_g = \frac{1}{\abs{C_g}} \sum_{i \in C_g} \mathbf{z}_i . | ||||
| 190 | +\end{equation} | ||||
| 191 | +Le problème est combinatoire et l'algorithme ne garantit qu'un optimum local : partant de $k$ centres initiaux, il affecte chaque point au centre le plus proche, recalcule les centres, et recommence jusqu'à stabilité. On le relance donc depuis plusieurs initialisations, vingt dans les calculs de ce chapitre, et l'on retient la meilleure. La \motcle{classification hiérarchique} ascendante procède autrement : elle part de $n$ groupes d'un seul bien et fusionne à chaque étape les deux groupes les plus proches, jusqu'à n'en former qu'un. Le critère de Ward (1963), le plus utilisé pour des variables continues, fusionne les deux groupes dont la réunion augmente le moins l'inertie intra-groupe : | ||||
| 192 | +\begin{equation}\label{eq:15:ward} | ||||
| 193 | +\Delta(C_a, C_b) = \frac{\abs{C_a}\,\abs{C_b}}{\abs{C_a} + \abs{C_b}}\ \norm{\bar{\mathbf{z}}_a - \bar{\mathbf{z}}_b}^2 , | ||||
| 194 | +\end{equation} | ||||
| 195 | +de sorte qu'il poursuit le même objectif que les k-moyennes par un chemin différent, déterministe et hiérarchique. La suite des fusions se représente par un \motcle{dendrogramme}, arbre dont la hauteur de chaque nœud est la distance de fusion $\Delta$ ; couper l'arbre à une hauteur donnée produit une partition, et les grands sauts de hauteur entre deux fusions successives signalent les nombres de groupes « naturels ». | ||||
| 196 | + | ||||
| 197 | +Le choix du nombre de segments $k$ est le point délicat. L'inertie intra-groupe diminue mécaniquement avec $k$ et ne peut servir de critère ; on recourt à la \motcle{silhouette} proposée par Rousseeuw en 1987, qui compare pour chaque bien sa distance moyenne aux membres de son propre groupe à sa distance moyenne aux membres du groupe voisin le plus proche. | ||||
| 198 | + | ||||
| 199 | +\begin{definition}{Silhouette}{silhouette} | ||||
| 200 | +Pour un bien $i$ affecté au groupe $C_g$, soit $a_i$ la distance moyenne de $i$ aux autres membres de $C_g$ et $b_i$ la plus petite, sur les autres groupes $C_h$, des distances moyennes de $i$ aux membres de $C_h$. La silhouette de $i$ est | ||||
| 201 | +\begin{equation}\label{eq:15:silhouette} | ||||
| 202 | +s_i = \frac{b_i - a_i}{\max(a_i, b_i)} \in [-1, 1], | ||||
| 203 | +\end{equation} | ||||
| 204 | +et la silhouette moyenne d'une partition est $\bar s = n^{-1}\sum_i s_i$. Un $s_i$ proche de 1 indique un bien bien classé, loin du groupe voisin ; un $s_i$ proche de 0 un bien à la frontière de deux groupes ; un $s_i$ négatif un bien probablement mal classé. On retient le nombre de groupes qui maximise $\bar s$, sous réserve que les groupes aient un sens pour le marché. | ||||
| 205 | +\end{definition} | ||||
| 206 | + | ||||
| 207 | +La silhouette a l'avantage de ne dépendre que des distances, donc d'être comparable entre méthodes et entre nombres de groupes ; elle a l'inconvénient de favoriser les partitions en peu de groupes bien séparés, qui ne sont pas toujours les plus utiles. Des ordres de grandeur indicatifs circulent, une silhouette moyenne supérieure à 0,5 signalant une structure nette et une silhouette inférieure à 0,25 une structure faible ou artificielle ; ils n'ont pas valeur de norme. Pour comparer deux partitions entre elles, par exemple les segments statistiques et les secteurs a priori, on utilise l'indice de Rand ajusté de Hubert et Arabie (1985), qui vaut 1 si les deux partitions coïncident, 0 si leur concordance est celle du hasard, et prend des valeurs intermédiaires selon la proportion de paires de biens classées ensemble ou séparément dans les deux partitions. | ||||
| 208 | + | ||||
| 209 | +\subsection{Application aux 600 ventes du cas 1} | ||||
| 210 | + | ||||
| 211 | +Les variables de classification retenues sont de deux natures : les attributs du bien, logarithme de la superficie habitable, logarithme du terrain, âge, qualité et type ; et sa localisation, coordonnées projetées en kilomètres et distance au centre. Trois jeux ont été essayés, attributs seuls, coordonnées seules, et les deux réunis, parce que le résultat dépend de ce choix autant que de la méthode. Le \cref{tab:15:silhouette} donne, pour le jeu complet, la silhouette moyenne des k-moyennes et de Ward pour $k$ de 2 à 8, l'inertie des k-moyennes et l'indice de Rand ajusté entre les deux méthodes ; la \cref{fig:15:dendrogramme} montre le dendrogramme de Ward et la \cref{fig:15:silhouette} la silhouette moyenne pour les trois jeux de variables ainsi que le profil des silhouettes individuelles à $k = 5$. | ||||
| 212 | + | ||||
| 213 | +\begin{table}[htbp] | ||||
| 214 | +\caption{Silhouette moyenne et inertie selon le nombre de segments, 600 ventes du cas 1, variables : attributs et coordonnées centrés-réduits (données synthétiques)}\label{tab:15:silhouette} | ||||
| 215 | +\centering\small | ||||
| 216 | +\begin{tabular}{@{}S[table-format=1.0]S[table-format=1.3]S[table-format=1.3]S[table-format=4.0]S[table-format=1.3]@{}} | ||||
| 217 | +\toprule | ||||
| 218 | +{$k$} & {$\bar s$ k-moyennes} & {$\bar s$ Ward} & {Inertie k-moyennes} & {ARI k-moyennes / Ward} \\ | ||||
| 219 | +\midrule | ||||
| 220 | +2 & 0.417 & 0.417 & 3261 & 1.000 \\ | ||||
| 221 | +3 & 0.225 & 0.225 & 2749 & 1.000 \\ | ||||
| 222 | +4 & 0.187 & 0.157 & 2548 & 0.765 \\ | ||||
| 223 | +5 & 0.188 & 0.156 & 2378 & 0.476 \\ | ||||
| 224 | +6 & 0.185 & 0.149 & 2238 & 0.569 \\ | ||||
| 225 | +7 & 0.174 & 0.149 & 2138 & 0.478 \\ | ||||
| 226 | +8 & 0.181 & 0.159 & 2035 & 0.498 \\ | ||||
| 227 | +\bottomrule | ||||
| 228 | +\end{tabular} | ||||
| 229 | +\tabsource{\synth{\texttt{analysis/python/cases/ch15\_segmentation.py} ; k-moyennes : 20 initialisations, graine 20261031 ; Ward : \texttt{scipy.cluster.hierarchy} ; ARI : indice de Rand ajusté entre les deux partitions au même $k$.}} | ||||
| 230 | +\end{table} | ||||
| 231 | + | ||||
| 232 | +\begin{figure}[htbp] | ||||
| 233 | +\centering | ||||
| 234 | +\includegraphics[width=\textwidth]{ch15/ch15-fig-dendrogramme.pdf} | ||||
| 235 | +\caption{Dendrogramme de Ward des 600 ventes synthétiques du cas 1 (attributs et coordonnées centrés-réduits), tronqué à trente grappes terminales. La fusion finale, de loin la plus coûteuse, sépare les ventes de l'est de la RMR des autres ; les coupes à $k = 2$ et $k = 5$ sont indiquées. Les hauteurs intermédiaires décroissent sans saut marqué, signe d'une structure faible au-delà de deux groupes.}\label{fig:15:dendrogramme} | ||||
| 236 | +\figsource{\synth{script \texttt{analysis/python/figures/ch15\_figures.py}, graine 20261031}} | ||||
| 237 | +\end{figure} | ||||
| 238 | + | ||||
| 239 | +\begin{figure}[htbp] | ||||
| 240 | +\centering | ||||
| 241 | +\includegraphics[width=\textwidth]{ch15/ch15-fig-silhouette.pdf} | ||||
| 242 | +\caption{(a) Silhouette moyenne des k-moyennes selon le nombre de segments, pour trois jeux de variables : les attributs seuls ne révèlent aucune structure, les coordonnées seules en révèlent une nette, et le jeu complet se situe entre les deux. (b) Profil des silhouettes individuelles à $k = 5$ pour le jeu complet : les segments sont peu séparés et plusieurs ventes ont une silhouette négative.}\label{fig:15:silhouette} | ||||
| 243 | +\figsource{\synth{script \texttt{analysis/python/figures/ch15\_figures.py}, graine 20261031}} | ||||
| 244 | +\end{figure} | ||||
| 245 | + | ||||
| 246 | +Trois enseignements se dégagent. Le premier est que la structure la plus nette est à deux groupes : la silhouette moyenne vaut 0,417 à $k = 2$ et tombe à 0,225 dès $k = 3$, puis stagne autour de 0,18 ; les k-moyennes et Ward coïncident exactement jusqu'à $k = 3$ et divergent ensuite, ce qui est un autre signe que la structure au-delà de deux ou trois groupes est fragile. Le segment qui se détache regroupe les 89 ventes de Buckingham et de Masson-Angers, à une trentaine de kilomètres du centre, dont le prix médian de \dollars{371000} et le prix médian au mètre carré de \parmsq{2684} contrastent avec les \dollars{495500} et \parmsq{3529} des 511 autres ventes. Le deuxième enseignement est que cette structure est géographique : avec les coordonnées seules, la silhouette atteint 0,735 à $k = 2$ et reste à 0,672 à $k = 5$, où la partition reproduit presque exactement les cinq secteurs, avec un indice de Rand ajusté de 0,986 ; avec les attributs seuls, elle plafonne à 0,221 et la partition n'a aucun rapport avec les secteurs, l'indice de Rand ajusté étant de 0,001. Autrement dit, les maisons du jeu synthétique ne forment pas de « types » distincts par leur taille, leur âge et leur qualité, qui varient continûment, mais elles forment des grappes spatiales qui sont les secteurs. Le troisième enseignement concerne le jeu complet à $k = 5$ : la silhouette de 0,188 est faible, les segments mélangent les critères, et leur concordance avec les secteurs est médiocre, l'indice de Rand ajusté valant 0,124. Le \cref{tab:15:profil} et la \cref{fig:15:carte} en donnent le détail. | ||||
| 247 | + | ||||
| 248 | +\begin{table}[htbp] | ||||
| 249 | +\caption{Profil des cinq segments des k-moyennes (attributs et coordonnées) et croisement avec les secteurs, cas 1 (données synthétiques)}\label{tab:15:profil} | ||||
| 250 | +\centering\footnotesize\setlength{\tabcolsep}{3.5pt} | ||||
| 251 | +\begin{tabular}{@{}cS[table-format=3.0]S[table-format=3.1]S[table-format=2.0]S[table-format=1.2]S[table-format=2.1]S[table-format=6.0]S[table-format=4.0]S[table-format=3.0]S[table-format=3.0]S[table-format=3.0]S[table-format=2.0]S[table-format=2.0]@{}} | ||||
| 252 | +\toprule | ||||
| 253 | +Seg. & {$n$} & {Sup. méd. (m\textsuperscript{2})} & {Âge méd.} & {Qualité moy.} & {Dist. centre méd. (km)} & {Prix méd. (\$)} & {\$/m\textsuperscript{2} méd.} & {Hull} & {Gatineau} & {Aylmer} & {Buck.} & {M.-A.} \\ | ||||
| 254 | +\midrule | ||||
| 255 | +1 & 197 & 135.0 & 41 & 3.36 & 6.9 & 523500 & 3655 & 69 & 83 & 45 & 0 & 0 \\ | ||||
| 256 | +2 & 89 & 145.0 & 43 & 3.09 & 28.1 & 371000 & 2684 & 0 & 0 & 0 & 42 & 47 \\ | ||||
| 257 | +3 & 120 & 165.5 & 50 & 3.05 & 6.3 & 528000 & 3179 & 51 & 35 & 34 & 0 & 0 \\ | ||||
| 258 | +4 & 96 & 145.5 & 44 & 1.81 & 7.2 & 473250 & 3350 & 33 & 34 & 29 & 0 & 0 \\ | ||||
| 259 | +5 & 98 & 116.0 & 34 & 3.14 & 6.9 & 446750 & 3853 & 33 & 48 & 17 & 0 & 0 \\ | ||||
| 260 | +\bottomrule | ||||
| 261 | +\end{tabular} | ||||
| 262 | +\tabsource{\synth{\texttt{analysis/python/cases/ch15\_segmentation.py}, k-moyennes à $k = 5$, 20 initialisations, graine 20261031 ; silhouette moyenne 0,188 ; indice de Rand ajusté avec les secteurs 0,124.}} | ||||
| 263 | +\end{table} | ||||
| 264 | + | ||||
| 265 | +\begin{figure}[htbp] | ||||
| 266 | +\centering | ||||
| 267 | +\includegraphics[width=\textwidth]{ch15/ch15-fig-carte-segments.pdf} | ||||
| 268 | +\caption{Carte fictive des segments des k-moyennes : (a) le segment « Est » de la partition à deux groupes ; (b) à (f) les cinq segments de la partition à cinq groupes, chacun mis en évidence sur fond des autres ventes ; l'étoile marque le sujet. Seul le segment 2 est purement géographique ; les segments 1, 3, 4 et 5 découpent l'ouest de la RMR selon la qualité, la taille et l'âge et chevauchent les trois secteurs de Hull, Gatineau et Aylmer.}\label{fig:15:carte} | ||||
| 269 | +\figsource{\synth{script \texttt{analysis/python/figures/ch15\_figures.py}, coordonnées fictives projetées en kilomètres, graine 20261031}} | ||||
| 270 | +\end{figure} | ||||
| 271 | + | ||||
| 272 | +Le segment 2 est l'est de la RMR ; le segment 4 regroupe les maisons de qualité inférieure, de moyenne 1,81 sur une échelle de 1 à 5, où qu'elles se trouvent à l'ouest ; le segment 5 les petites maisons récentes, de \msq{116} et 34 ans en médiane ; le segment 3 les grandes maisons anciennes, de \msq{165} et 50 ans ; et le segment 1 les maisons de qualité supérieure à la moyenne. Ces segments ont une cohérence descriptive, mais ils ne sont pas des sous-marchés au sens de la \cref{def:sousmarche} : rien n'indique qu'une maison de qualité 2 à Aylmer et une maison de qualité 2 à Gatineau soient des substituts pour le même acheteur, ni que la relation entre le prix et la superficie y soit différente de celle des maisons de qualité 4. C'est la limite de la classification non supervisée : elle regroupe ce qui se ressemble, non ce qui se vend de la même façon. Seul un test portant sur la relation entre le prix et les attributs peut dire si une partition, a priori ou statistique, définit des sous-marchés. | ||||
| 273 | + | ||||
| 274 | +\section{Le test de Chow : une équation ou plusieurs ?}\label{sec:15:chow} | ||||
| 275 | + | ||||
| 276 | +\subsection{Dérivation} | ||||
| 277 | + | ||||
| 278 | +Le test proposé par Chow en 1960 compare l'ajustement d'un modèle linéaire estimé sous la contrainte de coefficients communs à celui du même modèle estimé librement dans chaque segment. Soit $n$ observations réparties en $G$ segments d'effectifs $n_1, \dots, n_G$, et $k_0$ régresseurs, constante comprise. Le modèle libre estime $G$ équations distinctes, soit $G k_0$ coefficients, et sa somme des carrés des résidus est $\mathit{SCR}_{\text{L}} = \sum_g \mathit{SCR}_g$. Le modèle contraint impose des restrictions linéaires sur ces coefficients ; dans la version \emph{classique}, il impose que tous les coefficients soient égaux entre segments, soit une seule équation à $k_0$ coefficients et $q_0 = (G-1)k_0$ restrictions ; dans la version que l'on appellera \emph{pentes}, plus pertinente pour l'évaluation, il laisse libre la constante de chaque segment et n'impose l'égalité que des $k_0 - 1$ pentes, soit $k_0 + G - 1$ coefficients et $q = (G-1)(k_0-1)$ restrictions. Dans les deux cas, la statistique de test est le rapport de l'accroissement de la somme des carrés dû aux restrictions, par restriction, à la variance résiduelle du modèle libre. | ||||
| 279 | + | ||||
| 280 | +\begin{proposition}{Test de Chow}{chow} | ||||
| 281 | +Sous les hypothèses du modèle linéaire classique, erreurs normales, indépendantes, de variance $\sigma^2$ identique dans tous les segments, et sous l'hypothèse nulle $H_0$ que les $q$ restrictions sont vraies, la statistique | ||||
| 282 | +\begin{equation}\label{eq:15:chow} | ||||
| 283 | +F = \frac{\left(\mathit{SCR}_{\text{C}} - \mathit{SCR}_{\text{L}}\right)/q}{\mathit{SCR}_{\text{L}}/(n - G k_0)} | ||||
| 284 | +\end{equation} | ||||
| 285 | +suit une loi de Fisher à $q$ et $n - Gk_0$ degrés de liberté, où $\mathit{SCR}_{\text{C}}$ est la somme des carrés des résidus du modèle contraint. On rejette $H_0$ au seuil $\alpha$ si $F$ dépasse le quantile $F_{1-\alpha}(q, n - Gk_0)$. | ||||
| 286 | +\end{proposition} | ||||
| 287 | +\begin{proof} | ||||
| 288 | +Le modèle libre s'écrit comme une seule régression empilée $\mathbf{y} = \mathbf{X}_{\text{L}} \boldsymbol{\theta} + \boldsymbol{\varepsilon}$, où $\mathbf{X}_{\text{L}}$ est diagonale par blocs, chaque bloc étant la matrice des régresseurs d'un segment, et $\boldsymbol{\theta}$ empile les $G k_0$ coefficients. Le modèle contraint est $\mathbf{R}\boldsymbol{\theta} = \mathbf{0}$ pour une matrice $\mathbf{R}$ de $q$ lignes indépendantes exprimant l'égalité des coefficients concernés entre segments. Sous normalité, $\mathit{SCR}_{\text{L}}/\sigma^2 \sim \chi^2(n - Gk_0)$ ; la différence $(\mathit{SCR}_{\text{C}} - \mathit{SCR}_{\text{L}})/\sigma^2$ est la forme quadratique $(\mathbf{R}\hat{\boldsymbol\theta})\T[\mathbf{R}(\mathbf{X}_{\text{L}}\T\mathbf{X}_{\text{L}})^{-1}\mathbf{R}\T]^{-1}(\mathbf{R}\hat{\boldsymbol\theta})/\sigma^2$, qui suit sous $H_0$ une loi $\chi^2(q)$ et est indépendante de $\mathit{SCR}_{\text{L}}$ par le théorème de Cochran, les deux formes quadratiques portant sur des projections orthogonales de $\boldsymbol\varepsilon$. Le rapport des deux khi-deux divisés par leurs degrés de liberté suit une loi $F(q, n - Gk_0)$, et $\sigma^2$ s'élimine. La version pentes s'obtient avec une matrice $\mathbf{R}$ qui ne porte pas sur les constantes ; la version classique avec une matrice qui porte sur tous les coefficients \parencite[chap.~4]{wooldridge2010}. | ||||
| 289 | +\end{proof} | ||||
| 290 | + | ||||
| 291 | +La démonstration repose sur une hypothèse qu'il faut discuter : l'homoscédasticité, et en particulier l'égalité des variances résiduelles entre segments. Si un segment est plus bruyant qu'un autre, ce qui est fréquent lorsqu'un sous-marché est mince ou hétérogène, la statistique $F$ ne suit plus exactement sa loi de référence. On lui préfère alors une statistique de Wald construite sur le modèle empilé avec interactions, $\ln P_i = \mathbf{x}_i\T\boldsymbol\beta + \sum_{g \neq 1} D_{ig}\,(\gamma_g + \tilde{\mathbf{x}}_i\T\boldsymbol\delta_g) + \varepsilon_i$, où $D_{ig}$ indique l'appartenance au segment $g$, $\tilde{\mathbf{x}}_i$ exclut la constante et les $\boldsymbol\delta_g$ mesurent l'écart des pentes du segment $g$ à celles du segment de référence : | ||||
| 292 | +\begin{equation}\label{eq:15:wald} | ||||
| 293 | +W = \hat{\boldsymbol\delta}\T\,\hat{\mathbf{V}}_{\text{HC1}}(\hat{\boldsymbol\delta})^{-1}\,\hat{\boldsymbol\delta} \ \overset{H_0}{\sim}\ \chi^2(q), | ||||
| 294 | +\end{equation} | ||||
| 295 | +avec $\hat{\mathbf{V}}_{\text{HC1}}$ la matrice de covariance robuste à l'hétéroscédasticité que l'annexe des conventions de calcul impose dans tout l'ouvrage. La statistique $W$ ne vaut qu'asymptotiquement, mais elle ne suppose rien sur l'égalité des variances ; lorsque $F$ et $W$ concluent dans le même sens, la décision est solide ; lorsqu'ils divergent, c'est le signe d'une hétéroscédasticité qu'il faut examiner. Une précaution technique s'impose enfin : un régresseur constant à l'intérieur d'un segment, par exemple l'indicatrice « à étages » lorsque l'on segmente par type de bâtiment, n'est pas identifiable dans l'équation de ce segment et doit être retiré du jeu des pentes testées, sa contribution passant dans la constante du segment ; le script du chapitre le fait automatiquement et le signale. | ||||
| 296 | + | ||||
| 297 | +\subsection{Application : les cinq secteurs de Gatineau} | ||||
| 298 | + | ||||
| 299 | +Le \cref{tab:15:coefficients} présente, pour chacun des cinq secteurs, les coefficients des quatre variables les plus importantes du modèle, estimés séparément avec leurs erreurs-types HC1, à côté du coefficient commun du modèle de référence ; la \cref{fig:15:coefficients} les représente avec leurs intervalles à 95 \%. Les élasticités de la superficie vont de 0,513 à Aylmer à 0,558 à Masson-Angers, autour d'un coefficient commun de 0,539 ; les prix implicites d'un échelon de qualité de \pct{4.8} à \pct{7.8}, autour de \pct{6.1} ; les effets de l'âge de $-0{,}0032$ à $-0{,}0055$ par année ; les tendances mensuelles de \pct{0.30} à \pct{0.44}. Aucun intervalle ne manque le coefficient commun, et les intervalles des deux petits secteurs sont deux à trois fois plus larges que ceux des grands, ce qui illustre le coût en variance de la segmentation. | ||||
| 300 | + | ||||
| 301 | +\begin{table}[htbp] | ||||
| 302 | +\caption{Coefficients hédoniques estimés séparément dans chaque secteur (erreurs-types HC1 entre parenthèses) et coefficient commun du modèle de référence, cas 1 (données synthétiques)}\label{tab:15:coefficients} | ||||
| 303 | +\centering\footnotesize\setlength{\tabcolsep}{4pt} | ||||
| 304 | +\begin{tabular}{@{}lccccccc@{}} | ||||
| 305 | +\toprule | ||||
| 306 | +Secteur & $n$ & ln(superficie) & ln(terrain) & Âge & Qualité & Garage & Tendance (mois) \\ | ||||
| 307 | +\midrule | ||||
| 308 | +Hull & 186 & 0,540 (0,022) & 0,083 (0,021) & $-$0,0043 (0,0010) & 0,064 (0,007) & 0,040 (0,009) & 0,0032 (0,0005) \\ | ||||
| 309 | +Gatineau & 200 & 0,556 (0,020) & 0,109 (0,020) & $-$0,0054 (0,0009) & 0,058 (0,008) & 0,031 (0,009) & 0,0035 (0,0005) \\ | ||||
| 310 | +Aylmer & 125 & 0,513 (0,029) & 0,047 (0,025) & $-$0,0032 (0,0016) & 0,054 (0,011) & 0,023 (0,013) & 0,0044 (0,0006) \\ | ||||
| 311 | +Buckingham & 42 & 0,536 (0,051) & 0,096 (0,046) & $-$0,0055 (0,0025) & 0,048 (0,017) & 0,010 (0,017) & 0,0039 (0,0012) \\ | ||||
| 312 | +Masson-Angers & 47 & 0,558 (0,061) & 0,161 (0,038) & $-$0,0053 (0,0023) & 0,078 (0,017) & 0,044 (0,019) & 0,0030 (0,0012) \\ | ||||
| 313 | +\midrule | ||||
| 314 | +Modèle commun & 600 & 0,539 (0,013) & 0,094 (0,011) & $-$0,0051 (0,0006) & 0,061 (0,004) & 0,032 (0,005) & 0,0036 (0,0003) \\ | ||||
| 315 | +Loi de génération & {---} & 0,55 & 0,10 & $-$0,0055 & 0,06 & 0,035 & 0,0036 \\ | ||||
| 316 | +\bottomrule | ||||
| 317 | +\end{tabular} | ||||
| 318 | +\tabsource{\synth{\texttt{analysis/python/cases/ch15\_segmentation.py} ; modèle commun : \texttt{traite.cas1.hedonique} (indicatrices de secteur incluses) ; chaque équation de secteur comprend aussi l'âge au carré, le sous-sol fini, la piscine, le type et la distance au centre ; loi de génération : \texttt{data/synthetic/README.md} (la tendance mensuelle de 0,0036 découle de la croissance annuelle de 4,43 \%).}} | ||||
| 319 | +\end{table} | ||||
| 320 | + | ||||
| 321 | +\begin{figure}[htbp] | ||||
| 322 | +\centering | ||||
| 323 | +\includegraphics[width=\textwidth]{ch15/ch15-fig-coefficients-secteurs.pdf} | ||||
| 324 | +\caption{Coefficients de la superficie, de la qualité, de l'âge et de la tendance estimés séparément dans chaque secteur, avec intervalles à 95 \% (HC1) ; le tireté est le coefficient commun du modèle de référence. Tous les intervalles le contiennent ; ceux des deux petits secteurs sont nettement plus larges.}\label{fig:15:coefficients} | ||||
| 325 | +\figsource{\synth{script \texttt{analysis/python/figures/ch15\_figures.py}, graine 20261031}} | ||||
| 326 | +\end{figure} | ||||
| 327 | + | ||||
| 328 | +Le test formel confirme cette lecture. Avec $k_0 = 12$ régresseurs par équation et $G = 5$ secteurs, la somme des carrés des résidus passe de 4,0245 pour le modèle à constantes de secteur et pentes communes à 3,7360 pour les cinq équations libres ; la statistique pentes vaut | ||||
| 329 | +\begin{equation}\label{eq:15:chow-app} | ||||
| 330 | +F = \frac{(4{,}0245 - 3{,}7360)/44}{3{,}7360/540} = 0{,}948, \qquad p = 0{,}570, | ||||
| 331 | +\end{equation} | ||||
| 332 | +très loin du seuil critique $F_{0{,}95}(44, 540) = 1{,}40$ : l'hypothèse de pentes communes n'est pas rejetée. La statistique de Wald robuste donne $W = 54{,}5$ pour 44 degrés de liberté, $p = 0{,}134$, et conduit à la même conclusion. En revanche, la version classique, qui impose aussi l'égalité des constantes, donne $F = 8{,}03$ pour 48 et 540 degrés de liberté, avec une valeur $p$ de l'ordre de $10^{-38}$ : les niveaux de prix diffèrent massivement entre secteurs. La réponse à la question du titre est donc nuancée et, dans ce cas synthétique, conforme à la loi de génération : les cinq secteurs ne sont pas des sous-marchés au sens de la \cref{def:sousmarche}, puisque la structure des prix implicites y est la même, mais ils sont des niveaux de prix distincts, et une équation unique n'est acceptable qu'avec des effets de secteur. Supprimer ces effets, comme le fait le modèle entièrement commun, porte l'écart-type résiduel de 0,0830 à 0,104 et biaise toute comparaison entre secteurs. | ||||
| 333 | + | ||||
| 334 | +\subsection{D'autres partitions, et le piège des tests multiples} | ||||
| 335 | + | ||||
| 336 | +Le même test a été appliqué à cinq autres partitions, et le \cref{tab:15:tests} en rassemble les résultats. Le regroupement de Buckingham et de Masson-Angers en un secteur « Est », qui porte tous les effectifs au-dessus de 89 ventes, ne change rien : $p = 0{,}43$. Les partitions statistiques des k-moyennes, à deux et à cinq segments, ne révèlent pas davantage de différences de pentes, $p = 0{,}59$ et $p = 0{,}43$, tandis que la version classique rejette dans les deux cas parce que les segments ont des niveaux de prix différents ; la statistique de Wald à cinq segments, $p = 0{,}057$, frôle le seuil sans le franchir. La partition par type de bâtiment donne un résultat intermédiaire : le test $F$ des pentes ne rejette pas au seuil de 5 \% ($p = 0{,}079$), mais la statistique de Wald rejette ($p = 0{,}010$), divergence qui signale une hétéroscédasticité entre plain-pieds et maisons à étages plutôt qu'une différence de structure, et qui appellerait un examen des résidus avant toute conclusion. La partition temporelle, enfin, qui oppose les ventes de 2023-2024 à celles de 2025-2026, conduit à rejeter l'égalité des pentes au seuil de 5 \% par les trois statistiques, avec des valeurs $p$ de 0,034, 0,024 et 0,037. | ||||
| 337 | + | ||||
| 338 | +\begin{table}[htbp] | ||||
| 339 | +\caption{Tests de stabilité des coefficients hédoniques pour six partitions des 600 ventes du cas 1 (données synthétiques)}\label{tab:15:tests} | ||||
| 340 | +\centering\footnotesize\setlength{\tabcolsep}{4pt} | ||||
| 341 | +\begin{tabular}{@{}lcccS[table-format=1.3]S[table-format=1.3]S[table-format=2.3]S[table-format=1.4]S[table-format=2.2]S[table-format=1.4]@{}} | ||||
| 342 | +\toprule | ||||
| 343 | +Partition & $G$ & $k_0$ & $q$ & {$F$ pentes} & {$p$} & {$F$ classique} & {$p$} & {$W$ (HC1)} & {$p$} \\ | ||||
| 344 | +\midrule | ||||
| 345 | +Secteur (5) & 5 & 12 & 44 & 0.948 & 0.570 & 8.029 & {$<$ 0,0001} & 54.48 & 0.1338 \\ | ||||
| 346 | +Secteur, Est regroupé (4) & 4 & 12 & 33 & 1.028 & 0.426 & 10.539 & {$<$ 0,0001} & 40.28 & 0.1791 \\ | ||||
| 347 | +Type de bâtiment (2) & 2 & 11 & 10 & 1.692 & 0.079 & 3.118 & 0.0004 & 23.33 & 0.0096 \\ | ||||
| 348 | +Période 2023-24 / 2025-26 (2) & 2 & 12 & 11 & 1.926 & 0.034 & 1.978 & 0.0240 & 20.64 & 0.0373 \\ | ||||
| 349 | +k-moyennes, $k = 2$ & 2 & 12 & 11 & 0.852 & 0.588 & 19.189 & {$<$ 0,0001} & 12.56 & 0.3231 \\ | ||||
| 350 | +k-moyennes, $k = 5$ & 5 & 11 & 40 & 1.028 & 0.427 & 6.371 & {$<$ 0,0001} & 55.01 & 0.0574 \\ | ||||
| 351 | +\bottomrule | ||||
| 352 | +\end{tabular} | ||||
| 353 | +\tabsource{\synth{\texttt{analysis/python/cases/ch15\_segmentation.py} ; $F$ pentes : \cref{eq:15:chow} avec constantes libres par segment, $q = (G-1)(k_0-1)$ ; $F$ classique : tous coefficients communs, $q_0 = (G-1)k_0$ ; $W$ : \cref{eq:15:wald} ; $k_0 = 11$ lorsque l'indicatrice « à étages » est constante dans un segment et retirée des pentes testées.}} | ||||
| 354 | +\end{table} | ||||
| 355 | + | ||||
| 356 | +Ce dernier résultat mérite qu'on s'y arrête, parce qu'il est faux et que l'on sait pourquoi. Le jeu synthétique a été généré avec des coefficients constants dans le temps ; la seule chose qui change entre les deux périodes est le niveau des prix, capté par la tendance. Le rejet au seuil de 5 \% est donc une erreur de première espèce, et sa survenue n'a rien d'étonnant : six partitions ont été testées, chacune avec trois statistiques, et la probabilité qu'au moins un test sur six rejette à tort au seuil de 5 \% est de l'ordre de \pct{26} si les tests étaient indépendants. Au seuil de 1 \%, dont le quantile $F_{0{,}99}(11, 576)$ vaut 2,28, aucune statistique ne rejette. Sur des données réelles, l'évaluateur ne connaît pas la vérité, et la leçon est double : d'une part, les partitions testées doivent être fixées a priori, en petit nombre, pour des raisons de marché et non après inspection des données ; d'autre part, un rejet isolé à un seuil de 5 \%, surtout avec une valeur $p$ voisine du seuil, n'autorise pas à conclure à une rupture de structure sans un examen des coefficients concernés et sans une confirmation hors échantillon. Dans le cas présent, l'examen montrerait que la pente de la tendance, estimée sur une fenêtre de deux ans dans chaque sous-période, est mal identifiée et porte l'essentiel de l'écart. | ||||
| 357 | + | ||||
| 358 | +\subsection{La précision hors échantillon tranche} | ||||
| 359 | + | ||||
| 360 | +Le test de Chow dit si les coefficients diffèrent significativement ; il ne dit pas si la segmentation améliore les prédictions, qui est la question qui importe à l'évaluateur. \textcite{goodmanThibodeau2003} ont proposé de trancher par la précision hors échantillon, et le \cref{tab:15:cv} applique leur critère : les 600 ventes sont réparties au hasard en dix plis, chaque spécification est estimée sur neuf plis et ses prédictions sont évaluées sur le dixième, et l'on rapporte la racine de l'erreur quadratique moyenne en logarithme ainsi que l'erreur absolue médiane et moyenne en pourcentage du prix. | ||||
| 361 | + | ||||
| 362 | +\begin{table}[htbp] | ||||
| 363 | +\caption{Précision prédictive hors échantillon (validation croisée à dix plis) de sept spécifications, cas 1 (données synthétiques)}\label{tab:15:cv} | ||||
| 364 | +\centering\small | ||||
| 365 | +\begin{tabular}{@{}lS[table-format=1.4]S[table-format=1.2]S[table-format=1.2]@{}} | ||||
| 366 | +\toprule | ||||
| 367 | +Spécification & {RMSE (log)} & {Erreur abs. médiane (\%)} & {Erreur abs. moyenne (\%)} \\ | ||||
| 368 | +\midrule | ||||
| 369 | +Équation unique sans segment & 0.1053 & 7.08 & 8.39 \\ | ||||
| 370 | +Pentes communes + indicatrices de secteur (référence) & 0.0839 & 5.81 & 6.79 \\ | ||||
| 371 | +Une équation par secteur & 0.0888 & 6.26 & 7.19 \\ | ||||
| 372 | +Pentes communes + indicatrices k-moyennes, $k = 2$ & 0.0898 & 6.53 & 7.32 \\ | ||||
| 373 | +Une équation par segment k-moyennes, $k = 2$ & 0.0904 & 6.65 & 7.37 \\ | ||||
| 374 | +Pentes communes + indicatrices k-moyennes, $k = 5$ & 0.0901 & 6.55 & 7.33 \\ | ||||
| 375 | +Une équation par segment k-moyennes, $k = 5$ & 0.0942 & 6.71 & 7.62 \\ | ||||
| 376 | +\bottomrule | ||||
| 377 | +\end{tabular} | ||||
| 378 | +\tabsource{\synth{\texttt{analysis/python/cases/ch15\_segmentation.py} ; dix plis aléatoires, graine 20261031 ; erreurs en pourcentage calculées sur $\exp(\text{résidu}) - 1$.}} | ||||
| 379 | +\end{table} | ||||
| 380 | + | ||||
| 381 | +Le classement est sans ambiguïté. L'équation unique sans aucun effet de localisation est la pire, avec une erreur absolue médiane de \pct{7.1} ; l'ajout des indicatrices de secteur la ramène à \pct{5.8}, soit un gain d'un cinquième ; et toutes les spécifications segmentées font moins bien que cette référence, l'équation par secteur à \pct{6.3} et l'équation par segment statistique à cinq groupes à \pct{6.7}. La segmentation par secteur coûte de la variance sans réduire de biais, puisque les pentes sont communes ; la segmentation statistique coûte davantage encore, parce que ses segments ne captent pas les primes de secteur aussi bien que les secteurs eux-mêmes, le segment 1 mélangeant par exemple des ventes de Hull, de Gatineau et d'Aylmer dont les niveaux de prix diffèrent de \pct{2} à \pct{9}. Le résultat rejoint celui de \textcite{bourassaHoesliPeng2003} sur des données réelles : la connaissance a priori du marché, ici les cinq secteurs de courtage, fait mieux que la classification statistique, et l'important est d'inclure les sous-marchés comme effets de niveau plutôt que de multiplier les équations. On gardera toutefois à l'esprit que ce verdict dépend des données : sur un marché réel où les prix implicites diffèrent effectivement entre sous-marchés, par exemple entre un centre-ville dense où le terrain commande le prix et une banlieue où c'est la surface habitable, la segmentation réduit le biais et peut l'emporter, comme l'ont trouvé \textcite{goodmanThibodeau2003} à Dallas et \textcite{bourassaCantoniHoesli2010} en comparant les sous-marchés aux méthodes spatiales du \cref{ch:19}. | ||||
| 382 | + | ||||
| 383 | +\section{Sensibilité : variables de classification et partitions}\label{sec:15:sensibilite} | ||||
| 384 | + | ||||
| 385 | +Les conclusions des deux sections précédentes dépendent de choix de l'analyste, et le \cref{tab:15:sens} mesure leur sensibilité au plus important d'entre eux, le jeu des variables de classification. Avec les attributs seuls, la silhouette maximale est de 0,221 à $k = 2$ et la partition n'a aucun lien avec les secteurs ; avec les coordonnées seules, elle atteint 0,735 et la partition à cinq groupes reproduit les secteurs à \pct{98.6} ; avec le jeu complet, les résultats sont intermédiaires et instables au-delà de $k = 2$. La leçon est que la classification révèle la structure que les variables contiennent : des coordonnées produisent des grappes spatiales, des attributs des types de maisons, et le mélange des deux un compromis qui n'a de sens que si l'on pondère les variables selon leur importance pour le prix, par exemple en utilisant comme variables de classification les prix implicites des attributs multipliés par ceux-ci, ce qui revient à classer les biens selon la décomposition de leur prix prédit plutôt que selon leurs caractéristiques brutes. La sensibilité des tests de Chow à la partition a été examinée au \cref{tab:15:tests} : la conclusion de pentes communes résiste à toutes les partitions géographiques et statistiques, et ne cède qu'à la partition temporelle, pour les raisons de tests multiples déjà discutées. Celle de la validation croisée est robuste au nombre de plis et à la graine aléatoire, le classement des spécifications ne changeant pas lorsque l'on passe de dix à cinq plis ou que l'on change l'ordre des observations, ce que le lecteur peut vérifier en modifiant le script. | ||||
| 386 | + | ||||
| 387 | +\begin{table}[htbp] | ||||
| 388 | +\caption{Sensibilité de la segmentation statistique au jeu de variables de classification, k-moyennes, cas 1 (données synthétiques)}\label{tab:15:sens} | ||||
| 389 | +\centering\small | ||||
| 390 | +\begin{tabular}{@{}lcS[table-format=1.3]S[table-format=1.3]S[table-format=1.3]S[table-format=1.3]@{}} | ||||
| 391 | +\toprule | ||||
| 392 | +Variables & $k$ optimal & {$\bar s$ au $k$ optimal} & {ARI secteurs au $k$ optimal} & {$\bar s$ à $k = 5$} & {ARI secteurs à $k = 5$} \\ | ||||
| 393 | +\midrule | ||||
| 394 | +Attributs seuls (superficie, terrain, âge, qualité, type) & 2 & 0.221 & 0.001 & 0.180 & 0.048 \\ | ||||
| 395 | +Coordonnées seules (x, y, distance au centre) & 2 & 0.735 & 0.213 & 0.672 & 0.986 \\ | ||||
| 396 | +Attributs et coordonnées & 2 & 0.417 & 0.213 & 0.188 & 0.124 \\ | ||||
| 397 | +\bottomrule | ||||
| 398 | +\end{tabular} | ||||
| 399 | +\tabsource{\synth{\texttt{analysis/python/cases/ch15\_segmentation.py}, 20 initialisations, graine 20261031 ; ARI : indice de Rand ajusté entre la partition et les cinq secteurs.}} | ||||
| 400 | +\end{table} | ||||
| 401 | + | ||||
| 402 | +\section{L'étude de marché locatif : l'immeuble du cas 3}\label{sec:15:locatif} | ||||
| 403 | + | ||||
| 404 | +\subsection{L'univers et la structure des loyers de la zone} | ||||
| 405 | + | ||||
| 406 | +L'étude de marché d'un immeuble de logements porte sur un marché différent, celui des loyers, et ses indicateurs viennent d'une source différente, l'Enquête sur les logements locatifs de la SCHL, dont les résultats d'octobre sont publiés en décembre dans le Rapport sur le marché locatif \parencite{schlLocatif2025}. L'enquête couvre les appartements d'initiative privée des immeubles de trois logements et plus, et elle les décrit par zone, par nombre de chambres, par taille d'immeuble et par année de construction, avec un indicateur de qualité statistique de a à d et la suppression des cellules dont l'échantillon est insuffisant. L'immeuble du cas 3, douze logements de 1962 dans Rosemont--La Petite-Patrie, relève de la zone 9 de la RMR de Montréal. Le \cref{tab:15:locatif} rassemble les indicateurs pertinents de cette zone, de l'île et de la RMR, et la \cref{fig:15:loyers} représente la structure des loyers et de l'univers par taille de logement. | ||||
| 407 | + | ||||
| 408 | +\begin{figure}[htbp] | ||||
| 409 | +\centering | ||||
| 410 | +\includegraphics[width=\textwidth]{ch15/ch15-fig-loyers-rosemont.pdf} | ||||
| 411 | +\caption{(a) Loyer moyen des appartements d'initiative privée par taille de logement, octobre 2025, zone 9 Rosemont/La Petite-Patrie et RMR de Montréal : la zone suit la RMR pour les petits logements et la dépasse pour les trois chambres et plus. (b) Univers de la zone 9 par taille de logement : les deux chambres représentent la moitié des 44\,554 logements.}\label{fig:15:loyers} | ||||
| 412 | +\figsource{SCHL, Enquête sur les logements locatifs, octobre 2025, tableaux 1.1.2 et 1.1.3 de la RMR de Montréal \parencite{schlrmltables2025}, consultés le 31 octobre 2026 ; indicateurs de qualité SCHL de c à d pour les loyers de la zone 9 ; script \texttt{analysis/python/figures/ch15\_figures.py}.} | ||||
| 413 | +\end{figure} | ||||
| 414 | + | ||||
| 415 | +\begin{table}[htbp] | ||||
| 416 | +\caption{Indicateurs du marché locatif pour l'immeuble du cas 3 : zone SCHL 9 Rosemont/La Petite-Patrie, île et RMR de Montréal, octobre 2025}\label{tab:15:locatif} | ||||
| 417 | +\centering\small | ||||
| 418 | +\begin{tabularx}{\textwidth}{@{}YL{32mm}L{32mm}L{30mm}@{}} | ||||
| 419 | +\toprule | ||||
| 420 | +Indicateur & Zone 9 Rosemont & Île, immeubles de 6 à 19 logements & RMR de Montréal \\ | ||||
| 421 | +\midrule | ||||
| 422 | +Univers (appartements d'initiative privée, 3 logements et plus) & 44\,554 & --- & 667\,266 \\ | ||||
| 423 | +Loyer moyen 1 ch. / 2 ch. / 3 ch. + (\$/mois) & 1\,055 / 1\,348 / 1\,750 & --- / 1\,177 / --- & 1\,131 / 1\,346 / 1\,626 \\ | ||||
| 424 | +Loyer moyen, tous logements (\$/mois) & 1\,237 & 1\,162 & 1\,290 \\ | ||||
| 425 | +Variation « même échantillon » 2024-2025, tous (\%) & 7,5 & --- & 7,4 \\ | ||||
| 426 | +Taux d'inoccupation 2025, tous (\%) & supprimé (0,7 en 2024) & 2,2 (1,7 en 2024) & 2,9 (2,1 en 2024) \\ | ||||
| 427 | +Taux d'inoccupation 2025, 1 ch. (\%) & 0,5 & --- & 3,2 \\ | ||||
| 428 | +Taux de rotation 2025, tous (\%) & supprimé & 8,5 (9,4 en 2024) & 9,4 (11,1 en 2024) \\ | ||||
| 429 | +Loyer des logements inoccupés vs occupés, 1 ch. (\$) & 1\,295 vs 1\,054 & --- & 1\,344 vs 1\,124 \\ | ||||
| 430 | +Parc achevé de juillet 2022 à juin 2025 : logements, loyer moyen (\$) & 627 ; 1\,920 (2 ch. : 2\,226) & --- & --- \\ | ||||
| 431 | +\bottomrule | ||||
| 432 | +\end{tabularx} | ||||
| 433 | +\tabsource{SCHL, Enquête sur les logements locatifs, octobre 2025 (Rapport sur le marché locatif publié le 11 décembre 2025), tableaux 1.1.1, 1.1.2, 1.1.3, 1.1.5, 1.1.6, 1.1.9, 1.3.1, 1.3.2, 1.3.4 et 3.1.7 de la RMR de Montréal \parencite{schlrmltables2025,schlLocatif2025}, consultés le 31 octobre 2026 ; « supprimé » : cellule non publiée par la SCHL (échantillon insuffisant) ; indicateurs de qualité SCHL de a à d selon les cellules, les loyers de la zone 9 étant de qualité c ou d.} | ||||
| 434 | +\end{table} | ||||
| 435 | + | ||||
| 436 | +La zone 9 est un marché locatif de grande taille, avec 44\,554 appartements d'initiative privée, soit \pct{6.7} de l'univers de la RMR, dominé par les logements de deux chambres, qui en forment la moitié, les une chambre comptant pour \pct{27.8}, les studios pour \pct{12.5} et les trois chambres et plus pour \pct{9.1}. Les loyers moyens d'octobre 2025, \dollars{1055} pour une chambre, \dollars{1348} pour deux et \dollars{1750} pour trois et plus, sont voisins de ceux de la RMR pour les petits logements et supérieurs de \pct{7.6} pour les grands ; ils ont progressé de \pct{7.5} en un an sur un échantillon constant d'immeubles, au même rythme que la RMR. L'inoccupation de la zone est trop faible pour être publiée en 2025, sauf pour les une chambre à \pct{0.5} ; elle était de \pct{0.7} en 2024, contre \pct{2.1} dans la RMR, et la remontée régionale à \pct{2.9} en 2025 ne semble pas avoir atteint la zone. Deux indicateurs supplémentaires éclairent l'immeuble du cas 3. Le premier est l'écart entre le loyer des logements inoccupés et celui des logements occupés, que la SCHL publie depuis quelques années : pour les une chambre de la zone 9, un logement vacant se loue \dollars{1295} contre \dollars{1054} pour un logement occupé, soit \pct{22.9} de plus, et pour l'ensemble des logements de la RMR l'écart est de \pct{27.1}. Cet écart mesure directement le rattrapage que permet un départ de locataire dans un marché où l'encadrement des loyers du \cref{ch:34} retient les loyers en place. Le second est l'offre neuve : 627 logements achevés entre juillet 2022 et juin 2025 dans la zone, à un loyer moyen de \dollars{1920}, soit \pct{55} au-dessus du loyer moyen du parc existant ; ils ne représentent que \pct{1.4} de l'univers et ne concurrencent pas directement un immeuble de 1962, mais ils fixent le plafond du marché et attirent les locataires les plus solvables. | ||||
| 437 | + | ||||
| 438 | +\subsection{Les loyers de l'immeuble face au marché} | ||||
| 439 | + | ||||
| 440 | +\begin{table}[htbp] | ||||
| 441 | +\caption{Loyers de l'immeuble du cas 3 par type de logement et loyers moyens de la zone SCHL 9 (données synthétiques pour l'immeuble ; SCHL pour la zone)}\label{tab:15:cas3} | ||||
| 442 | +\centering\small | ||||
| 443 | +\begin{tabular}{@{}lS[table-format=1.0]S[table-format=4.0]S[table-format=4.0]S[table-format=4.0]S[table-format=1.3]S[table-format=2.1]@{}} | ||||
| 444 | +\toprule | ||||
| 445 | +Type (immeuble / SCHL) & {$n$} & {Loyer contractuel moyen (\$)} & {Loyer de marché moyen (\$)} & {Loyer moyen zone 9 (\$)} & {Marché / zone} & {Écart contrat--marché (\%)} \\ | ||||
| 446 | +\midrule | ||||
| 447 | +3½ / 1 chambre & 4 & 875 & 1039 & 1055 & 0.985 & 15.8 \\ | ||||
| 448 | +4½ / 2 chambres & 6 & 1192 & 1340 & 1348 & 0.994 & 11.1 \\ | ||||
| 449 | +5½ / 3 chambres et plus & 2 & 1571 & 1652 & 1750 & 0.944 & 4.9 \\ | ||||
| 450 | +\midrule | ||||
| 451 | +Ensemble (mensuel) & 12 & 13795 & 15503 & {---} & {---} & 11.0 \\ | ||||
| 452 | +\bottomrule | ||||
| 453 | +\end{tabular} | ||||
| 454 | +\tabsource{immeuble : \synth{\texttt{data/synthetic/cas3\_montreal\_etat\_locatif.csv}, \texttt{traite.cas3.revenus}} ; zone 9 : SCHL, Enquête sur les logements locatifs, octobre 2025, tableau 1.1.2 \parencite{schlrmltables2025} ; écart en pourcentage du loyer de marché ; calculs : \texttt{ch15\_segmentation.py}.} | ||||
| 455 | +\end{table} | ||||
| 456 | + | ||||
| 457 | +\begin{exemple}{L'état locatif du cas 3 confronté à la zone SCHL 9}{locatif} | ||||
| 458 | +L'état locatif synthétique de l'immeuble du cas 3, fourni par \texttt{traite.cas3.charger} et détaillé au \cref{ch:47}, compte quatre logements de trois pièces et demie, six de quatre et demie et deux de cinq et demie, dont le loyer contractuel mensuel total est de \dollars{13795} contre \dollars{15503} au loyer de marché estimé, soit un revenu brut potentiel contractuel de \dollars{165540} et un revenu au marché de \dollars{186036}, un écart annuel de \dollars{20496} ou \pct{11.0} du revenu de marché, chiffres fournis par \texttt{traite.cas3.revenus}. Le \cref{tab:15:cas3} compare, par type de logement, les loyers contractuels et de marché de l'immeuble aux loyers moyens de la zone : les loyers de marché retenus dans le dossier sont à \pct{98.5}, \pct{99.4} et \pct{94.4} des moyennes SCHL des une, deux et trois chambres, ce qui est cohérent pour un immeuble de 1962 d'état moyen, légèrement en deçà d'un parc qui comprend des logements rénovés et récents ; et l'écart entre le loyer en place et le loyer de marché décroît avec la taille du logement, de \pct{15.8} pour les trois et demie, où siègent les baux les plus anciens, à \pct{4.9} pour les cinq et demie, reloués récemment. | ||||
| 459 | + | ||||
| 460 | + | ||||
| 461 | +L'étude de marché fournit ensuite les paramètres dont les \cref{ch:27,ch:30} ont besoin. La provision combinée pour inoccupation et mauvaises créances de \pct{3.9} retenue dans les hypothèses du cas 3 est supérieure à l'inoccupation physique observée dans la zone et dans les immeubles de six à dix-neuf logements de l'île (\pct{2.2}), ce qui est voulu : l'inoccupation de la SCHL est un instantané d'octobre qui ne compte ni les pertes entre deux baux ni les créances irrécouvrables, et la SCHL anticipe une remontée de l'inoccupation régionale \parencite{schlpmh2026}. Le rythme de rattrapage des loyers dépend de la rotation. Si une fraction $r$ des baux est renouvelée avec un nouveau locataire chaque année et que l'écart entre loyer en place et loyer de marché reste constant, la part de l'écart récupérée après $T$ années est | ||||
| 462 | +\begin{equation}\label{eq:15:rattrapage} | ||||
| 463 | +\pi_T = 1 - (1 - r)^T , | ||||
| 464 | +\end{equation} | ||||
| 465 | +et l'horizon moyen de renouvellement complet du parc est $1/r$. L'hypothèse de rotation de \pct{15} du dossier du cas 3 récupérerait \dollars{3074} de l'écart dès la première année et \pct{55.6} en cinq ans, avec un renouvellement complet en 6,7 ans ; la rotation observée par la SCHL en 2025, \pct{9.4} dans la RMR et \pct{8.5} dans les immeubles de six à dix-neuf logements de l'île, en baisse par rapport à 2024, ne récupérerait que \dollars{1927} ou \dollars{1742} la première année et \pct{39.0} ou \pct{35.9} en cinq ans, avec un horizon de 10,6 à 11,8 ans. L'écart entre ces scénarios est l'un des paramètres de l'analyse de sensibilité du \cref{ch:47} ; l'étude de marché ne le tranche pas, mais elle borne l'hypothèse par l'observation et oblige l'évaluateur à justifier une rotation supérieure à celle du marché, par exemple par l'ancienneté des locataires ou par des départs annoncés. | ||||
| 466 | +\end{exemple} | ||||
| 467 | + | ||||
| 468 | +\begin{quebec} | ||||
| 469 | +L'Enquête sur les logements locatifs de la SCHL est réalisée en octobre auprès des propriétaires et gestionnaires d'immeubles d'initiative privée de trois logements et plus ; elle exclut donc les duplex, les logements de copropriété offerts en location, couverts par une enquête distincte, et les logements sociaux. Ses zones ne correspondent ni aux arrondissements ni aux secteurs de courtage ; pour Montréal, la zone 9 recouvre l'arrondissement de Rosemont--La Petite-Patrie. Chaque cellule porte un indicateur de qualité de a à d, et les cellules dont le coefficient de variation est trop élevé sont supprimées ; les loyers moyens par taille de logement de la zone 9 sont de qualité c ou d en 2025 et doivent être utilisés avec prudence. La variation annuelle « même échantillon » est calculée sur les immeubles présents dans l'enquête deux années de suite et mesure mieux l'évolution du marché que la différence des moyennes, qui subit les changements de composition. Les données sont publiées sous les conditions d'utilisation de la SCHL : la citation de chiffres avec la mention « Source : SCHL, Enquête sur les logements locatifs » est admise, la redistribution des tableaux ne l'est pas \parencite{schlLocatif2025,schlrmltables2025}. Consultées le 31 octobre 2026. | ||||
| 470 | +\end{quebec} | ||||
| 471 | + | ||||
| 472 | +\begin{erreurs} | ||||
| 473 | +\begin{itemize} | ||||
| 474 | +\item Confondre le délai de vente médian des propriétés vendues avec la durée de séjour dans l'inventaire : le premier est censuré et ne porte que sur les ventes conclues ; le second est mesuré par les mois d'inventaire et lui est plusieurs fois supérieur. | ||||
| 475 | +\item Citer un ratio du prix vendu au prix demandé sans préciser si le prix demandé est le prix initial ou le dernier prix affiché, ou en inventer un faute de source : au Québec, aucune source publique ne le diffuse. | ||||
| 476 | +\item Appliquer les seuils de quatre et six mois d'inventaire comme s'il s'agissait de normes, et sans tenir compte de la tendance de l'offre ni du segment. | ||||
| 477 | +\item Segmenter le marché par classification statistique sur des attributs et appeler « sous-marchés » des groupes qui ne sont que des types de maisons ; seul un test sur la relation prix-attributs, confirmé hors échantillon, établit un sous-marché. | ||||
| 478 | +\item Lire un rejet du test de Chow classique comme une preuve de structures différentes alors qu'il peut ne refléter que des niveaux de prix différents ; tester les pentes séparément des constantes. | ||||
| 479 | +\item Multiplier les partitions testées puis retenir celle qui rejette : à six partitions et trois statistiques, un rejet au seuil de 5 \% est attendu même si rien ne diffère. | ||||
| 480 | +\item Estimer une équation par sous-marché de quarante ventes avec douze coefficients, puis utiliser ses prix implicites comme ajustements : la variance l'emporte sur le biais évité. | ||||
| 481 | +\item Utiliser le taux d'inoccupation de la SCHL comme provision pour inoccupation et mauvaises créances, ou utiliser le loyer moyen d'une zone comme loyer de marché d'un immeuble sans ajuster l'état, l'année de construction et la taille d'immeuble. | ||||
| 482 | +\item Retenir une rotation des locataires très supérieure à celle que mesure la SCHL sans justification propre à l'immeuble. | ||||
| 483 | +\end{itemize} | ||||
| 484 | +\end{erreurs} | ||||
| 485 | + | ||||
| 486 | +\begin{limites} | ||||
| 487 | +Les indicateurs de la \cref{sec:15:etude} proviennent de l'APCIQ, qui ne couvre que les ventes conclues par courtier, soit une partie du marché, et dont les communiqués ne donnent ni les inscriptions ni les délais au niveau du secteur ; l'étude de marché d'un sous-marché précis exige l'accès aux données de courtage ou au Registre foncier, et les résultats du \cref{tab:15:indicateurs} décrivent des agrégats métropolitains. Le ratio du prix vendu au prix demandé n'a pu être documenté par une source publique. Les seuils d'interprétation des mois d'inventaire sont des usages non normés. Les résultats de la \cref{sec:15:classification} et de la \cref{sec:15:chow} portent sur un jeu synthétique dont la loi de génération impose des pentes communes ; ils illustrent la méthode et ses pièges, non l'état du marché de Gatineau, où des différences réelles de structure entre secteurs peuvent exister et où les effectifs par secteur seraient différents. Le test de Chow suppose la normalité et l'homoscédasticité des erreurs ; la statistique de Wald robuste ne vaut qu'asymptotiquement, et les deux ignorent la dépendance spatiale des résidus traitée au \cref{ch:19}, qui peut gonfler les statistiques de test. La validation croisée aléatoire est optimiste pour des données spatiales, parce que des ventes voisines se retrouvent dans les plis d'apprentissage et de test ; une validation par blocs spatiaux serait plus sévère. Enfin, les données de la SCHL pour la zone 9 sont de qualité statistique c ou d et plusieurs cellules sont supprimées ; l'inoccupation et la rotation de la zone ne sont pas connues pour 2025 et ont été remplacées par celles de l'île et de la RMR, ce qui est une approximation déclarée. | ||||
| 488 | +\end{limites} | ||||
| 489 | + | ||||
| 490 | +\begin{synthese} | ||||
| 491 | +\begin{itemize} | ||||
| 492 | +\item Le marché d'un bien est l'ensemble de ses substituts pour son acheteur type ; un sous-marché n'existe que si la relation entre le prix et les caractéristiques y diffère, et non seulement le niveau des prix. | ||||
| 493 | +\item L'étude de marché procède en six étapes sourcées : demande structurelle, prix et volumes, conjoncture de la revente, tendance des prix, marché locatif, lecture ; chaque chiffre porte son organisme, son découpage, sa période et ses conditions d'utilisation. | ||||
| 494 | +\item Les mois d'inventaire sont un indicateur de stock, le délai de vente un indicateur de flux censuré ; leur rapport mesure la part de l'offre hors du prix. Au troisième trimestre de 2026, Montréal et Gatineau dépassaient six mois d'inventaire et Québec restait à trois. | ||||
| 495 | +\item Les k-moyennes et la méthode de Ward regroupent ce qui se ressemble selon les variables fournies ; la silhouette guide le choix du nombre de groupes ; sur le cas 1, la structure révélée est géographique et coïncide avec les secteurs lorsque l'on classe par coordonnées. | ||||
| 496 | +\item Le test de Chow compare les sommes des carrés des résidus d'un modèle contraint et d'un modèle libre ; il faut tester les pentes séparément des constantes et doubler la statistique $F$ d'une statistique de Wald robuste. Sur le cas 1, les pentes sont communes aux cinq secteurs et seuls les niveaux diffèrent : une équation unique avec effets de secteur est acceptable, et elle prédit mieux hors échantillon que toute segmentation. | ||||
| 497 | +\item Pour un immeuble de logements, l'étude de marché tire de l'Enquête sur les logements locatifs l'univers, les loyers par taille, l'inoccupation, la rotation, l'écart entre loyers des logements vacants et occupés et l'offre neuve, et elle borne les hypothèses de provision d'inoccupation et de rattrapage des loyers. | ||||
| 498 | +\end{itemize} | ||||
| 499 | +\end{synthese} | ||||
| 500 | + | ||||
| 501 | +\section*{Exercices} | ||||
| 502 | +\addcontentsline{toc}{section}{Exercices} | ||||
| 503 | + | ||||
| 504 | +\begin{exercice}[1]{Mois d'inventaire et taux d'absorption}{ex:15:1} | ||||
| 505 | +Au troisième trimestre de 2026, la RMR de Sherbrooke comptait 569 ventes résidentielles et 825 inscriptions en vigueur (APCIQ par le système Centris). Calculez le nombre de mois d'inventaire et le taux d'absorption mensuel. Si, au trimestre suivant, les inscriptions augmentaient de \pct{20} et les ventes diminuaient de \pct{10}, que deviendraient ces deux indicateurs, et dans quelle bande d'usage le marché se situerait-il ? | ||||
| 506 | +\end{exercice} | ||||
| 507 | + | ||||
| 508 | +\begin{exercice}[1]{Délimiter le marché d'un triplex}{ex:15:2} | ||||
| 509 | +Le sujet du cas 2 est un triplex de 1948 dans Limoilou, à Québec, dont deux logements sont loués et le troisième occupé par le propriétaire. Pour chacun des critères du \cref{tab:15:criteres}, indiquez la frontière que vous retiendriez pour délimiter son marché et nommez l'acheteur type. Quelles sources publiques utiliseriez-vous pour les étapes 2, 3 et 5 du \cref{tab:15:etapes}, et quels découpages géographiques ces sources imposent-elles ? | ||||
| 510 | +\end{exercice} | ||||
| 511 | + | ||||
| 512 | +\begin{exercice}[2]{Stock, flux et inscriptions hors du prix}{ex:15:3} | ||||
| 513 | +Dans la RMR de Montréal au troisième trimestre de 2026, 9\,265 ventes ont été conclues et 20\,350 inscriptions étaient en vigueur ; le délai de vente médian de l'unifamiliale était de 40 jours. Calculez les ventes mensuelles, le délai médian en mois et le stock d'inscriptions que l'on observerait si toutes les propriétés se vendaient en ce délai médian (\cref{eq:15:little}). Quelle part du stock observé excède ce stock « au rythme des ventes » ? Discutez les deux explications de cet excédent et ce qu'il implique pour l'ajustement de conditions du marché. | ||||
| 514 | +\end{exercice} | ||||
| 515 | + | ||||
| 516 | +\begin{exercice}[2]{Calcul d'une silhouette}{ex:15:4} | ||||
| 517 | +Six ventes sont décrites par deux variables centrées-réduites : le groupe A contient les points $(0, 0)$, $(0, 1)$ et $(1, 0)$, le groupe B les points $(4, 0)$, $(4, 1)$ et $(5, 0)$. Calculez la silhouette du point $(1, 0)$ par l'\cref{eq:15:silhouette}. Que vaudrait-elle si ce point était affecté à tort au groupe B ? Expliquez pourquoi la silhouette moyenne favorise les partitions en peu de groupes bien séparés. | ||||
| 518 | +\end{exercice} | ||||
| 519 | + | ||||
| 520 | +\begin{exercice}[2]{Test de Chow à partir des sommes des carrés}{ex:15:5} | ||||
| 521 | +Sur les 600 ventes du cas 1, avec douze régresseurs par équation et cinq secteurs, la somme des carrés des résidus vaut 6,4024 pour l'équation unique sans effet de secteur, 4,0245 pour l'équation à constantes de secteur et pentes communes, et 3,7360 pour les cinq équations libres. Calculez la statistique de Chow dans sa version pentes et dans sa version classique, avec leurs degrés de liberté, et comparez-les aux quantiles à 95 \% de la loi de Fisher, $F_{0{,}95}(44, 540) = 1{,}40$ et $F_{0{,}95}(48, 540) = 1{,}38$. Formulez la conclusion en distinguant niveau et structure. Que signifierait un résultat inverse, rejet des pentes et non des niveaux ? | ||||
| 522 | +\end{exercice} | ||||
| 523 | + | ||||
| 524 | +\begin{exercice}[3]{Rattrapage des loyers et rotation}{ex:15:6} | ||||
| 525 | +L'immeuble du cas 3 a un écart annuel de \dollars{20496} entre ses loyers de marché et ses loyers en place. En supposant cet écart constant, calculez la part de l'écart récupérée après cinq et dix ans par l'\cref{eq:15:rattrapage} pour une rotation de \pct{15}, de \pct{9.4} et de \pct{8.5}, et le montant récupéré la première année dans chaque cas. Pour les quatre logements de trois pièces et demie, dont le loyer contractuel moyen est de \dollars{875.25} et le loyer de marché de \dollars{1039}, calculez l'écart en pourcentage du loyer de marché et comparez-le à l'écart de \pct{22.9} entre loyers des une chambre inoccupées et occupées de la zone SCHL 9. Que suggère cette comparaison sur le loyer de marché retenu dans le dossier ? | ||||
| 526 | +\end{exercice} | ||||
| 527 | + | ||||
| 528 | +\begin{exercice}[3]{Variables de classification et sous-marchés}{ex:15:7} | ||||
| 529 | +À l'aide de \texttt{analysis/python/cases/ch15\_segmentation.py}, remplacez les variables de classification par les contributions au prix prédit, c'est-à-dire chaque attribut multiplié par son coefficient dans le modèle de référence \texttt{traite.cas1.hedonique}, et refaites la classification pour $k$ de 2 à 8. Comparez la silhouette et l'indice de Rand ajusté avec les secteurs à ceux du \cref{tab:15:sens}, puis appliquez le test de Chow à la partition obtenue. Rédigez une note de 200 mots sur ce que cette pondération change et sur ce qu'elle ne peut pas changer. | ||||
| 530 | +\end{exercice} | ||||
| 531 | + | ||||
| 532 | +\section*{Pour aller plus loin} | ||||
| 533 | +\addcontentsline{toc}{section}{Pour aller plus loin} | ||||
| 534 | + | ||||
| 535 | +Sur la définition et la mesure des sous-marchés, les deux articles fondateurs de \textcite{goodmanThibodeau1998} et de \textcite{bourassa1999} dans le \emph{Journal of Housing Economics} restent la meilleure introduction ; \textcite{goodmanThibodeau2003} et \textcite{bourassaHoesliPeng2003} en tirent les conséquences pour la précision des prédictions, et \textcite{bourassaCantoniHoesli2010} comparent les sous-marchés aux modèles spatiaux que présente le \cref{ch:19}. Les travaux de l'équipe de l'Université Laval, \textcite{kestensTheriaultDesrosiers2006} sur l'hétérogénéité liée aux profils d'acheteurs et \textcite{desrosiersDubeTheriault2011} sur les effets de voisinage, fournissent le contrepoint québécois ; \textcite{desrosiersTheriaultVilleneuve2000} et \textcite{dubeLegros2014} montrent comment l'accessibilité et la dépendance spatio-temporelle structurent le marché de Québec. Sur la segmentation en évaluation de masse, \textcite{gloudemansAlmy2011} et la norme de l'IAAO sur l'évaluation de masse \parencite{iaaomass2025} décrivent la stratification des rôles par type et par voisinage. Les fondements économiques de l'étude de marché, schéma à quatre quadrants et dynamique de l'inventaire, se lisent chez \textcite{dipasqualeWheaton1996} et \textcite{wheaton1999} ; \textcite{sivitanidouSivitanides1999} montrent comment les conditions locales de marché se répercutent sur les taux de capitalisation, lien repris au \cref{ch:29}. Pour l'inférence, le chapitre de \textcite{wooldridge2010} sur les tests de restrictions linéaires et l'hétéroscédasticité couvre le test de Chow et sa version robuste ; les textes originaux de Chow (1960), de MacQueen (1967), de Ward (1963) et de Rousseeuw (1987) sont référencés dans la bibliographie complémentaire du chapitre. Le traitement de l'étude de marché par l'Appraisal Institute \parencite{appraisal2026} offre enfin le cadre de la pratique nord-américaine, que \textcite{achour1992} a adapté au vocabulaire québécois. | ||||
modified
manuscript/chapters/ch19.tex
+25 −24
@@ -33,6 +33,7 @@ Les deux phénomènes coexistent souvent et l'un peut se déguiser en l'autre : | |||||
| 33 | 33 | ||||
| 34 | \begin{figure}[htbp] | 34 | \begin{figure}[htbp] | ||
| 35 | \centering | 35 | \centering | ||
| 36 | +\resizebox{\textwidth}{!}{% | ||||
| 36 | \begin{tikzpicture}[node distance=5mm and 6mm, every node/.style={font=\sffamily\footnotesize}, boite/.style={draw=brandPrimary, fill=brandLight, rounded corners=1pt, align=center, minimum height=9mm, text width=36mm}, racine/.style={boite, fill=brandSecondary!35, text width=46mm}, feuille/.style={boite, fill=white, text width=30mm, minimum height=11mm}, fleche/.style={-{Stealth[length=2mm]}, brandGray, thick}] | 37 | \begin{tikzpicture}[node distance=5mm and 6mm, every node/.style={font=\sffamily\footnotesize}, boite/.style={draw=brandPrimary, fill=brandLight, rounded corners=1pt, align=center, minimum height=9mm, text width=36mm}, racine/.style={boite, fill=brandSecondary!35, text width=46mm}, feuille/.style={boite, fill=white, text width=30mm, minimum height=11mm}, fleche/.style={-{Stealth[length=2mm]}, brandGray, thick}] | ||
| 37 | \node[racine] (r) {Effets spatiaux dans un modèle hédonique}; | 38 | \node[racine] (r) {Effets spatiaux dans un modèle hédonique}; | ||
| 38 | \node[boite, below left=of r, xshift=-14mm] (d) {\textbf{Dépendance}\\covariance des résidus ou des prix entre voisins}; | 39 | \node[boite, below left=of r, xshift=-14mm] (d) {\textbf{Dépendance}\\covariance des résidus ou des prix entre voisins}; | ||
@@ -44,7 +45,7 @@ Les deux phénomènes coexistent souvent et l'un peut se déguiser en l'autre : | |||||
| 44 | \node[feuille, below right=of h, xshift=-4mm] (gwr) {Régression géographiquement pondérée (\cref{sec:19:gwr})}; | 45 | \node[feuille, below right=of h, xshift=-4mm] (gwr) {Régression géographiquement pondérée (\cref{sec:19:gwr})}; | ||
| 45 | \foreach \a/\b in {r/d, r/h, d/fe, d/ar, d/kr, h/seg, h/gwr} \draw[fleche] (\a) -- (\b); | 46 | \foreach \a/\b in {r/d, r/h, d/fe, d/ar, d/kr, h/seg, h/gwr} \draw[fleche] (\a) -- (\b); | ||
| 46 | \node[below=3mm of ar, text=brandGray, align=center] {Diagnostic commun : $I$ de Moran, corrélogramme, tests LM (\cref{sec:19:tests}) ; matrice $\mathbf{W}$ (\cref{sec:19:poids})}; | 47 | \node[below=3mm of ar, text=brandGray, align=center] {Diagnostic commun : $I$ de Moran, corrélogramme, tests LM (\cref{sec:19:tests}) ; matrice $\mathbf{W}$ (\cref{sec:19:poids})}; | ||
| 47 | −\end{tikzpicture} | 48 | +\end{tikzpicture}} | ||
| 48 | \caption{Les deux familles d'effets spatiaux et les outils qui leur répondent. La dépendance se diagnostique sur les résidus et se traite par des effets fixes, des modèles autorégressifs ou le krigeage ; l'hétérogénéité se traite par la segmentation ou par des coefficients locaux.}\label{fig:19:taxonomie} | 49 | \caption{Les deux familles d'effets spatiaux et les outils qui leur répondent. La dépendance se diagnostique sur les résidus et se traite par des effets fixes, des modèles autorégressifs ou le krigeage ; l'hétérogénéité se traite par la segmentation ou par des coefficients locaux.}\label{fig:19:taxonomie} | ||
| 49 | \figsource{schéma de l'auteur, d'après \textcite{anselin1988} et \textcite{dubeLegros2014}.} | 50 | \figsource{schéma de l'auteur, d'après \textcite{anselin1988} et \textcite{dubeLegros2014}.} | ||
| 50 | \end{figure} | 51 | \end{figure} | ||
@@ -55,7 +56,7 @@ L'écriture générale retenue dans l'ouvrage pour le modèle hédonique, | |||||
| 55 | \begin{equation}\label{eq:19:hedonique} | 56 | \begin{equation}\label{eq:19:hedonique} | ||
| 56 | \ln P_i = \alpha + \mathbf{x}_i\T\boldsymbol\beta + \tau_{t(i)} + \mu_{s(i)} + \varepsilon_i , | 57 | \ln P_i = \alpha + \mathbf{x}_i\T\boldsymbol\beta + \tau_{t(i)} + \mu_{s(i)} + \varepsilon_i , | ||
| 57 | \end{equation} | 58 | \end{equation} | ||
| 58 | −contient déjà un effet temporel $\tau_{t(i)}$ et un effet spatial $\mu_{s(i)}$. Tout ce chapitre peut se lire comme une discussion de la nature de $\mu$. Dans le modèle de référence du cas 1 (\texttt{traite.cas1.hedonique}), $\mu_{s(i)}$ est un effet fixe de secteur, cinq constantes pour les cinq secteurs de Gatineau, complété par un gradient de distance au centre. Cette spécification suppose que la localisation agit par paliers, identiques pour toutes les maisons d'un secteur, et qu'à l'intérieur d'un secteur les résidus sont indépendants. Les modèles de ce chapitre relâchent ces deux hypothèses : $\mu$ peut être une surface continue (krigeage, régression géographiquement pondérée), un processus autorégressif qui lie chaque résidu à ceux de ses voisins (modèle à erreur spatiale), ou encore une dépendance directe du prix aux prix voisins (modèle à décalage spatial). De même, $\tau$ peut être une tendance linéaire, une suite d'indicatrices trimestrielles, ou une pondération des ventes antérieures qui décroît avec leur ancienneté. | 59 | +contient déjà un effet temporel $\tau_{t(i)}$ et un effet spatial $\mu_{s(i)}$. Tout ce chapitre peut se lire comme une discussion de la nature de $\mu$. Dans le modèle de référence du cas 1 (fonction \texttt{hedonique} du module \texttt{traite.cas1}), $\mu_{s(i)}$ est un effet fixe de secteur, cinq constantes pour les cinq secteurs de Gatineau, complété par un gradient de distance au centre. Cette spécification suppose que la localisation agit par paliers, identiques pour toutes les maisons d'un secteur, et qu'à l'intérieur d'un secteur les résidus sont indépendants. Les modèles de ce chapitre relâchent ces deux hypothèses : $\mu$ peut être une surface continue (krigeage, régression géographiquement pondérée), un processus autorégressif qui lie chaque résidu à ceux de ses voisins (modèle à erreur spatiale), ou encore une dépendance directe du prix aux prix voisins (modèle à décalage spatial). De même, $\tau$ peut être une tendance linéaire, une suite d'indicatrices trimestrielles, ou une pondération des ventes antérieures qui décroît avec leur ancienneté. | ||
| 59 | 60 | ||||
| 60 | \subsection{Ce que la dépendance fait aux moindres carrés} | 61 | \subsection{Ce que la dépendance fait aux moindres carrés} | ||
| 61 | 62 | ||||
@@ -424,10 +425,10 @@ Le \cref{tab:19:gwr} résume la distribution des coefficients locaux et la \cref | |||||
| 424 | \begin{table}[htbp] | 425 | \begin{table}[htbp] | ||
| 425 | \caption{Distribution des coefficients locaux de la GWR (noyau gaussien, bande passante 4,99 km) sur les 600 ventes, spécification sans indicatrices de secteur (données synthétiques)}\label{tab:19:gwr} | 426 | \caption{Distribution des coefficients locaux de la GWR (noyau gaussien, bande passante 4,99 km) sur les 600 ventes, spécification sans indicatrices de secteur (données synthétiques)}\label{tab:19:gwr} | ||
| 426 | \centering | 427 | \centering | ||
| 427 | −\small | 428 | +\footnotesize\setlength{\tabcolsep}{2.5pt} | ||
| 428 | \begin{tabular}{lrrrrrr} | 429 | \begin{tabular}{lrrrrrr} | ||
| 429 | \toprule | 430 | \toprule | ||
| 430 | −Coefficient local & {Minimum} & {Q1} & {Médiane} & {Q3} & {Maximum} & {Global (MCO)} \\ | 431 | +Coefficient local & {Min.} & {Q1} & {Médiane} & {Q3} & {Max.} & {MCO global} \\ | ||
| 431 | \midrule | 432 | \midrule | ||
| 432 | Constante & 12,769 & 13,171 & 13,202 & 13,206 & 13,208 & 13,229 \\ | 433 | Constante & 12,769 & 13,171 & 13,202 & 13,206 & 13,208 & 13,229 \\ | ||
| 433 | $\ln(S/140)$ & 0,508 & 0,533 & 0,542 & 0,549 & 0,552 & 0,550 \\ | 434 | $\ln(S/140)$ & 0,508 & 0,533 & 0,542 & 0,549 & 0,552 & 0,550 \\ | ||
@@ -456,16 +457,16 @@ Le \cref{tab:19:effets-fixes} compare des spécifications à effets fixes de gra | |||||
| 456 | \begin{table}[htbp] | 457 | \begin{table}[htbp] | ||
| 457 | \caption{Spécifications à effets fixes spatiaux et temporels sur les 600 ventes du cas 1 (données synthétiques)}\label{tab:19:effets-fixes} | 458 | \caption{Spécifications à effets fixes spatiaux et temporels sur les 600 ventes du cas 1 (données synthétiques)}\label{tab:19:effets-fixes} | ||
| 458 | \centering | 459 | \centering | ||
| 459 | −\small | 460 | +\footnotesize\setlength{\tabcolsep}{3.5pt} | ||
| 460 | \begin{tabular}{lrrrrrr} | 461 | \begin{tabular}{lrrrrrr} | ||
| 461 | \toprule | 462 | \toprule | ||
| 462 | Spécification & {Param.} & {$R^2$} & {$\bar R^2$} & {$\hat\sigma$} & {AIC} & {$I$ résidus} \\ | 463 | Spécification & {Param.} & {$R^2$} & {$\bar R^2$} & {$\hat\sigma$} & {AIC} & {$I$ résidus} \\ | ||
| 463 | \midrule | 464 | \midrule | ||
| 464 | −Gradient de distance seul ; tendance linéaire & 12 & 0,766 & 0,762 & 0,104 & $-995{,}4$ & 0,324 \\ | 465 | +Gradient de distance seul (sans secteur) ; tendance & 12 & 0,766 & 0,762 & 0,104 & $-995{,}4$ & 0,324 \\ | ||
| 465 | −Secteurs et gradient (référence) ; tendance linéaire & 16 & 0,853 & 0,849 & 0,083 & $-1\,266{,}0$ & $-0{,}014$ \\ | 466 | +Secteurs et gradient (référence) ; tendance & 16 & 0,853 & 0,849 & 0,083 & $-1\,266{,}0$ & $-0{,}014$ \\ | ||
| 466 | −Grille de 5 km (19 cellules) ; tendance linéaire & 30 & 0,856 & 0,849 & 0,083 & $-1\,252{,}1$ & $-0{,}021$ \\ | 467 | +Grille de 5 km (19 cellules) ; tendance & 30 & 0,856 & 0,849 & 0,083 & $-1\,252{,}1$ & $-0{,}021$ \\ | ||
| 467 | −Grille de 3 km (39 cellules) ; tendance linéaire & 50 & 0,863 & 0,851 & 0,083 & $-1\,240{,}4$ & $-0{,}032$ \\ | 468 | +Grille de 3 km (39 cellules) ; tendance & 50 & 0,863 & 0,851 & 0,083 & $-1\,240{,}4$ & $-0{,}032$ \\ | ||
| 468 | −Grille de 2 km (67 cellules) ; tendance linéaire & 78 & 0,872 & 0,853 & 0,082 & $-1\,225{,}4$ & $-0{,}065$ \\ | 469 | +Grille de 2 km (67 cellules) ; tendance & 78 & 0,872 & 0,853 & 0,082 & $-1\,225{,}4$ & $-0{,}065$ \\ | ||
| 469 | Secteurs et gradient ; 14 indicatrices trimestrielles & 29 & 0,856 & 0,849 & 0,083 & $-1\,253{,}8$ & $-0{,}018$ \\ | 470 | Secteurs et gradient ; 14 indicatrices trimestrielles & 29 & 0,856 & 0,849 & 0,083 & $-1\,253{,}8$ & $-0{,}018$ \\ | ||
| 470 | \bottomrule | 471 | \bottomrule | ||
| 471 | \end{tabular} | 472 | \end{tabular} | ||
@@ -519,16 +520,16 @@ Aucun des modèles qui ignorent les secteurs ne retrouve exactement la référen | |||||
| 519 | \begin{table}[htbp] | 520 | \begin{table}[htbp] | ||
| 520 | \caption{Précision en validation croisée sur les 600 ventes et indication de valeur pour le sujet selon le modèle (données synthétiques)}\label{tab:19:validation} | 521 | \caption{Précision en validation croisée sur les 600 ventes et indication de valeur pour le sujet selon le modèle (données synthétiques)}\label{tab:19:validation} | ||
| 521 | \centering | 522 | \centering | ||
| 522 | −\small\setlength{\tabcolsep}{4pt} | 523 | +\footnotesize\setlength{\tabcolsep}{3pt} | ||
| 523 | \begin{tabular}{lrrrrr} | 524 | \begin{tabular}{lrrrrr} | ||
| 524 | \toprule | 525 | \toprule | ||
| 525 | −Modèle & {EQM (log)} & {Err. abs. moy.} & {$I$ des erreurs} & {Indication (\$)} & {Écart à la réf.} \\ | 526 | +Modèle & {EQM (log)} & {Err. abs.} & {$I$ erreurs} & {Indication (\$)} & {Écart réf.} \\ | ||
| 526 | \midrule | 527 | \midrule | ||
| 527 | MCO, modèle de référence (secteurs) & 0,084 & 6,8 \% & $-0{,}014$ & 637 953 & --- \\ | 528 | MCO, modèle de référence (secteurs) & 0,084 & 6,8 \% & $-0{,}014$ & 637 953 & --- \\ | ||
| 528 | MCO sans indicatrices de secteur & 0,105 & 8,4 \% & 0,323 & 664 342 & $+4{,}1$ \% \\ | 529 | MCO sans indicatrices de secteur & 0,105 & 8,4 \% & 0,323 & 664 342 & $+4{,}1$ \% \\ | ||
| 529 | −MCO sans secteur + krigeage du résidu & 0,088 & 7,1 \% & $-0{,}115$ & 624 799 & $-2{,}1$ \% \\ | 530 | +MCO sans secteur, krigeage du résidu & 0,088 & 7,1 \% & $-0{,}115$ & 624 799 & $-2{,}1$ \% \\ | ||
| 530 | −SEM sans secteur (espérance conditionnelle) & 0,088 & 7,1 \% & $-0{,}152$ & 633 352 & $-0{,}7$ \% \\ | 531 | +SEM sans secteur (espérance cond.) & 0,088 & 7,1 \% & $-0{,}152$ & 633 352 & $-0{,}7$ \% \\ | ||
| 531 | −SAR sans secteur (prédiction conditionnelle) & 0,095 & 7,6 \% & 0,121 & 654 429 & $+2{,}6$ \% \\ | 532 | +SAR sans secteur (prédiction cond.) & 0,095 & 7,6 \% & 0,121 & 654 429 & $+2{,}6$ \% \\ | ||
| 532 | GWR sans secteur (coefficients locaux) & 0,086 & --- & $-0{,}002$ & 627 519 & $-1{,}6$ \% \\ | 533 | GWR sans secteur (coefficients locaux) & 0,086 & --- & $-0{,}002$ & 627 519 & $-1{,}6$ \% \\ | ||
| 533 | \bottomrule | 534 | \bottomrule | ||
| 534 | \end{tabular} | 535 | \end{tabular} | ||
@@ -542,16 +543,16 @@ Le \cref{tab:19:sensibilite} et la \cref{fig:19:sensibilite} reprennent les esti | |||||
| 542 | \begin{table}[htbp] | 543 | \begin{table}[htbp] | ||
| 543 | \caption{Sensibilité au choix de la matrice de pondération, spécification sans indicatrices de secteur (données synthétiques)}\label{tab:19:sensibilite} | 544 | \caption{Sensibilité au choix de la matrice de pondération, spécification sans indicatrices de secteur (données synthétiques)}\label{tab:19:sensibilite} | ||
| 544 | \centering | 545 | \centering | ||
| 545 | −\small | 546 | +\footnotesize\setlength{\tabcolsep}{3pt} | ||
| 546 | \begin{tabular}{lrrrrrrr} | 547 | \begin{tabular}{lrrrrrrr} | ||
| 547 | \toprule | 548 | \toprule | ||
| 548 | −Matrice & {Voisins moy.} & {$I$ résidus MCO} & {$z$} & {$\hat\rho$ SAR} & {AIC SAR} & {$\hat\lambda$ SEM} & {AIC SEM} \\ | 549 | +Matrice $\mathbf{W}$ & {Vois.} & {$I$ (MCO)} & {$z$} & {$\hat\rho$ SAR (é.-t.)} & {AIC SAR} & {$\hat\lambda$ SEM (é.-t.)} & {AIC SEM} \\ | ||
| 549 | \midrule | 550 | \midrule | ||
| 550 | −4 plus proches voisins & 4,0 & 0,320 & 12,0 & 0,236 (0,036) & $-1\,033{,}0$ & 0,507 (0,041) & $-1\,108{,}7$ \\ | 551 | +$k = 4$ plus proches voisins & 4,0 & 0,320 & 12,0 & 0,236 (0,036) & $-1\,033{,}0$ & 0,507 (0,041) & $-1\,108{,}7$ \\ | ||
| 551 | −6 plus proches voisins & 6,0 & 0,331 & 15,1 & 0,343 (0,038) & $-1\,059{,}6$ & 0,596 (0,043) & $-1\,140{,}4$ \\ | 552 | +$k = 6$ plus proches voisins & 6,0 & 0,331 & 15,1 & 0,343 (0,038) & $-1\,059{,}6$ & 0,596 (0,043) & $-1\,140{,}4$ \\ | ||
| 552 | −8 plus proches voisins (référence) & 8,0 & 0,324 & 17,1 & 0,439 (0,041) & $-1\,080{,}5$ & 0,649 (0,045) & $-1\,153{,}2$ \\ | 553 | +$k = 8$ plus proches voisins (réf.) & 8,0 & 0,324 & 17,1 & 0,439 (0,041) & $-1\,080{,}5$ & 0,649 (0,045) & $-1\,153{,}2$ \\ | ||
| 553 | −12 plus proches voisins & 12,0 & 0,324 & 21,2 & 0,531 (0,046) & $-1\,099{,}4$ & 0,718 (0,047) & $-1\,175{,}3$ \\ | 554 | +$k = 12$ plus proches voisins & 12,0 & 0,324 & 21,2 & 0,531 (0,046) & $-1\,099{,}4$ & 0,718 (0,047) & $-1\,175{,}3$ \\ | ||
| 554 | −16 plus proches voisins & 16,0 & 0,332 & 25,2 & 0,654 (0,046) & $-1\,135{,}9$ & 0,786 (0,044) & $-1\,204{,}1$ \\ | 555 | +$k = 16$ plus proches voisins & 16,0 & 0,332 & 25,2 & 0,654 (0,046) & $-1\,135{,}9$ & 0,786 (0,044) & $-1\,204{,}1$ \\ | ||
| 555 | Distance inverse, 2 km & 61,8 & 0,322 & 25,2 & 0,636 (0,057) & $-1\,124{,}2$ & 0,803 (0,049) & $-1\,201{,}7$ \\ | 556 | Distance inverse, 2 km & 61,8 & 0,322 & 25,2 & 0,636 (0,057) & $-1\,124{,}2$ & 0,803 (0,049) & $-1\,201{,}7$ \\ | ||
| 556 | Distance inverse, 3 km & 106,7 & 0,328 & 35,4 & 0,790 (0,053) & $-1\,175{,}8$ & 0,863 (0,043) & $-1\,226{,}0$ \\ | 557 | Distance inverse, 3 km & 106,7 & 0,328 & 35,4 & 0,790 (0,053) & $-1\,175{,}8$ & 0,863 (0,043) & $-1\,226{,}0$ \\ | ||
| 557 | Distance inverse, 4 km & 140,7 & 0,327 & 40,4 & 0,837 (0,047) & $-1\,196{,}3$ & 0,888 (0,039) & $-1\,233{,}2$ \\ | 558 | Distance inverse, 4 km & 140,7 & 0,327 & 40,4 & 0,837 (0,047) & $-1\,196{,}3$ & 0,888 (0,039) & $-1\,233{,}2$ \\ | ||
@@ -567,8 +568,8 @@ Distance inverse, 4 km & 140,7 & 0,327 & 40,4 & 0,837 (0,047) & $-1\,196{,}3$ & | |||||
| 567 | \figsource{\synth{analysis/python/figures/ch19\_figures.py}} | 568 | \figsource{\synth{analysis/python/figures/ch19\_figures.py}} | ||
| 568 | \end{figure} | 569 | \end{figure} | ||
| 569 | 570 | ||||
| 570 | −\begin{quebec}[Localisation, données ouvertes et fiscalité au Québec] | 571 | +\begin{quebec}[Localisation et données ouvertes au Québec] | ||
| 571 | −Les travaux de l'école de Québec sur la dimension spatiale des prix résidentiels sont parmi les plus cités de la littérature : \textcite{desrosiersTheriaultVilleneuve2000} séparent les effets d'accessibilité et de voisinage dans un modèle hédonique de la région de Québec, \textcite{theriaultDesrosiersVilleneuveKestens2003} montrent que les prix implicites des attributs y varient avec la localisation, et \textcite{dubeLegros2013} y développent leur mesure spatio-temporelle de la dépendance ; \textcite{theriaultDesrosiers2011} et \textcite{dubeLegros2014} en font la synthèse. Les outils de ce chapitre sont donc nés, pour partie, de données québécoises. Leur application à grande échelle est facilitée depuis que le ministère des Affaires municipales et de l'Habitation diffuse les rôles d'évaluation foncière des 1\,140 municipalités en format ouvert, sous licence Creative Commons Attribution 4.0, y compris dans des versions géoréférencées (FGDB, GPKG, GeoJSON) qui permettent de localiser chaque unité d'évaluation, les noms et adresses des propriétaires étant caviardés \parencite{dqroles}. L'hétérogénéité spatiale est aussi reconnue par la fiscalité locale : le règlement de taxation 2026 de la Ville de Gatineau fixe, à côté d'un taux de base de \qty{5.224}{\dollar} par \dollars{1000} d'évaluation, un taux de la taxe foncière générale résidentielle propre à chaque unité de voisinage, qui s'échelonne de 1,613 à \qty{7.544}{\dollar} par \dollars{1000} selon l'annexe du règlement \parencite{gatineaureglement994}. Les « unités de voisinage » de l'évaluateur municipal sont, en pratique, des effets fixes de quartier ; le choix de leurs frontières relève du jugement professionnel et des méthodes du \cref{ch:15}, et les tests de ce chapitre permettent de vérifier qu'elles épuisent la dépendance spatiale des ratios du \cref{ch:9}. Sources consultées le 31 octobre 2026. | 572 | +Les travaux de l'école de Québec sur la dimension spatiale des prix résidentiels sont parmi les plus cités de la littérature : \textcite{desrosiersTheriaultVilleneuve2000} séparent les effets d'accessibilité et de voisinage dans un modèle hédonique de la région de Québec, \textcite{theriaultDesrosiersVilleneuveKestens2003} montrent que les prix implicites des attributs y varient avec la localisation, et \textcite{dubeLegros2013} y développent leur mesure spatio-temporelle de la dépendance ; \textcite{theriaultDesrosiers2011} et \textcite{dubeLegros2014} en font la synthèse. Les outils de ce chapitre sont donc nés, pour partie, de données québécoises. Leur application à grande échelle est facilitée depuis que le ministère des Affaires municipales et de l'Habitation diffuse les rôles d'évaluation foncière des 1\,140 municipalités en format ouvert, sous licence Creative Commons Attribution 4.0, y compris dans des versions géoréférencées (FGDB, GPKG, GeoJSON) qui permettent de localiser chaque unité d'évaluation, les noms et adresses des propriétaires étant caviardés \parencite{dqroles}. L'hétérogénéité spatiale est aussi reconnue par la fiscalité locale : le règlement de taxation 2026 de la Ville de Gatineau fixe, à côté d'un taux de base de \qty{5.224}{\dollar} par \dollars{1000} d'évaluation, un taux de la taxe foncière générale résidentielle propre à chaque unité de voisinage, qui s'échelonne de 1,613 à \qty{7.544}{\dollar} par \dollars{1000} selon l'annexe du règlement \parencite{gatineaureglement994}. Les « unités de voisinage » de l'évaluateur municipal sont, en pratique, des effets fixes de quartier ; le choix de leurs frontières relève du jugement professionnel et des méthodes du \cref{ch:15}, et les tests de ce chapitre permettent de vérifier qu'elles épuisent la dépendance spatiale des ratios du \cref{ch:09}. Sources consultées le 31 octobre 2026. | ||
| 572 | \end{quebec} | 573 | \end{quebec} | ||
| 573 | 574 | ||||
| 574 | \begin{quebec}[Modèles spatiaux et pratique professionnelle] | 575 | \begin{quebec}[Modèles spatiaux et pratique professionnelle] | ||
modified
manuscript/chapters/ch22.tex
+632 −1
@@ -1,2 +1,633 @@ | |||||
| 1 | \chapter{Métrés et quantités}\label{ch:22} | 1 | \chapter{Métrés et quantités}\label{ch:22} | ||
| 2 | −\stubchapter | 2 | + | ||
| 3 | +Le \cref{ch:21} a établi que le coût neuf d'un bâtiment se calcule, dans sa forme la plus rigoureuse, comme une somme de quantités multipliées par des prix unitaires. Il a laissé ouverte la question qui fait l'objet du présent chapitre : d'où viennent ces quantités, comment les mesure-t-on, et comment l'évaluateur, qui n'est ni architecte ni estimateur de chantier, peut-il s'assurer qu'un devis de trente-huit postes décrit bien le bâtiment qu'il a devant lui ? Le métré, c'est-à-dire le relevé méthodique des quantités d'ouvrage à partir des plans, est le métier des économistes en construction et des estimateurs ; l'évaluateur ne le pratique pas pour produire un prix de soumission, mais il doit en connaître les règles pour trois raisons. Il doit pouvoir lire un plan et en tirer les dimensions de base dont dépendent toutes les conventions de superficie ; il doit pouvoir vérifier, par quelques règles géométriques simples, qu'un devis qu'on lui remet n'est ni gonflé ni amputé ; et il doit savoir où loge l'incertitude d'un coût neuf, dans les quantités, dans les prix ou dans la structure du devis, pour pondérer correctement l'indication de valeur. Le chapitre reprend le devis synthétique du sujet du cas 1, exactement tel que le \cref{ch:21} l'a utilisé, lui adjoint un plan coté, et conduit un métré de contrôle complet ; le \cref{ch:23} poursuivra avec la construction des prix unitaires et la structure des coûts indirects. | ||||
| 4 | + | ||||
| 5 | +\begin{objectifs} | ||||
| 6 | +À la fin de ce chapitre, le lecteur sait : | ||||
| 7 | +\begin{itemize} | ||||
| 8 | +\item définir le métré, le bordereau de quantités et le prix unitaire installé, et situer la méthode quantitative dans la hiérarchie des méthodes d'estimation du coût neuf ; | ||||
| 9 | +\item lire un plan d'architecture résidentiel, en relever les dimensions de base et calculer les superficies selon les conventions du Manuel d'évaluation foncière, du courtage et du métré ; | ||||
| 10 | +\item appliquer les règles de mesure propres à chaque corps de métier (volumes de terrassement et de béton, surfaces de charpente, d'enveloppe et de finition, longueurs, dénombrements) et en connaître les conventions brutes ou nettes ; | ||||
| 11 | +\item passer des quantités mesurées aux quantités à commander par les taux de pertes et de chutes, et décomposer un prix unitaire installé en matériaux, main-d'œuvre, équipement et marge ; | ||||
| 12 | +\item conduire un métré de contrôle d'un devis par composantes, qualifier chaque écart selon une tolérance déclarée et en chiffrer l'effet sur le coût direct et le coût neuf ; | ||||
| 13 | +\item quantifier la propagation des erreurs de mesure dans un coût neuf et distinguer ce qui relève des quantités, des prix et de la structure du devis. | ||||
| 14 | +\end{itemize} | ||||
| 15 | +\end{objectifs} | ||||
| 16 | + | ||||
| 17 | +\section{Le métré : objet, vocabulaire et place dans la méthode du coût}\label{sec:22:principes} | ||||
| 18 | + | ||||
| 19 | +\subsection{Mesurer avant de chiffrer} | ||||
| 20 | + | ||||
| 21 | +Un coût de construction n'est jamais observé directement : il résulte d'un produit entre une quantité et un prix. La comparaison unitaire du \cref{ch:21} réduit ce produit à un seul terme, la superficie, multipliée par un coût au mètre carré qui résume tout le reste ; la méthode par composantes le décompose en quelques dizaines de termes ; la méthode quantitative le pousse jusqu'au matériau et à l'heure de travail. À chaque niveau de finesse correspond une opération de mesure, et c'est cette opération que la tradition francophone de la construction nomme le métré. Le mot désigne à la fois l'activité, le relevé des quantités d'ouvrage à partir des plans et des devis descriptifs, et son résultat, le document qui en consigne les quantités poste par poste. Dans l'usage nord-américain, l'équivalent est le \emph{quantity take-off}, et la méthode d'estimation qui en découle est la \emph{quantity survey method} que \textcite{appraisal2026} placent au sommet de la hiérarchie des méthodes de coût, au-dessus de l'\emph{unit-in-place} et de la comparaison unitaire ; le glossaire de \textcite{aiDictionary2022} fixe ces termes, et \textcite{achour1992} a introduit dans la littérature québécoise d'évaluation la terminologie française que l'on reprend ici. | ||||
| 22 | + | ||||
| 23 | +\begin{definition}{Métré, bordereau de quantités et prix unitaire installé}{metre} | ||||
| 24 | +Le \emph{métré} est le relevé méthodique, à partir des plans et du devis descriptif, des quantités d'ouvrage nécessaires à la construction d'un bâtiment, chaque ouvrage étant mesuré dans l'unité qui gouverne son coût (mètre cube, mètre carré, mètre linéaire, unité, forfait). Le \emph{bordereau de quantités} (\emph{bill of quantities}) est le document qui consigne ces quantités poste par poste, dans l'ordre des corps de métier, avec leur unité et, lorsqu'il est chiffré, leur prix unitaire et leur montant. Le \emph{prix unitaire installé} (\emph{unit-in-place cost}) d'un poste est le coût, par unité de mesure, de l'ouvrage livré et posé : matériaux, pertes, main-d'œuvre, équipement, frais généraux et marge du corps de métier compris. | ||||
| 25 | +\end{definition} | ||||
| 26 | + | ||||
| 27 | +La distinction entre le métré de l'estimateur et celui de l'évaluateur mérite d'être posée d'emblée, parce qu'elle détermine le niveau de détail pertinent. L'estimateur d'un entrepreneur général mesure pour soumissionner : il doit connaître le nombre de montants, de feuilles de contreplaqué, de sacs de ciment et d'heures de chaque métier, parce que c'est ce qu'il achètera et paiera ; son erreur se traduit en pertes réelles. L'économiste en construction (\emph{quantity surveyor}), profession représentée au Canada par le Canadian Institute of Quantity Surveyors, qui décerne les titres de \emph{Professional Quantity Surveyor} (PQS) et de \emph{Construction Estimator Certified} (CEC), mesure pour conseiller le maître d'ouvrage, contrôler les coûts d'un projet et arbitrer les réclamations. L'évaluateur, lui, mesure pour estimer une valeur : il lui suffit que les quantités des composantes soient justes à quelques pour cent près, parce que l'incertitude du coût neuf se combine ensuite à celle, bien plus grande, de la dépréciation et de la valeur du terrain. Son métré est donc un métré de contrôle, qui porte sur les composantes et non sur les matériaux, et dont la fonction est de détecter les erreurs matérielles d'un devis plutôt que d'en produire un. C'est à ce niveau que se situe le présent chapitre. | ||||
| 28 | + | ||||
| 29 | +\subsection{Trois classes de postes} | ||||
| 30 | + | ||||
| 31 | +Les trente-huit postes du devis du cas 1 (\cref{tab:21:devis}) ne se mesurent pas tous de la même façon, et la première tâche du métré est de les classer. Les postes \emph{mesurés} ont une quantité continue qui se déduit de la géométrie du bâtiment : un volume d'excavation ou de béton en mètres cubes, une surface de charpente, de toiture, de gypse ou de plancher en mètres carrés, une longueur de drain ou de gouttière en mètres linéaires. Les postes \emph{dénombrés} ont une quantité discrète que l'on compte sur les plans : fenêtres, portes, escaliers, appareils de plomberie, semaines de supervision. Les postes \emph{forfaitaires}, enfin, ne sont pas rattachés à une quantité physique parce que leur coût dépend d'un ensemble de choix (armoires de cuisine, entrée électrique, thermopompe, honoraires) que le devis résume en un montant global ; ils ne se vérifient pas par la géométrie mais par des ratios, par exemple le montant par mètre carré habitable ou la part du coût direct, comparés à des bâtiments semblables. Dans le devis du sujet, les dix-sept postes mesurés représentent 48,2 \% du sous-total des directs et des indirects, les sept postes dénombrés 24,9 \% et les quatorze forfaits 26,9 \% ; autrement dit, la géométrie contrôle directement un peu moins de la moitié du coût, et c'est sur cette moitié que porte l'essentiel du métré de contrôle, le reste relevant du jugement et de la comparaison. | ||||
| 32 | + | ||||
| 33 | +\begin{figure}[tbp] | ||||
| 34 | +\centering | ||||
| 35 | +\begin{tikzpicture}[ | ||||
| 36 | + bloc/.style={draw, rounded corners=2pt, minimum height=9mm, text width=30mm, align=center, font=\sffamily\footnotesize, line width=0.6pt}, | ||||
| 37 | + src/.style={bloc, fill=brandLight, draw=brandPrimary}, | ||||
| 38 | + op/.style={bloc, fill=white, draw=brandDark}, | ||||
| 39 | + res/.style={bloc, fill=brandPrimary, text=white, draw=brandPrimary}, | ||||
| 40 | + ctl/.style={bloc, fill=orange!8, draw=brandAmber, text width=36mm}, | ||||
| 41 | + fl/.style={-{Stealth[length=2mm]}, line width=0.6pt, color=brandGray}] | ||||
| 42 | + \node[src] (plans) at (0,0) {Plans, coupes,\\ élévations, devis descriptif}; | ||||
| 43 | + \node[op, right=5mm of plans] (dims) {Dimensions de base\\ (aire au sol, périmètre, hauteurs, ouvertures)}; | ||||
| 44 | + \node[op, right=5mm of dims] (regles) {Règles de mesure\\ par corps de métier}; | ||||
| 45 | + \node[res, right=5mm of regles] (bord) {Bordereau\\ des quantités $q_k$}; | ||||
| 46 | + \node[op, below=9mm of bord] (prix) {Prix unitaires installés $p_k$\\ (matériaux, pertes, main-d'œuvre, marge)}; | ||||
| 47 | + \node[res, left=5mm of prix] (D) {Coût direct\\ $D = \sum_k q_k p_k$}; | ||||
| 48 | + \node[op, left=5mm of D] (cn) {Indirects, incitatif\\ $\to C_N$ (ch.~21 et 23)}; | ||||
| 49 | + \node[ctl, below=9mm of dims, xshift=-8mm] (ctl) {Métré de contrôle : cohérence géométrique, dénombrements, ratios des forfaits, tolérances, effet sur $D$ et $C_N$}; | ||||
| 50 | + \draw[fl] (plans) -- (dims); \draw[fl] (dims) -- (regles); \draw[fl] (regles) -- (bord); | ||||
| 51 | + \draw[fl] (bord) -- (prix); \draw[fl] (prix) -- (D); \draw[fl] (D) -- (cn); | ||||
| 52 | + \draw[fl, dashed] (ctl.north) -- ($(dims.south)+(-8mm,0)$); | ||||
| 53 | + \draw[fl, dashed] (ctl.east) -- (D.west |- ctl.east) -- (D.south); | ||||
| 54 | +\end{tikzpicture} | ||||
| 55 | +\caption{Le processus du métré : des plans aux dimensions de base, des dimensions aux quantités par les règles de mesure propres à chaque corps de métier, des quantités au coût direct par les prix unitaires installés. Le métré de contrôle de l'évaluateur (tireté) remonte des quantités vers les dimensions et redescend vers l'effet sur le coût.}\label{fig:22:processus} | ||||
| 56 | +\figsource{schéma de l'auteur (TikZ, \texttt{manuscript/chapters/ch22.tex}).} | ||||
| 57 | +\end{figure} | ||||
| 58 | + | ||||
| 59 | +\subsection{L'ordre des corps de métier et le choix des unités} | ||||
| 60 | + | ||||
| 61 | +Un bordereau se lit dans l'ordre d'exécution du chantier, parce que c'est l'ordre dans lequel l'estimateur mesure et dans lequel les sous-traitants soumissionnent : terrassement et excavation, fondations et dalle, drainage, charpente des planchers et des murs, toiture, enveloppe (couverture, revêtement, isolation, portes et fenêtres), cloisons et finitions intérieures (gypse, peinture, planchers, escaliers, portes, armoires), mécanique (plomberie, chauffage, ventilation) et électricité, puis les ouvrages extérieurs et les frais de chantier. Les classifications normalisées de la construction, comme celle qu'utilisent les données RSMeans par divisions de travaux \parencite{rsmeans2025} ou la classification par divisions de l'indice des prix de la construction de bâtiments de Statistique Canada \parencite{statcanIPCB}, suivent cette logique et permettent de comparer des bordereaux entre eux. Le regroupement en sept blocs adopté au \cref{ch:21} (fondations et site, structure et charpente, enveloppe, finition intérieure, mécanique et électricité, aménagements extérieurs, coûts indirects) est une version condensée de cet ordre, et le chapitre le conserve pour que les deux chapitres se répondent chiffre pour chiffre. | ||||
| 62 | + | ||||
| 63 | +Le choix de l'unité n'est pas une affaire de commodité : il doit refléter ce qui fait varier le coût du poste. Le béton coûte au mètre cube parce que c'est le volume que la bétonnière livre et que le coffrage, en première approximation, lui est proportionnel ; la toiture coûte au mètre carré de versant parce que les bardeaux et la main-d'œuvre se comptent à la surface réellement couverte, non à la projection horizontale ; le drain coûte au mètre linéaire ; une fenêtre coûte à l'unité parce que sa fabrication et sa pose dépendent davantage de son existence que de sa taille, du moins dans une gamme usuelle. Choisir une mauvaise unité revient à appliquer un prix à une grandeur qui ne le commande pas, et c'est la source d'erreurs la plus sournoise du métré. Le \cref{tab:22:regles} rassemble, pour chaque corps de métier, l'unité usuelle et la règle de mesure que l'on détaille à la \cref{sec:22:regles}. | ||||
| 64 | + | ||||
| 65 | +\begin{table}[tbp] | ||||
| 66 | +\caption{Unités de mesure et règles de mesure usuelles par corps de métier dans un devis résidentiel par composantes.}\label{tab:22:regles} | ||||
| 67 | +\centering\small | ||||
| 68 | +\begin{tabularx}{\textwidth}{@{}L{30mm}L{14mm}YL{36mm}@{}} | ||||
| 69 | +\toprule | ||||
| 70 | +Corps de métier & Unité & Règle de mesure & Convention à déclarer \\ | ||||
| 71 | +\midrule | ||||
| 72 | +Excavation et remblai & m\textsuperscript{3} & volume du prisme excavé : fond à l'aire au sol plus dégagement, talus selon la nature du sol, profondeur jusqu'au dessous des semelles ; tranchées des services & dégagement, pente des talus, foisonnement exclu ou inclus \\ | ||||
| 73 | +Fondations (semelles, murs) & m\textsuperscript{3} & longueur à l'axe × hauteur × épaisseur des murs ; longueur × section des semelles ; semelles isolées à l'unité & axe ou face externe ; murs hors gel des annexes \\ | ||||
| 74 | +Dalle & m\textsuperscript{2} & aire de la dalle coulée (nette) ou aire au sol brute si le prix unitaire est calibré ainsi & brute ou nette \\ | ||||
| 75 | +Drain, imperméabilisation & m lin. & périmètre à la face externe des semelles, raccords compris & raccords au puisard \\ | ||||
| 76 | +Charpente (planchers, murs) & m\textsuperscript{2} & aire des planchers ossaturés + aire des murs (périmètre × hauteur par étage) nette ou brute d'ouvertures & ouvertures déduites ou non ; cloisons incluses ou non \\ | ||||
| 77 | +Fermes et toiture & m\textsuperscript{2} & projection horizontale, débords compris (fermes) ; projection × facteur de pente (couverture) & pente, débords, faîtages et noues \\ | ||||
| 78 | +Revêtement extérieur & m\textsuperscript{2} & périmètre × hauteur revêtue + pignons ; ouvertures souvent non déduites en compensation des retours & brut ou net \\ | ||||
| 79 | +Isolation, pare-vapeur & m\textsuperscript{2} & toutes les surfaces de l'enveloppe thermique : murs nets, plafond, murs de fondation, séparation garage, solives de rive & périmètre de l'enveloppe chauffée \\ | ||||
| 80 | +Portes, fenêtres & unité & dénombrement sur plan et élévations, par type & dimensions moyennes pour les déductions \\ | ||||
| 81 | +Gypse, peinture & m\textsuperscript{2} & plafonds des pièces finies + murs (périmètre des pièces × hauteur) − ouvertures ; cloisons comptées sur deux faces & espaces finis ; déduction des ouvertures \\ | ||||
| 82 | +Planchers finis & m\textsuperscript{2} & aire nette des pièces par type de fini & brute ou nette ; placards \\ | ||||
| 83 | +Plomberie & appareil & dénombrement des appareils et des raccords & ce qu'un « appareil » recouvre \\ | ||||
| 84 | +Électricité, chauffage, ventilation & forfait & non mesurables : contrôle par ratios (par m\textsuperscript{2}, par logement) & contenu du forfait \\ | ||||
| 85 | +Ouvrages extérieurs & m\textsuperscript{2}, m lin., forfait & aires du balcon, de l'entrée ; longueurs de clôture & inclus dans le bâtiment ou évalués à part \\ | ||||
| 86 | +\bottomrule | ||||
| 87 | +\end{tabularx} | ||||
| 88 | +\tabsource{synthèse de l'auteur d'après la pratique du métré par composantes \parencite{appraisal2026,rsmeans2025} et le devis synthétique du cas 1.} | ||||
| 89 | +\end{table} | ||||
| 90 | + | ||||
| 91 | +\section{Lecture de plans et dimensions de base}\label{sec:22:plans} | ||||
| 92 | + | ||||
| 93 | +\subsection{Les documents et leurs cotes} | ||||
| 94 | + | ||||
| 95 | +Le jeu de plans d'une résidence comprend un plan d'implantation, qui positionne le bâtiment sur le lot et donne les marges de recul et le niveau du sol fini ; un plan par niveau, sous-sol, rez-de-chaussée et étage, qui montre les murs, les cloisons, les ouvertures, les escaliers et l'affectation des pièces ; une ou plusieurs coupes, qui donnent les hauteurs de plancher à plancher, l'épaisseur des planchers, la hauteur des murs de fondation, la profondeur des semelles et la pente du toit ; des élévations, qui montrent les façades, les hauteurs de revêtement et la position des ouvertures ; et des détails de construction. Le devis descriptif, lorsqu'il existe, précise les matériaux et les finis que le plan ne montre pas : type de revêtement, épaisseur d'isolant, essence du plancher. La première habileté du métré est de savoir quelle cote lire et à quel endroit. Les dimensions hors tout d'un plan d'architecte sont presque toujours données à la face externe des murs extérieurs, parce que c'est la cote que l'excavateur et le fondeur utilisent ; les dimensions des pièces, lorsqu'elles sont indiquées, le sont à la face interne des murs finis ; et les longueurs de murs de fondation se calculent à l'axe, parce qu'un mur d'angle ne doit pas être compté deux fois. Une erreur de référence de quelques centimètres sur un périmètre de quarante mètres ne pèse pas lourd sur une surface, mais elle change de 2 à 4 \% le volume d'un mur de fondation. | ||||
| 96 | + | ||||
| 97 | +\subsection{Les conventions de superficie} | ||||
| 98 | + | ||||
| 99 | +Les conventions de superficie ont été présentées au \cref{ch:12} du point de vue du mesurage ; elles reviennent ici parce que le métré les produit toutes à partir des mêmes dimensions de base et que le choix de l'une ou de l'autre change le coût unitaire d'un même bâtiment d'un tiers. Le Manuel d'évaluation foncière du Québec définit, au bloc 07 des dossiers de propriété des bâtiments résidentiels, quatre grandeurs : l'aire au sol, « surface brute totale que contiendrait la projection au sol de tous les étages et sous-sols du bâtiment » ; le périmètre au sol ; l'aire des étages, « somme des aires de chacun des étages du bâtiment, ce qui exclut l'aire de toute mezzanine ou attique » ; et le périmètre des étages. Ces mesures sont brutes, prises à la face externe des murs ; un niveau est compté comme un étage « lorsque son plancher n'est pas plus bas que 0,4 mètre sous le niveau moyen du sol » ; les murs mitoyens sont exclus du périmètre ; un garage intégré et une verrière intégrée font partie de l'étage \parencite{mefqpartie2}. La superficie habitable des fiches de courtage, elle, n'a pas de définition réglementaire unique ; l'usage le plus répandu la prend à la face externe des murs mais exclut le garage et le sous-sol. L'aire nette intérieure, enfin, est la somme des aires des pièces mesurées à la face interne des murs et des cloisons, trémies d'escalier déduites ; c'est celle que mesure le métré des finitions. | ||||
| 100 | + | ||||
| 101 | +Pour un bâtiment à deux étages hors sol d'aire au sol $A_0$, de garage intégré d'aire brute $G$, dont les murs extérieurs ont une épaisseur $t$ et les cloisons une longueur totale $\ell$ et une épaisseur $t_c$, ces conventions se relient par des identités que l'on vérifie sur le sujet : | ||||
| 102 | +\begin{equation}\label{eq:22:conventions} | ||||
| 103 | +A_{\text{ét}} = 2A_0,\qquad A_{\text{hab}} = A_{\text{ét}} - G,\qquad | ||||
| 104 | +A_{\text{nette}} \approx A_{\text{hab}} - t\,P_{\text{int}} - t_c\,\ell - A_{\text{trémie}}, | ||||
| 105 | +\end{equation} | ||||
| 106 | +où $P_{\text{int}}$ est la longueur des murs extérieurs qui bordent les espaces habitables, cumulée sur les deux étages, et $A_{\text{trémie}}$ l'aire de la trémie d'escalier à l'étage. L'approximation tient à ce que les angles sont comptés deux fois dans le produit $t\,P_{\text{int}}$ ; le calcul exact pièce par pièce, que fait le script du chapitre, lève cette approximation. Il en résulte que l'aire nette représente typiquement 80 à 85 \% de la superficie habitable et 70 à 75 \% de l'aire des étages du Manuel, proportions dont la \cref{sec:22:exemple} donne les valeurs exactes pour le sujet. | ||||
| 107 | + | ||||
| 108 | +La forme du bâtiment intervient par le périmètre, et une propriété élémentaire mais souvent oubliée simplifie le métré des cottages à garage intégré en coin, dont le plan est une forme en L. | ||||
| 109 | + | ||||
| 110 | +\begin{proposition}{Périmètre d'une forme en L}{perimetreL} | ||||
| 111 | +Soit un rectangle de côtés $L$ et $W$ dans lequel on découpe, dans un coin, un rectangle de côtés $g_x \le L$ et $g_y \le W$. Le périmètre de la forme en L qui en résulte est égal à celui du rectangle entier, $P = 2(L + W)$, quelles que soient les dimensions du coin découpé. | ||||
| 112 | +\end{proposition} | ||||
| 113 | +\begin{proof} | ||||
| 114 | +Parcourons la forme en L à partir du coin opposé au découpage : deux côtés entiers $L$ et $W$, puis les deux côtés amputés $L - g_x$ et $W - g_y$, puis les deux côtés du rentrant $g_x$ et $g_y$. La somme vaut $L + W + (L - g_x) + (W - g_y) + g_x + g_y = 2(L + W)$. | ||||
| 115 | +\end{proof} | ||||
| 116 | + | ||||
| 117 | +La proposition signifie que, pour un cottage dont le garage occupe un coin de l'empreinte au niveau du sol et dont le sous-sol ne s'étend que sous la partie habitable, le périmètre des murs de fondation du sous-sol est le même que celui de l'empreinte entière : les deux murs intérieurs du rentrant, qui séparent le sous-sol du remblai sous le garage, remplacent exactement les deux segments de façade manquants. Elle signifie aussi que le ratio périmètre sur aire, qui gouverne les économies d'échelle géométriques de la \cref{prop:echelle}, est plus défavorable pour la forme en L que pour le rectangle de même aire, puisque l'aire diminue alors que le périmètre ne change pas. | ||||
| 118 | + | ||||
| 119 | +\subsection{Le sujet du cas 1 : plan coté et dimensions de base} | ||||
| 120 | + | ||||
| 121 | +Le sujet est un cottage à deux étages de 12,00 m de façade sur 7,92 m de profondeur, mesuré à la face externe des murs, soit une aire au sol de \msq{95.04} et un périmètre au sol de 39,84 m. Un garage simple intégré de 3,96 m sur 6,30 m occupe le coin avant gauche du rez-de-chaussée ; il repose sur une dalle sur sol et des murs hors gel, de sorte que le sous-sol, d'aire brute \msq{70.09}, ne s'étend que sous la partie habitable, en forme de L. Le toit à deux versants a une pente de 6:12 et des débords de 0,40 m ; les murs extérieurs ont une épaisseur finie de 0,30 m, la séparation entre le garage et la maison 0,15 m, les cloisons 0,10 m ; les murs de fondation, de 0,25 m d'épaisseur et de 2,44 m de hauteur, reposent sur des semelles de 0,60 m sur 0,30 m ; la hauteur de plancher à plancher est de 2,75 m et celle des murs d'ossature de 2,44 m. La \cref{fig:22:plan} donne le plan du rez-de-chaussée et de l'étage avec l'aire brute de chaque pièce, et la \cref{fig:22:coupe} la coupe transversale avec les hauteurs et le prisme d'excavation. Toutes ces dimensions sont des hypothèses du dossier synthétique, choisies pour être cohérentes avec les quantités du devis du \cref{ch:21} ; elles sont consignées dans le dictionnaire \texttt{PLAN} du script \texttt{analysis/python/cases/ch22\_metre.py}, qui en déduit tout ce qui suit. | ||||
| 122 | + | ||||
| 123 | +\begin{figure}[tbp] | ||||
| 124 | +\centering | ||||
| 125 | +\begin{tikzpicture}[scale=0.46, font=\sffamily\tiny, every node/.style={inner sep=1pt}] | ||||
| 126 | +% ---- rez-de-chaussée | ||||
| 127 | +\begin{scope} | ||||
| 128 | +\draw[line width=1.4pt] (0,0) rectangle (12.0,7.92); | ||||
| 129 | +\draw[line width=0.5pt] (0,0) rectangle (3.96,6.3); \node[align=center] at (1.98,3.15) {Garage\\24,9}; | ||||
| 130 | +\draw[line width=0.5pt] (0,6.3) rectangle (3.96,7.92); \node[align=center] at (1.98,7.11) {Buanderie 6,4}; | ||||
| 131 | +\draw[line width=0.5pt] (3.96,0) rectangle (6.3,3.1); \node[align=center] at (5.13,1.55) {Vestibule,\\escaliers\\7,3}; | ||||
| 132 | +\draw[line width=0.5pt] (3.96,3.1) rectangle (5.6,4.7); \node[align=center] at (4.78,3.9) {S. d'eau\\2,6}; | ||||
| 133 | +\draw[line width=0.5pt] (5.6,3.1) rectangle (6.3,4.7); \node[align=center, rotate=90] at (5.95,3.9) {G.-r. 1,1}; | ||||
| 134 | +\draw[line width=0.5pt] (3.96,4.7) rectangle (8.5,7.92); \node[align=center] at (6.23,6.31) {Cuisine\\14,6}; | ||||
| 135 | +\draw[line width=0.5pt] (6.3,0) rectangle (12.0,4.7); \node[align=center] at (9.15,2.35) {Salon\\26,8}; | ||||
| 136 | +\draw[line width=0.5pt] (8.5,4.7) rectangle (12.0,7.92); \node[align=center] at (10.25,6.31) {Salle à manger\\11,3}; | ||||
| 137 | +\draw[line width=1.1pt] (3.96,0) -- (3.96,6.3) -- (0,6.3); | ||||
| 138 | +% porte de garage et entrée (façade = y = 0) | ||||
| 139 | +\draw[line width=2pt, brandPrimary] (0.6,0) -- (3.34,0); | ||||
| 140 | +\draw[line width=2pt, brandPrimary] (4.6,0) -- (5.5,0); | ||||
| 141 | +\draw[line width=2pt, brandPrimary] (9.4,7.92) -- (11.2,7.92); | ||||
| 142 | +% cotes | ||||
| 143 | +\draw[|<->|, line width=0.4pt] (0,-0.9) -- (12,-0.9) node[midway, fill=white] {12,00 m}; | ||||
| 144 | +\draw[|<->|, line width=0.4pt] (-0.9,0) -- (-0.9,7.92) node[midway, fill=white, rotate=90] {7,92 m}; | ||||
| 145 | +\draw[|<->|, line width=0.4pt] (0,8.6) -- (3.96,8.6) node[midway, fill=white] {3,96}; | ||||
| 146 | +\draw[|<->|, line width=0.4pt] (12.9,0) -- (12.9,6.3) node[midway, fill=white, rotate=90] {6,30}; | ||||
| 147 | +\node[font=\sffamily\scriptsize\bfseries, anchor=south west] at (0,9.3) {Rez-de-chaussée — aire brute 95,0 m\textsuperscript{2}, garage compris}; | ||||
| 148 | +\end{scope} | ||||
| 149 | +% ---- étage | ||||
| 150 | +\begin{scope}[xshift=15.2cm] | ||||
| 151 | +\draw[line width=1.4pt] (0,0) rectangle (12.0,7.92); | ||||
| 152 | +\draw[line width=0.5pt] (0,0) rectangle (2.7,3.1); \node[align=center] at (1.35,1.55) {Salle de\\bain 8,4}; | ||||
| 153 | +\draw[line width=0.5pt] (2.7,0) rectangle (3.96,3.1); \node[align=center, rotate=90] at (3.33,1.55) {Lingerie 3,9}; | ||||
| 154 | +\draw[line width=0.5pt] (3.96,0) rectangle (5.0,3.1); \node[align=center, rotate=90] at (4.48,1.55) {Trémie 3,2}; | ||||
| 155 | +\draw[line width=0.5pt] (5.0,0) rectangle (6.3,3.1); \node[align=center, rotate=90] at (5.65,1.55) {Palier 4,0}; | ||||
| 156 | +\draw[line width=0.5pt] (6.3,0) rectangle (12.0,3.1); \node[align=center] at (9.15,1.55) {Chambre principale\\17,7}; | ||||
| 157 | +\draw[line width=0.5pt] (0,3.1) rectangle (2.7,4.1); \node[align=center] at (1.35,3.6) {G.-r. 2,7}; | ||||
| 158 | +\draw[line width=0.5pt] (2.7,3.1) rectangle (8.3,4.1); \node[align=center] at (5.5,3.6) {Corridor 5,6}; | ||||
| 159 | +\draw[line width=0.5pt] (8.3,3.1) rectangle (12.0,7.92); \node[align=center] at (10.15,5.51) {Chambre 2\\17,8}; | ||||
| 160 | +\draw[line width=0.5pt] (4.9,4.1) rectangle (8.3,7.92); \node[align=center] at (6.6,6.01) {Chambre 3\\13,0}; | ||||
| 161 | +\draw[line width=0.5pt] (0,4.1) rectangle (4.9,7.92); \node[align=center] at (2.45,6.01) {Chambre 4\\18,7}; | ||||
| 162 | +\draw[|<->|, line width=0.4pt] (0,-0.9) -- (12,-0.9) node[midway, fill=white] {12,00 m}; | ||||
| 163 | +\draw[|<->|, line width=0.4pt] (12.9,0) -- (12.9,7.92) node[midway, fill=white, rotate=90] {7,92 m}; | ||||
| 164 | +\node[font=\sffamily\scriptsize\bfseries, anchor=south west] at (0,9.3) {Étage — aire brute 95,0 m\textsuperscript{2}}; | ||||
| 165 | +\end{scope} | ||||
| 166 | +\end{tikzpicture} | ||||
| 167 | +\caption{Plan coté du sujet du cas 1 (données synthétiques) : rez-de-chaussée avec garage intégré en coin et étage ; cotes à la face externe des murs, aires brutes des pièces en mètres carrés (limites de pièces à l'axe des cloisons). La façade est en bas ; les traits épais colorés marquent la porte de garage, l'entrée principale et la porte-patio. Le sous-sol occupe la partie en L sous les espaces habitables (\msq{70.1}).}\label{fig:22:plan} | ||||
| 168 | +\figsource{\synth{schéma de l'auteur (TikZ) d'après les coordonnées du dictionnaire \texttt{PIECES} de \texttt{analysis/python/cases/ch22\_metre.py}, graine 20261031}.} | ||||
| 169 | +\end{figure} | ||||
| 170 | + | ||||
| 171 | +\begin{figure}[tbp] | ||||
| 172 | +\centering | ||||
| 173 | +\begin{tikzpicture}[scale=0.62, font=\sffamily\tiny, every node/.style={inner sep=1pt}] | ||||
| 174 | +% sol | ||||
| 175 | +\draw[line width=0.4pt, brandGray] (-5.5,0) -- (13.5,0); | ||||
| 176 | +\node[anchor=south east, font=\sffamily\tiny] at (13.5,0.05) {niveau moyen du sol}; | ||||
| 177 | +% prisme d'excavation (talus 0,5:1 ; dégagement 0,90 ; profondeur 2,60) : largeur 7,92 + 2×0,90 au fond | ||||
| 178 | +\fill[orange!10] (-0.9,-2.6) -- (8.82,-2.6) -- (10.12,0) -- (-2.2,0) -- cycle; | ||||
| 179 | +\draw[dashed, line width=0.5pt, brandAmber] (-0.9,-2.6) -- (8.82,-2.6) -- (10.12,0); | ||||
| 180 | +\draw[dashed, line width=0.5pt, brandAmber] (-0.9,-2.6) -- (-2.2,0); | ||||
| 181 | +% semelles et murs de fondation | ||||
| 182 | +\fill[gray!35] (-0.175,-2.3) rectangle (0.425,-2.6); \fill[gray!35] (7.495,-2.3) rectangle (8.095,-2.6); | ||||
| 183 | +\fill[gray!55] (0,-2.3) rectangle (0.25,0.3); \fill[gray!55] (7.67,-2.3) rectangle (7.92,0.3); | ||||
| 184 | +\fill[gray!55] (0.25,-2.3) rectangle (7.67,-2.2); | ||||
| 185 | +% murs hors sol, planchers | ||||
| 186 | +\draw[line width=1.2pt] (0,0.3) -- (0,5.8); \draw[line width=1.2pt] (7.92,0.3) -- (7.92,5.8); | ||||
| 187 | +\draw[line width=0.8pt] (0,0.3) -- (7.92,0.3); \draw[line width=0.8pt] (0,3.05) -- (7.92,3.05); \draw[line width=0.8pt] (0,5.8) -- (7.92,5.8); | ||||
| 188 | +% toit 6:12 avec débords 0,40 | ||||
| 189 | +\draw[line width=1.0pt] (-0.4,5.6) -- (3.96,7.98) -- (8.32,5.6); | ||||
| 190 | +\draw[line width=0.4pt, brandGray] (3.96,5.8) -- (3.96,7.98); | ||||
| 191 | +% cotes verticales | ||||
| 192 | +\draw[|<->|, line width=0.4pt] (-1.4,-2.3) -- (-1.4,0.14) node[midway, fill=white, rotate=90] {fondation 2,44}; | ||||
| 193 | +\draw[|<->|, line width=0.4pt] (9.0,0.3) -- (9.0,3.05) node[midway, fill=white, rotate=90] {rez 2,75}; | ||||
| 194 | +\draw[|<->|, line width=0.4pt] (9.0,3.05) -- (9.0,5.8) node[midway, fill=white, rotate=90] {étage 2,75}; | ||||
| 195 | +\draw[|<->|, line width=0.4pt] (-3.0,-2.6) -- (-3.0,0) node[midway, fill=white, rotate=90] {excavation 2,60}; | ||||
| 196 | +\draw[|<->|, line width=0.4pt] (9.0,5.8) -- (9.0,7.98) node[midway, fill=white, rotate=90] {faîte 1,98}; | ||||
| 197 | +% cotes horizontales | ||||
| 198 | +\draw[|<->|, line width=0.4pt] (0,-3.3) -- (7.92,-3.3) node[midway, fill=white] {7,92 m (face externe)}; | ||||
| 199 | +\draw[|<->|, line width=0.4pt] (-0.9,-2.95) -- (0,-2.95) node[midway, above, yshift=1pt] {0,90}; | ||||
| 200 | +\draw[|<->|, line width=0.4pt] (-2.2,0.35) -- (-0.9,0.35) node[midway, above] {talus 1,30}; | ||||
| 201 | +\draw[|<->|, line width=0.4pt] (7.92,6.3) -- (8.32,6.3) node[midway, above] {0,40}; | ||||
| 202 | +\node[anchor=west, font=\sffamily\tiny] at (4.2,7.2) {pente 6:12}; | ||||
| 203 | +\node[font=\sffamily\tiny] at (3.96,-1.2) {sous-sol (dalle à $-2{,}20$ m)}; | ||||
| 204 | +\node[font=\sffamily\tiny] at (3.96,1.6) {rez-de-chaussée}; | ||||
| 205 | +\node[font=\sffamily\tiny] at (3.96,4.4) {étage}; | ||||
| 206 | +\node[font=\sffamily\tiny, brandAmber] at (-1.1,-1.3) {prisme}; | ||||
| 207 | +\node[font=\sffamily\tiny, brandAmber] at (9.1,-1.3) {d'excavation}; | ||||
| 208 | +\end{tikzpicture} | ||||
| 209 | +\caption{Coupe transversale schématique du sujet du cas 1 (données synthétiques) : murs de fondation de 2,44 m sur semelles de 0,60 × 0,30 m, deux niveaux de 2,75 m de plancher à plancher, toit à 6:12 avec débords de 0,40 m. Le prisme d'excavation (tireté) a un fond débordant de 0,90 m des murs et des talus à 0,5 horizontal pour 1 vertical sur 2,60 m de profondeur ; son volume se calcule par la formule du prismoïde (\cref{eq:22:prismoide}).}\label{fig:22:coupe} | ||||
| 210 | +\figsource{\synth{schéma de l'auteur (TikZ) d'après le dictionnaire \texttt{PLAN} de \texttt{analysis/python/cases/ch22\_metre.py}}.} | ||||
| 211 | +\end{figure} | ||||
| 212 | + | ||||
| 213 | +Le \cref{tab:22:dimensions} rassemble les dimensions de base et les superficies du sujet selon les conventions. L'aire des étages au sens du Manuel est de \msq{190.08} (\pisq{2046}) et son périmètre des étages de 79,68 m ; la superficie habitable, brute hors garage, est de \msq{165.13} (\pisq{1777}), ce qui est la valeur de \msq{165} du dossier du sujet ; l'aire nette intérieure des espaces habitables hors sol, pièce par pièce, est de \msq{135.37}, soit 58,56 au rez-de-chaussée et 76,81 à l'étage après déduction de la trémie de \msq{2.45}. L'aire nette représente 86,9 \% de l'aire habitable et 71,2 \% de l'aire des étages. Le même coût neuf de \dollars{397567} du \cref{ch:21} s'exprime donc par \parmsq{2092} à l'aire des étages, \parmsq{2408} à la superficie habitable et \parmsq{2937} à l'aire nette : trois coûts unitaires qui diffèrent de 40 \% entre les extrêmes pour un seul et même bâtiment. C'est la raison pour laquelle le métré commence toujours par déclarer sa convention. | ||||
| 214 | + | ||||
| 215 | +\begin{table}[tbp] | ||||
| 216 | +\caption{Dimensions de base et superficies du sujet du cas 1 selon la convention retenue, et coût neuf unitaire correspondant ($C_N = \dollars{397567.33}$, \cref{ch:21}).}\label{tab:22:dimensions} | ||||
| 217 | +\centering\small | ||||
| 218 | +\begin{tabular}{@{}l l S[table-format=3.2] S[table-format=4.0] S[table-format=4.0]@{}} | ||||
| 219 | +\toprule | ||||
| 220 | +Grandeur & Convention & {m\textsuperscript{2}} & {pi\textsuperscript{2}} & {$C_N$ (\$/m\textsuperscript{2})} \\ | ||||
| 221 | +\midrule | ||||
| 222 | +Aire au sol (empreinte 12,00 × 7,92 m) & MEFQ, bloc 07, face externe & 95.04 & 1023 & {—} \\ | ||||
| 223 | +Garage intégré (3,96 × 6,30 m) & brut, face externe & 24.95 & 269 & {—} \\ | ||||
| 224 | +Sous-sol (empreinte moins garage) & brut, face externe & 70.09 & 754 & {—} \\ | ||||
| 225 | +Aire des étages (2 étages hors sol) & MEFQ, bloc 07, garage compris & 190.08 & 2046 & 2092 \\ | ||||
| 226 | +Superficie habitable & brute hors garage et sous-sol (usage du courtage) & 165.13 & 1777 & 2408 \\ | ||||
| 227 | +Aire nette intérieure hors sol & face interne, trémie déduite (métré des finis) & 135.37 & 1457 & 2937 \\ | ||||
| 228 | +Aire nette du sous-sol & face interne, escalier déduit & 58.65 & 631 & {—} \\ | ||||
| 229 | +\midrule | ||||
| 230 | +Périmètre au sol & face externe & \multicolumn{3}{l}{39,84 m} \\ | ||||
| 231 | +Périmètre des étages & MEFQ (2 étages) & \multicolumn{3}{l}{79,68 m} \\ | ||||
| 232 | +Cloisons intérieures & rez / étage / sous-sol & \multicolumn{3}{l}{21,52 / 47,94 / 20,80 m} \\ | ||||
| 233 | +Séparation garage–maison & deux segments du rentrant & \multicolumn{3}{l}{10,26 m} \\ | ||||
| 234 | +\bottomrule | ||||
| 235 | +\end{tabular} | ||||
| 236 | +\tabsource{\synth{\texttt{analysis/python/cases/ch22\_metre.py}, fonctions \texttt{empreinte}, \texttt{superficies} et \texttt{cloisons}} ; définitions MEFQ d'après \textcite{mefqpartie2} ; conversion $1\,\text{m}^2 = 10{,}7639\,\text{pi}^2$.} | ||||
| 237 | +\end{table} | ||||
| 238 | + | ||||
| 239 | +\section{Règles de mesure par corps de métier}\label{sec:22:regles} | ||||
| 240 | + | ||||
| 241 | +Les règles qui suivent sont celles d'un métré de composantes, c'est-à-dire d'un niveau de détail où chaque poste est une surface, un volume ou une longueur d'ouvrage fini, et non une liste de matériaux. Chacune est énoncée, justifiée et appliquée au sujet ; les quantités obtenues sont confrontées au devis à la \cref{sec:22:exemple}. | ||||
| 242 | + | ||||
| 243 | +\subsection{Terrassement et excavation} | ||||
| 244 | + | ||||
| 245 | +Le volume d'excavation n'est pas le volume du sous-sol. Il faut creuser plus large que les murs, pour que les ouvriers puissent coffrer, imperméabiliser et drainer, et plus profond que la dalle, pour asseoir les semelles sur un lit de pierre nette ; et, sauf si l'on étaye, les parois de la fouille doivent être inclinées pour ne pas s'effondrer, selon une pente qui dépend de la nature du sol. L'excavation a donc la forme d'un prismoïde dont la base, au fond de la fouille, est l'empreinte du sous-sol élargie d'un dégagement $d$ de chaque côté, et dont la section croît avec la hauteur selon la pente des talus $m$ (horizontal pour un vertical). Pour un polygone rectiligne d'aire $A$ et de périmètre $P$ décalé vers l'extérieur d'une distance $e$, l'aire décalée vaut | ||||
| 246 | +\begin{equation}\label{eq:22:decalage} | ||||
| 247 | +A(e) = A + P\,e + 4e^2, | ||||
| 248 | +\end{equation} | ||||
| 249 | +le terme $4e^2$ venant de ce qu'un polygone rectiligne simple compte quatre angles convexes nets (chaque angle rentrant retranche ce qu'un angle convexe ajoute), et le volume du prismoïde de profondeur $h$ se calcule par la formule classique | ||||
| 250 | +\begin{equation}\label{eq:22:prismoide} | ||||
| 251 | +V = \frac{h}{6}\bigl[A(d) + 4A(d + \tfrac{1}{2}mh) + A(d + mh)\bigr], | ||||
| 252 | +\end{equation} | ||||
| 253 | +exacte pour tout solide dont les sections sont des polynômes de degré au plus trois en la hauteur, ce qui est le cas ici. Pour le sujet, avec $A = \msq{70.09}$, $P = 39{,}84$ m, $d = 0{,}90$ m, $m = 0{,}5$ et $h = 2{,}60$ m, les trois sections valent 109,19, 141,45 et \msq{177.10} et le volume du prismoïde \qty{369.25}{\metre\cubed}. S'y ajoutent la tranchée des murs hors gel du garage, 10,26 m sur 1,00 m de largeur et 1,50 m de profondeur, soit \qty{15.39}{\metre\cubed}, et la tranchée des raccordements d'aqueduc et d'égout, 15 m sur 0,90 m sur 1,80 m, soit \qty{24.30}{\metre\cubed} : au total \qty{408.94}{\metre\cubed}. Le devis en compte 420, un écart de $-2{,}6$ \% qui tient dans la précision des hypothèses de dégagement et de talus. Le volume mesuré en place ne tient pas compte du foisonnement, l'augmentation de volume du sol excavé, qui intéresse le transport des déblais mais non le prix au mètre cube excavé lorsque celui-ci est exprimé, comme ici, en volume en place ; le remblai, compté dans le même poste, est mesuré sur le même volume. | ||||
| 254 | + | ||||
| 255 | +\subsection{Fondations, dalle et drainage} | ||||
| 256 | + | ||||
| 257 | +Le béton des murs de fondation se mesure à l'axe, parce que la longueur à l'axe est la seule qui ne compte ni deux fois ni zéro fois les angles : pour un polygone rectiligne de périmètre externe $P$ et d'épaisseur de mur $t_f$ à quatre angles convexes nets, la longueur à l'axe est $P - 4t_f$. Le volume des murs est alors $(P - 4t_f)\,H_f\,t_f$ et celui des semelles filantes $(P - 4t_f)\,b_s h_s$, où $H_f$ est la hauteur du mur et $b_s \times h_s$ la section de la semelle, la différence entre l'axe du mur et celui de la semelle étant négligeable. Pour le sujet, la longueur à l'axe est de $39{,}84 - 4 \times 0{,}25 = 38{,}84$ m, le volume des murs de $38{,}84 \times 2{,}44 \times 0{,}25 = \qty{23.69}{\metre\cubed}$, celui des semelles filantes de $38{,}84 \times 0{,}60 \times 0{,}30 = \qty{6.99}{\metre\cubed}$, celui des quatre semelles de colonnes de $0{,}90 \times 0{,}90 \times 0{,}30$ m de \qty{0.97}{\metre\cubed}, et celui des murs hors gel du garage (10,26 m sur 1,50 m de hauteur et 0,25 m d'épaisseur, sur semelles de 0,50 × 0,25 m) de $3{,}85 + 1{,}28 = \qty{5.13}{\metre\cubed}$ : au total \qty{36.79}{\metre\cubed}, contre 38 au devis ($-3{,}2$ \%). La dalle est le poste qui illustre le mieux l'importance de la convention : la surface de béton réellement coulée à l'intérieur des murs de fondation est d'environ \msq{59} pour le sous-sol et \msq{21} pour le garage, mais le devis mesure la dalle à l'aire au sol brute, \msq{95}, et son prix unitaire de \parmsq{68.67} est calibré sur cette base ; le métré de contrôle doit appliquer la même convention, faute de quoi il conclurait à une surestimation de 20 \% là où il n'y a qu'une différence de référence. Le drain français court à la face externe des semelles ; sa longueur est le périmètre externe augmenté de huit fois le débord de la semelle, $(0{,}60 - 0{,}25)/2 = 0{,}175$ m, soit 1,40 m, plus le raccord au puisard, 1,00 m : 42,24 m contre 42 au devis. | ||||
| 258 | + | ||||
| 259 | +\subsection{Charpente et toiture} | ||||
| 260 | + | ||||
| 261 | +La charpente des planchers se mesure à l'aire brute des planchers ossaturés : au rez-de-chaussée, l'empreinte moins la dalle du garage, soit \msq{70.09}, et à l'étage l'empreinte entière, \msq{95.04}, en tout \msq{165.13} ; la trémie d'escalier n'est pas déduite parce que son chevêtre coûte au moins autant que le plancher qu'il remplace. La charpente des murs extérieurs se mesure au périmètre multiplié par la hauteur d'ossature de chaque étage, nette des ouvertures : | ||||
| 262 | +\begin{equation}\label{eq:22:murs} | ||||
| 263 | +A_{\text{murs}} = P \times h_{\text{mur}} \times n_{\text{ét}} - \sum_{j} n_j\,a_j , | ||||
| 264 | +\end{equation} | ||||
| 265 | +où $n_j$ est le nombre d'ouvertures de type $j$ et $a_j$ leur aire unitaire. Pour le sujet, $39{,}84 \times 2{,}44 \times 2 = \msq{194.42}$ bruts, dont on retranche quatorze fenêtres hors sol de $1{,}20 \times 1{,}40$ m (\msq{23.52}), trois portes extérieures de $0{,}91 \times 2{,}03$ m (\msq{5.54}) et une porte de garage de $2{,}74 \times 2{,}13$ m (\msq{5.84}), soit \msq{34.90} d'ouvertures et \msq{159.52} de murs nets ; charpente totale \msq{324.65} contre 330 au devis ($-1{,}6$ \%). La règle appliquée ici exclut les cloisons intérieures, dont l'ossature légère est réputée comprise dans le prix du gypse posé ; c'est une convention du devis, et le \cref{ch:23} montre qu'elle doit être connue avant d'emprunter un prix unitaire à une autre source. Le toit se mesure deux fois : les fermes à la projection horizontale, débords compris, parce que c'est ainsi que le fabricant les facture, et la couverture à la surface réelle des versants, qui est la projection multipliée par le facteur de pente : | ||||
| 266 | +\begin{equation}\label{eq:22:toit} | ||||
| 267 | +A_{\text{couv}} = (L + 2d_t)(W + 2d_t)\,\sqrt{1 + p^2}, | ||||
| 268 | +\end{equation} | ||||
| 269 | +où $d_t$ est le débord et $p$ la pente exprimée en élévation par unité de course (0,5 pour 6:12). Pour le sujet, la projection est de $12{,}80 \times 8{,}72 = \msq{111.62}$ (devis : 110, $+1{,}5$ \%) et la couverture de $111{,}62 \times 1{,}1180 = \msq{124.79}$ (devis : 125). Un toit à 8:12 aurait un facteur de 1,2019 et une couverture 7,5 \% plus grande pour la même projection ; un toit à quatre versants (en croupe) de même pente a la même surface de couverture qu'un toit à deux versants de même projection, mais davantage d'arêtiers et de pertes. | ||||
| 270 | + | ||||
| 271 | +\subsection{Enveloppe : revêtement, isolation, ouvertures} | ||||
| 272 | + | ||||
| 273 | +Le revêtement extérieur se mesure au périmètre multiplié par la hauteur revêtue, du dessus de la fondation au soffite, plus les pignons. Le sujet a deux pignons triangulaires de base 7,92 m et de hauteur $7{,}92/2 \times 0{,}5 = 1{,}98$ m, soit \msq{7.84} chacun ; les murs revêtus mesurent $39{,}84 \times 5{,}60 = \msq{223.10}$ et le total \msq{238.79}. Le devis compte \msq{240} et n'a donc pas déduit les ouvertures : c'est une convention répandue pour les revêtements, où la main-d'œuvre des retours, des cadrages et des solins autour des ouvertures compense à peu près la surface non couverte, de sorte que mesurer brut et facturer brut revient à facturer net avec un supplément d'ouvertures. L'isolation et le pare-vapeur se mesurent sur toute l'enveloppe thermique, c'est-à-dire la frontière entre l'espace chauffé et l'extérieur ou les espaces non chauffés : murs extérieurs nets d'ouvertures (\msq{159.52}), plafond de l'étage sous l'entretoit (\msq{95.04}), murs de fondation isolés de l'intérieur nets des deux fenêtres du sous-sol ($38{,}84 \times 2{,}44 - 3{,}40 = \msq{91.37}$), séparation entre le garage non chauffé et la maison, murs ($10{,}26 \times 2{,}44 = \msq{25.03}$) et plafond du garage (\msq{24.95}), et solives de rive aux deux niveaux ($2 \times 39{,}84 \times 0{,}30 = \msq{23.90}$) : \msq{419.82}, contre 420 au devis. Les portes et fenêtres se dénombrent sur les plans et les élévations ; le sujet en compte seize fenêtres (six au rez-de-chaussée, huit à l'étage, deux au sous-sol), trois portes extérieures (entrée, porte-patio, porte de service du garage) et une porte de garage. | ||||
| 274 | + | ||||
| 275 | +\subsection{Finitions intérieures} | ||||
| 276 | + | ||||
| 277 | +Le gypse est le poste le plus laborieux du métré résidentiel, parce qu'il couvre les plafonds et toutes les faces de tous les murs de toutes les pièces finies. La règle est la suivante : pour chaque pièce finie, l'aire nette du plafond plus le périmètre net multiplié par la hauteur des murs ; les cloisons sont ainsi comptées sur leurs deux faces, une fois par pièce qu'elles bordent, et les murs extérieurs une fois ; on ajoute la face du côté garage de la séparation garage–maison, exigée comme séparation coupe-feu, et le plafond du garage ; on déduit les ouvertures, les portes intérieures sur deux faces. Pour le sujet, les plafonds des pièces finies totalisent \msq{209.63} garage compris, les murs \msq{582.53}, la face garage de la séparation \msq{25.03} et les ouvertures \msq{84.19} (seize fenêtres, trois portes extérieures, quatorze portes intérieures comptées deux fois) : \msq{733.00}. Le devis compte \msq{620}, et c'est l'écart le plus important du métré de contrôle, $+18{,}2$ \% ; il est discuté à la \cref{sec:22:exemple}. La peinture se mesure sur la même surface. Les planchers finis se mesurent à l'aire nette des pièces par type de fini : bois franc au salon, à la salle à manger, aux chambres, au corridor, au palier et aux placards (\msq{103.56}) ; céramique au vestibule, à la cuisine, à la salle d'eau, à la buanderie et à la salle de bain (\msq{31.81}) ; plancher flottant au sous-sol, que le devis mesure à l'aire brute du sous-sol (\msq{70.09}) alors que l'aire finie nette, salle mécanique et escalier exclus, n'est que de \msq{49.31}. Les escaliers, les portes intérieures (quatorze) et les armoires se dénombrent ou s'estiment au forfait. | ||||
| 278 | + | ||||
| 279 | +\subsection{Mécanique, électricité et ouvrages extérieurs} | ||||
| 280 | + | ||||
| 281 | +La plomberie se compte en appareils, chaque appareil recouvrant son alimentation, son évacuation, sa ventilation et sa robinetterie : évier, lave-vaisselle, réfrigérateur, laveuse et cuve de buanderie, lavabo et toilette de la salle d'eau, lavabo, toilette, baignoire et douche de la salle de bain, deux robinets extérieurs et un drain de plancher, quatorze au total pour le sujet. L'électricité, la ventilation, le chauffage et l'éclairage sont des forfaits dont le contenu doit être lu dans le devis descriptif (entrée de 200 A, échangeur d'air, thermopompe centrale avec plinthes d'appoint) et dont le contrôle passe par des ratios : le forfait d'électricité du sujet, \dollars{14096}, représente \qty{85}{\dollar\per\metre\squared} habitable et 4,7 \% du coût direct, et la thermopompe \dollars{10481}, soit 3,5 \% ; ces ratios se comparent à ceux de devis semblables plutôt qu'à une géométrie. Les ouvrages extérieurs se mesurent en aires (perron de $1{,}50 \times 2{,}40$ m et balcon de $3{,}00 \times 3{,}50$ m, \msq{14.10} ; entrée asphaltée de $5{,}00 \times 11{,}00$ m, \msq{55}) ou en longueurs (gouttières sur les deux rives, $2 \times 12{,}80 = 25{,}60$ m, plus quatre descentes de 5,80 m, 48,80 m au total contre 48 au devis). Comme le \cref{ch:21} l'a rappelé, ces ouvrages doivent figurer soit dans le coût du bâtiment, soit dans une évaluation séparée des améliorations du site, jamais aux deux endroits. | ||||
| 282 | + | ||||
| 283 | +\section{Du métré au coût}\label{sec:22:cout} | ||||
| 284 | + | ||||
| 285 | +\subsection{Quantités mesurées, quantités à commander, pertes et chutes} | ||||
| 286 | + | ||||
| 287 | +Le coût direct d'un devis par composantes est la somme des produits des quantités par les prix unitaires installés, $D = \sum_k q_k p_k$ (\cref{eq:21:composantes}). La quantité $q_k$ qui y figure est la quantité d'ouvrage \emph{en place}, celle que mesure le métré ; elle n'est pas la quantité de matériau qu'il faut acheter. Entre les deux s'interposent les pertes et les chutes : découpes des feuilles de gypse autour des ouvertures, rangs de départ et de faîtage des bardeaux, chutes de lames de bois franc en bout de rangée, carreaux de céramique cassés ou coupés, casse de briques, surconsommation de béton dans les coffrages qui fléchissent. La quantité à commander d'un matériau $k$ est | ||||
| 288 | +\begin{equation}\label{eq:22:pertes} | ||||
| 289 | +q_k^{\text{cmd}} = q_k\,(1 + w_k), | ||||
| 290 | +\end{equation} | ||||
| 291 | +où $w_k$ est le taux de pertes et de chutes, propre au matériau, à la complexité du plan et à l'habileté de la main-d'œuvre. Un prix unitaire \emph{installé} inclut déjà ces pertes, parce qu'il est construit sur le coût du matériau acheté rapporté à la surface posée ; un prix de matériau au mètre carré de produit, lui, ne les inclut pas. Confondre les deux revient à oublier ou à compter deux fois 5 à 15 \% du coût des matériaux. Le \cref{tab:22:pertes} illustre, pour dix postes du sujet, le passage de la quantité mesurée à la quantité à commander pour des taux déclarés comme hypothèses pédagogiques, parce qu'aucune source publique vérifiée n'en fixe la valeur ; les guides de coûts sous licence en publient, par matériau et par type d'ouvrage, et c'est à eux qu'un estimateur se réfère \parencite{rsmeans2025,marshallswift2025}. Valorisé au prix posé, le surplus de matériaux de ces dix postes représente \dollars{11284}, soit 3,8 \% du coût direct du sujet : une erreur sur le traitement des pertes n'est pas négligeable, mais elle est du même ordre que la tolérance d'un métré de contrôle. | ||||
| 292 | + | ||||
| 293 | +\begin{table}[tbp] | ||||
| 294 | +\caption{Pertes et chutes : passage de la quantité mesurée du devis à la quantité à commander pour des taux illustratifs (hypothèses pédagogiques, non sourcées), sujet du cas 1.}\label{tab:22:pertes} | ||||
| 295 | +\centering\small | ||||
| 296 | +\begin{tabular}{@{}l l S[table-format=3.0] S[table-format=2.0] S[table-format=3.1] S[table-format=2.1]@{}} | ||||
| 297 | +\toprule | ||||
| 298 | +Poste & Unité & {Mesuré} & {Taux (\%)} & {À commander} & {Surplus} \\ | ||||
| 299 | +\midrule | ||||
| 300 | +Fondations béton (semelles, murs) & m\textsuperscript{3} & 38 & 5 & 39.9 & 1.9 \\ | ||||
| 301 | +Dalle de sous-sol & m\textsuperscript{2} & 95 & 5 & 99.8 & 4.8 \\ | ||||
| 302 | +Charpente murs et planchers & m\textsuperscript{2} & 330 & 10 & 363.0 & 33.0 \\ | ||||
| 303 | +Couverture bardeaux d'asphalte & m\textsuperscript{2} & 125 & 10 & 137.5 & 12.5 \\ | ||||
| 304 | +Revêtement extérieur & m\textsuperscript{2} & 240 & 10 & 264.0 & 24.0 \\ | ||||
| 305 | +Isolation et pare-vapeur & m\textsuperscript{2} & 420 & 5 & 441.0 & 21.0 \\ | ||||
| 306 | +Gypse et tirage de joints & m\textsuperscript{2} & 620 & 12 & 694.4 & 74.4 \\ | ||||
| 307 | +Planchers bois franc & m\textsuperscript{2} & 95 & 8 & 102.6 & 7.6 \\ | ||||
| 308 | +Planchers céramique & m\textsuperscript{2} & 35 & 10 & 38.5 & 3.5 \\ | ||||
| 309 | +Planchers flottants (sous-sol) & m\textsuperscript{2} & 70 & 8 & 75.6 & 5.6 \\ | ||||
| 310 | +\bottomrule | ||||
| 311 | +\end{tabular} | ||||
| 312 | +\tabsource{\synth{\texttt{analysis/python/cases/ch22\_metre.py}, fonction \texttt{pertes}, dictionnaire \texttt{PERTES}} ; les taux sont des ordres de grandeur illustratifs déclarés comme tels, à remplacer par ceux d'un guide de coûts sous licence dans un mandat réel.} | ||||
| 313 | +\end{table} | ||||
| 314 | + | ||||
| 315 | +\subsection{La structure d'un prix unitaire installé} | ||||
| 316 | + | ||||
| 317 | +Le prix unitaire installé d'un poste se décompose en quatre termes : le coût des matériaux par unité d'ouvrage, pertes comprises ; le coût de la main-d'œuvre, produit du nombre d'heures par unité d'ouvrage et du taux horaire chargé ; le coût de l'équipement et des consommables ; et les frais généraux et la marge du corps de métier, en proportion du tout : | ||||
| 318 | +\begin{equation}\label{eq:22:prix-unitaire} | ||||
| 319 | +p_k = \bigl[m_k(1 + w_k) + h_k\,s_k + e_k\bigr](1 + \mu_k), | ||||
| 320 | +\end{equation} | ||||
| 321 | +où $m_k$ est le prix d'achat du matériau par unité d'ouvrage, $w_k$ le taux de pertes, $h_k$ la productivité inverse en heures par unité, $s_k$ le taux horaire chargé du métier, $e_k$ l'équipement et $\mu_k$ la marge du sous-traitant. Trois observations découlent de cette structure. La première est que la part de la main-d'œuvre varie énormément d'un poste à l'autre : faible pour une thermopompe ou des fenêtres, où le matériau domine, élevée pour le tirage de joints, la peinture ou la pose de céramique, où elle dépasse souvent la moitié du prix ; l'indexation d'un devis par un indice unique, comme au \cref{ch:21}, suppose que la composition du devis ressemble à celle du panier de l'indice. La deuxième est que la productivité $h_k$ est la grandeur la plus incertaine : elle dépend de la complexité du plan, de l'accès, de la saison et de la qualité d'exécution exigée, et c'est par elle que deux soumissions pour le même ouvrage diffèrent le plus. La troisième est que la marge $\mu_k$ du sous-traitant est déjà dans le prix : l'incitatif de l'entrepreneur du \cref{ch:21} rémunère la coordination et le risque du projet, non le métier, et un devis composé de prix de sous-traitants installés ne doit pas se voir appliquer une seconde marge de métier. | ||||
| 322 | + | ||||
| 323 | +Le taux horaire chargé $s_k$ est, au Québec, une donnée largement réglementée. Les salaires de l'industrie de la construction sont fixés par les conventions collectives sectorielles négociées sous l'égide de la Commission de la construction du Québec, par métier et par statut (apprenti, compagnon), dans quatre secteurs : génie civil et voirie, industriel, institutionnel et commercial, et résidentiel, ce dernier distinguant le résidentiel léger du résidentiel lourd ; l'employeur a l'obligation de payer les salariés selon les conventions en vigueur, et la CCQ publie un outil de consultation des taux par date et par secteur, les textes des conventions ayant priorité en cas de divergence \parencite{ccqSalaires}. Le taux chargé ajoute au salaire les avantages sociaux, les cotisations et les charges de l'employeur, qui en représentent une fraction importante. Le chapitre ne chiffre aucun taux horaire, parce qu'ils varient par métier et par date et qu'ils n'ont pas été relevés dans le registre de sources de l'ouvrage ; l'évaluateur qui construit ou vérifie un prix unitaire doit consulter la convention applicable à la date des travaux. Ce qu'il faut retenir pour la méthode du coût, c'est que la main-d'œuvre réglementée est l'un des moteurs de la hausse des coûts de construction mesurée par l'IPCB (\cref{fig:21:ipcb}) et que l'écart entre un prix unitaire d'un guide calibré sur Montréal et le coût réel dans une autre région tient en partie à la structure des secteurs et des métiers mobilisés. | ||||
| 324 | + | ||||
| 325 | +\subsection{Cohérence des conventions entre quantité et prix} | ||||
| 326 | + | ||||
| 327 | +Un prix unitaire n'a de sens que rapporté à la convention de mesure sur laquelle il a été établi. Un prix de gypse posé au mètre carré \emph{net}, ouvertures déduites, est plus élevé qu'un prix au mètre carré \emph{brut}, parce que les deux prix doivent produire le même montant pour le même ouvrage ; un prix de dalle à l'aire au sol brute est plus bas qu'un prix à la surface coulée ; un prix de revêtement « ouvertures non déduites » est plus bas qu'un prix net. Le métré de contrôle doit donc toujours commencer par identifier la convention de chaque poste du devis, et la seule vérification qui vaille est celle qui recalcule la quantité \emph{dans la même convention}. Lorsqu'un prix unitaire est emprunté à une autre source, un guide, une soumission, un devis antérieur, il faut le convertir : si $q^{\text{brut}}$ et $q^{\text{net}}$ sont les deux mesures du même ouvrage, les prix cohérents vérifient $p^{\text{brut}}\,q^{\text{brut}} = p^{\text{net}}\,q^{\text{net}}$, de sorte que | ||||
| 328 | +\begin{equation}\label{eq:22:conversion} | ||||
| 329 | +p^{\text{brut}} = p^{\text{net}}\,\frac{q^{\text{net}}}{q^{\text{brut}}} . | ||||
| 330 | +\end{equation} | ||||
| 331 | +Pour le revêtement du sujet, où les ouvertures représentent 34,90 des \msq{238.79} bruts, un prix net serait 17 \% plus élevé que le prix brut de \parmsq{119.27} du devis. Cette règle de cohérence est l'exact pendant, au niveau du poste, de celle que le \cref{ch:21} a posée au niveau du bâtiment pour le coût au mètre carré. | ||||
| 332 | + | ||||
| 333 | +\subsection{Propagation des erreurs de mesure} | ||||
| 334 | + | ||||
| 335 | +Chaque quantité du bordereau est entachée d'une erreur : imprécision des cotes, hypothèses de dégagement et de talus, choix d'inclure ou non une ouverture, arrondis. Comment ces erreurs se transmettent-elles au coût direct ? Notons $\varepsilon_k$ l'erreur relative sur la quantité du poste $k$ et $\omega_k = q_k p_k / D$ la part du poste dans le coût direct. Au premier ordre, | ||||
| 336 | +\begin{equation}\label{eq:22:propagation} | ||||
| 337 | +\frac{\Delta D}{D} = \sum_k \omega_k\,\varepsilon_k , | ||||
| 338 | +\end{equation} | ||||
| 339 | +l'erreur relative du coût direct est la moyenne des erreurs relatives des postes pondérée par leur poids dans le coût. Si les erreurs sont indépendantes, d'espérance nulle et d'écart type relatif $\sigma_k$, la variance de l'erreur relative du coût direct est $\sum_k \omega_k^2 \sigma_k^2$ ; avec un même $\sigma$ pour tous les postes, | ||||
| 340 | +\begin{equation}\label{eq:22:variance} | ||||
| 341 | +\frac{\sigma_D}{D} = \sigma\sqrt{\sum_k \omega_k^2} = \sigma\sqrt{H}, | ||||
| 342 | +\end{equation} | ||||
| 343 | +où $H = \sum_k \omega_k^2$ est l'indice de concentration de Herfindahl du devis, compris entre $1/K$ pour $K$ postes de poids égaux et 1 pour un devis réduit à un seul poste. La proposition suivante en tire la conséquence qui compte pour l'évaluateur. | ||||
| 344 | + | ||||
| 345 | +\begin{proposition}{Diversification des erreurs de métré}{diversification} | ||||
| 346 | +Pour un devis de $K$ postes directs dont les quantités sont entachées d'erreurs relatives indépendantes de même écart type $\sigma$, l'écart type relatif du coût direct vérifie $\sigma/\sqrt{K} \le \sigma_D/D \le \sigma$. La borne inférieure est atteinte lorsque tous les postes ont le même poids ; la borne supérieure lorsque les erreurs sont parfaitement corrélées, cas auquel l'\cref{eq:22:propagation} donne directement $\sigma_D/D = \sigma$. Le nombre $1/H$ est le nombre de postes de poids égaux qui produiraient la même dispersion : c'est le nombre effectif de postes du devis. | ||||
| 347 | +\end{proposition} | ||||
| 348 | +\begin{proof} | ||||
| 349 | +Sous la contrainte $\sum_k \omega_k = 1$, $\omega_k \ge 0$, la fonction convexe $\sum_k \omega_k^2$ est minimale au point $\omega_k = 1/K$, où elle vaut $1/K$, et maximale aux sommets du simplexe, où elle vaut 1 ; d'où $1/K \le H \le 1$ et, par l'\cref{eq:22:variance}, $\sigma/\sqrt{K} \le \sigma_D/D \le \sigma$. Si les erreurs sont parfaitement corrélées, $\varepsilon_k = \varepsilon$ pour tout $k$, et l'\cref{eq:22:propagation} donne $\Delta D/D = \varepsilon$, donc $\sigma_D/D = \sigma$. Enfin, $K'$ postes de poids égaux ont $H = 1/K'$ ; le devis a la même dispersion qu'un devis uniforme de $K' = 1/H$ postes. | ||||
| 350 | +\end{proof} | ||||
| 351 | + | ||||
| 352 | +Pour le devis du sujet, les trente-trois postes directs ont un indice de Herfindahl de 0,0539, soit 18,6 postes effectifs ; le poste le plus lourd, la charpente, pèse 13,2 \% du coût direct. Des erreurs de mesure indépendantes de 5 \% sur chaque poste ne produisent qu'une erreur de $0{,}05 \times \sqrt{0{,}0539} = 1{,}16$ \% sur le coût direct, soit \dollars{3468}, et, par le multiplicateur $(1 + \tau_I)(1 + \tau_E) = 1{,}3304$ du \cref{ch:21}, d'environ \dollars{4613} sur le coût neuf. Si les mêmes erreurs étaient parfaitement corrélées, par exemple parce qu'une cote de façade mal lue affecte tous les postes proportionnels au périmètre, l'erreur serait de 5 \% sur $D$ et de \dollars{16435} sur $C_N$. La leçon est double : la diversification protège le coût neuf contre les petites erreurs dispersées, mais elle est sans effet contre une erreur sur une dimension de base, qui se répercute sur tous les postes dans le même sens. C'est pourquoi le métré de contrôle commence par les dimensions de base et non par les postes. | ||||
| 353 | + | ||||
| 354 | +\section{Exemple intégral : bordereau et métré de contrôle du sujet du cas 1}\label{sec:22:exemple} | ||||
| 355 | + | ||||
| 356 | +\begin{synthetique} | ||||
| 357 | +Le sujet est la maison fictive du premier dossier de cas, décrite au \cref{ch:21} : cottage à étages de \msq{165} habitables sur un terrain de \msq{620}, construit en 1998 dans le secteur Hull de Gatineau, qualité moyenne, garage simple intégré, sous-sol fini, quatre chambres, une salle de bain et une salle d'eau (\texttt{data/synthetic/cas1\_gatineau\_sujet.json}). Son devis par composantes, \texttt{data/synthetic/cas1\_gatineau\_couts.csv}, compte 38 postes (33 directs, 5 indirects) générés par \texttt{analysis/python/traite/synth.py} avec la graine 20261031 ; il est repris ici sans aucune modification, de sorte que $D = \dollars{298826.17}$, $I = \dollars{62598.68}$ et $C_N = \dollars{397567.33}$ comme au \cref{ch:21}. Le plan coté (\cref{fig:22:plan,fig:22:coupe}) est une construction du présent chapitre, cohérente avec les quantités du devis ; ses dimensions sont des hypothèses déclarées dans \texttt{analysis/python/cases/ch22\_metre.py}, qui imprime tous les chiffres de cette section, vérifiés par \texttt{analysis/python/tests/test\_ch22.py}. Aucun chiffre ne décrit une propriété, un plan ou un entrepreneur réels ; les taux de pertes du \cref{tab:22:pertes} sont des ordres de grandeur illustratifs. | ||||
| 358 | +\end{synthetique} | ||||
| 359 | + | ||||
| 360 | +\begin{exemple}{Métré de contrôle du devis de 38 postes}{metre} | ||||
| 361 | +L'évaluateur reçoit le devis par composantes du constructeur et le plan coté du sujet. Il procède en cinq étapes : lecture du bordereau et classement des postes, recalcul des quantités mesurées et dénombrées par les règles de la \cref{sec:22:regles}, qualification des écarts selon une tolérance déclarée, contrôle des forfaits par ratios, et chiffrage de l'effet des écarts sur le coût direct et le coût neuf. | ||||
| 362 | + | ||||
| 363 | +\emph{Étape 1 : le bordereau.} Le \cref{tab:22:bordereau} présente le bordereau complet des 38 postes dans l'ordre des sept blocs du \cref{ch:21}, avec l'unité, la quantité, le prix unitaire installé et le montant de chacun ; les sous-totaux par bloc sont ceux du \cref{tab:21:devis}. Le classement par type d'unité (\cref{fig:22:repartition}) montre que les postes mesurés dominent les fondations, la structure et l'enveloppe, que les postes dénombrés pèsent lourd dans l'enveloppe (fenêtres et portes, \dollars{22770}) et dans la mécanique (appareils de plomberie), et que les forfaits concentrent la mécanique et l'électricité, les armoires et les coûts indirects. Sur le sous-total de \dollars{361424.85}, 48,2 \% sont mesurés, 24,9 \% dénombrés et 26,9 \% forfaitaires. | ||||
| 364 | + | ||||
| 365 | +\emph{Étape 2 : les quantités recalculées.} Les dix-sept postes mesurés et les sept postes dénombrés sont recalculés à partir du plan (\cref{tab:22:verification}). Les dimensions de base donnent une aire au sol de \msq{95.04} et un périmètre de 39,84 m, cohérents avec la dalle de \msq{95} du devis ; l'excavation ressort à \qty{408.94}{\metre\cubed} ($-2{,}6$ \%), les fondations à \qty{36.79}{\metre\cubed} ($-3{,}2$ \%), le drain à 42,24 m ($+0{,}6$ \%), la charpente à \msq{324.65} ($-1{,}6$ \%), les fermes à \msq{111.62} ($+1{,}5$ \%), la couverture à \msq{124.79} ($-0{,}2$ \%), le revêtement à \msq{238.79} ($-0{,}5$ \%), l'isolation à \msq{419.82} (0,0 \%), les gouttières à 48,80 m ($+1{,}7$ \%), le balcon et le perron à \msq{14.10}, l'entrée à \msq{55} et le plancher flottant à \msq{70.09} ; les sept dénombrements (16 fenêtres, 3 portes extérieures, 1 porte de garage, 2 escaliers, 14 portes intérieures, 14 appareils, 26 semaines) concordent exactement. Quatre postes s'écartent davantage : le gypse et la peinture ressortent à \msq{733.00} contre 620 ($+18{,}2$ \%), le bois franc à \msq{103.56} contre 95 ($+9{,}0$ \%) et la céramique à \msq{31.81} contre 35 ($-9{,}1$ \%). | ||||
| 366 | + | ||||
| 367 | +\emph{Étape 3 : la qualification des écarts.} La tolérance retenue est de 5 \% pour déclarer un poste conforme, de 10 \% pour le déclarer à préciser, au-delà de quoi il est à justifier ; ces seuils sont une convention de l'ouvrage, calibrée sur la précision que l'on peut attendre d'un métré de composantes fait à partir d'un plan d'architecte sans devis descriptif complet. Vingt postes sont conformes, deux à préciser et deux à justifier (\cref{fig:22:ecarts}). Les deux postes à préciser s'expliquent l'un par l'autre : le total des planchers finis hors sol, \msq{135.37} recalculés contre 130 au devis ($+4{,}1$ \%), est conforme, et c'est la répartition entre le bois franc et la céramique, c'est-à-dire le tracé exact de la frontière entre la cuisine et la salle à manger et le fini des placards, que le plan ne fixe pas et que le devis descriptif devrait préciser. Les deux postes à justifier, le gypse et la peinture, sont un véritable écart : la règle de mesure donne 733 m² et le devis 620, ce qui représente, aux prix du devis, \dollars{3104} de gypse et \dollars{1144} de peinture, soit \dollars{4248} ou 1,4 \% du coût direct. Trois explications sont possibles et doivent être soumises à l'estimateur : une convention de mesure différente (ouvertures déduites plus largement, cloisons comptées sur une face, plafond du garage exclu), un sous-sol partiellement fini au devis alors que le plan le suppose fini, ou une omission. Tant que la réponse n'est pas connue, l'évaluateur consigne la réserve et chiffre l'enjeu. | ||||
| 368 | + | ||||
| 369 | +\emph{Étape 4 : les forfaits.} Les quatorze postes forfaitaires, \dollars{97223} au total, ne se vérifient pas par la géométrie. Le \cref{tab:22:forfaits} les rapporte à la superficie habitable et au coût direct : les armoires et comptoirs représentent \qty{105}{\dollar\per\metre\squared} et 5,8 \% de $D$, l'électricité \qty{85}{\dollar\per\metre\squared} et 4,7 \%, la thermopompe 3,5 \%, les plans et honoraires 3,4 \%, le financement intérimaire 2,9 \%. Ces ratios sont plausibles pour une maison de qualité moyenne et n'appellent pas de réserve ; dans un mandat réel, ils seraient comparés à ceux de devis semblables de la région et aux fourchettes des guides de coûts, que l'ouvrage ne reproduit pas. | ||||
| 370 | + | ||||
| 371 | +\emph{Étape 5 : l'effet sur le coût.} Si l'on remplaçait les quantités des postes mesurés par celles du métré de contrôle, en conservant les prix unitaires du devis, le coût direct passerait de \dollars{298826.17} à \dollars{302236.39}, soit $+\dollars{3410.22}$ ou $+1{,}14$ \% : les petits écarts négatifs de l'excavation, des fondations et de la charpente ($-\dollars{1318}$) compensent en partie l'écart du gypse et de la peinture ($+\dollars{4248}$), et les planchers se neutralisent presque ($+\dollars{431}$). Les coûts indirects du devis étant exprimés en dollars, seul l'incitatif suit, et le coût neuf passerait de \dollars{397567.33} à \dollars{401318.58}, soit $+\dollars{3751.24}$ ou $+0{,}94$ \% ; si l'on maintenait au contraire le taux d'indirects de 20,95 \%, l'effet serait de $3410{,}22 \times 1{,}3304 = \dollars{4537}$. Dans les deux cas, l'écart est inférieur à l'arrondi de \dollars{398000} retenu au \cref{ch:21} pour les conclusions et très inférieur à l'effet d'une année d'indice de prix (16,5 \% d'étendue, \cref{fig:21:sensibilite}). Le devis est donc conservé tel quel pour la suite de la partie V, avec une réserve consignée sur le gypse et la peinture ; c'est la conclusion normale d'un métré de contrôle, dont l'objet n'est pas de refaire le devis mais d'en borner l'erreur. | ||||
| 372 | +\end{exemple} | ||||
| 373 | + | ||||
| 374 | +\begin{footnotesize} | ||||
| 375 | +\begin{longtable}{@{}L{62mm} l S[table-format=3.0] S[table-format=5.2] S[table-format=6.2]@{}} | ||||
| 376 | +\caption{Bordereau de quantités chiffré du sujet du cas 1 : 38 postes par bloc (ordre du \cref{ch:21}), unité, quantité, prix unitaire installé et montant, en dollars du T3 2026. Les sous-totaux par bloc sont ceux du \cref{tab:21:devis}.}\label{tab:22:bordereau}\\ | ||||
| 377 | +\toprule | ||||
| 378 | +Poste & Unité & {Quantité} & {Prix unitaire (\$)} & {Montant (\$)} \\ | ||||
| 379 | +\midrule | ||||
| 380 | +\endfirsthead | ||||
| 381 | +\multicolumn{5}{@{}l}{\emph{\cref{tab:22:bordereau} (suite)}}\\ | ||||
| 382 | +\toprule | ||||
| 383 | +Poste & Unité & {Quantité} & {Prix unitaire (\$)} & {Montant (\$)} \\ | ||||
| 384 | +\midrule | ||||
| 385 | +\endhead | ||||
| 386 | +\midrule | ||||
| 387 | +\multicolumn{5}{r@{}}{\emph{suite à la page suivante}}\\ | ||||
| 388 | +\endfoot | ||||
| 389 | +\bottomrule | ||||
| 390 | +\endlastfoot | ||||
| 391 | +\multicolumn{5}{@{}l}{\emph{Fondations et site (5 postes, 39 818,04 \$)}}\\ | ||||
| 392 | +Excavation et remblai & m\textsuperscript{3} & 420 & 20.24 & 8500.80 \\ | ||||
| 393 | +Fondations béton (semelles, murs) & m\textsuperscript{3} & 38 & 375.88 & 14283.44 \\ | ||||
| 394 | +Dalle de sous-sol & m\textsuperscript{2} & 95 & 68.67 & 6523.65 \\ | ||||
| 395 | +Drain français et imperméabilisation & m lin. & 42 & 86.74 & 3643.08 \\ | ||||
| 396 | +Raccordements aqueduc/égout & forfait & 1 & 6867.07 & 6867.07 \\ | ||||
| 397 | +\addlinespace | ||||
| 398 | +\multicolumn{5}{@{}l}{\emph{Structure et charpente (3 postes, 53 852,16 \$)}}\\ | ||||
| 399 | +Charpente murs et planchers & m\textsuperscript{2} & 330 & 119.27 & 39359.10 \\ | ||||
| 400 | +Fermes de toit & m\textsuperscript{2} & 110 & 68.67 & 7553.70 \\ | ||||
| 401 | +Escaliers & unité & 2 & 3469.68 & 6939.36 \\ | ||||
| 402 | +\addlinespace | ||||
| 403 | +\multicolumn{5}{@{}l}{\emph{Enveloppe (7 postes, 70 350,56 \$)}}\\ | ||||
| 404 | +Couverture bardeaux d'asphalte & m\textsuperscript{2} & 125 & 61.44 & 7680.00 \\ | ||||
| 405 | +Revêtement extérieur (brique 40 \%, fibrociment 60 \%) & m\textsuperscript{2} & 240 & 119.27 & 28624.80 \\ | ||||
| 406 | +Isolation et pare-vapeur & m\textsuperscript{2} & 420 & 23.13 & 9714.60 \\ | ||||
| 407 | +Fenêtres (PVC double vitrage) & unité & 16 & 1048.13 & 16770.08 \\ | ||||
| 408 | +Portes extérieures & unité & 3 & 1373.41 & 4120.23 \\ | ||||
| 409 | +Porte de garage & unité & 1 & 1879.41 & 1879.41 \\ | ||||
| 410 | +Gouttières et solins & m lin. & 48 & 32.53 & 1561.44 \\ | ||||
| 411 | +\addlinespace | ||||
| 412 | +\multicolumn{5}{@{}l}{\emph{Finition intérieure (8 postes, 67 092,26 \$)}}\\ | ||||
| 413 | +Gypse et tirage de joints & m\textsuperscript{2} & 620 & 27.47 & 17031.40 \\ | ||||
| 414 | +Peinture intérieure & m\textsuperscript{2} & 620 & 10.12 & 6274.40 \\ | ||||
| 415 | +Planchers bois franc & m\textsuperscript{2} & 95 & 86.74 & 8240.30 \\ | ||||
| 416 | +Planchers céramique & m\textsuperscript{2} & 35 & 97.58 & 3415.30 \\ | ||||
| 417 | +Planchers flottants (sous-sol) & m\textsuperscript{2} & 70 & 39.76 & 2783.20 \\ | ||||
| 418 | +Portes intérieures et moulures & unité & 14 & 469.85 & 6577.90 \\ | ||||
| 419 | +Armoires de cuisine et comptoirs & forfait & 1 & 17348.39 & 17348.39 \\ | ||||
| 420 | +Vanités et accessoires (2 salles de bain) & forfait & 1 & 5421.37 & 5421.37 \\ | ||||
| 421 | +\addlinespace | ||||
| 422 | +\multicolumn{5}{@{}l}{\emph{Mécanique et électricité (6 postes, 51 105,45 \$)}}\\ | ||||
| 423 | +Plomberie brute et finition & appareil & 14 & 1192.70 & 16697.80 \\ | ||||
| 424 | +Chauffe-eau & unité & 1 & 1156.56 & 1156.56 \\ | ||||
| 425 | +Électricité (entrée 200 A, filage, appareils) & forfait & 1 & 14095.57 & 14095.57 \\ | ||||
| 426 | +Ventilation (VRC) et conduits & forfait & 1 & 5638.23 & 5638.23 \\ | ||||
| 427 | +Thermopompe centrale et plinthes & forfait & 1 & 10481.32 & 10481.32 \\ | ||||
| 428 | +Éclairage et finition électrique & forfait & 1 & 3035.97 & 3035.97 \\ | ||||
| 429 | +\addlinespace | ||||
| 430 | +\multicolumn{5}{@{}l}{\emph{Aménagements extérieurs (4 postes, 16 607,70 \$)}}\\ | ||||
| 431 | +Balcon et perron & m\textsuperscript{2} & 14 & 469.85 & 6577.90 \\ | ||||
| 432 | +Entrée asphaltée & m\textsuperscript{2} & 55 & 46.99 & 2584.45 \\ | ||||
| 433 | +Aménagement paysager de base & forfait & 1 & 4698.52 & 4698.52 \\ | ||||
| 434 | +Nettoyage et conteneurs & forfait & 1 & 2746.83 & 2746.83 \\ | ||||
| 435 | +\addlinespace | ||||
| 436 | +\multicolumn{5}{@{}l}{\emph{Coûts indirects (5 postes, 62 598,68 \$)}}\\ | ||||
| 437 | +Permis et études (arpentage, sol) & forfait & 1 & 4481.67 & 4481.67 \\ | ||||
| 438 | +Supervision de chantier (salaires) & semaine & 26 & 1373.41 & 35708.66 \\ | ||||
| 439 | +Assurances chantier et cautionnement & forfait & 1 & 3758.82 & 3758.82 \\ | ||||
| 440 | +Plans et honoraires professionnels & forfait & 1 & 10119.90 & 10119.90 \\ | ||||
| 441 | +Financement intérimaire & forfait & 1 & 8529.63 & 8529.63 \\ | ||||
| 442 | +\midrule | ||||
| 443 | +Coûts directs $D$ (33 postes) & & & & 298826.17 \\ | ||||
| 444 | +Coûts indirects $I$ (5 postes) & & & & 62598.68 \\ | ||||
| 445 | +Sous-total $D + I$ & & & & 361424.85 \\ | ||||
| 446 | +\end{longtable} | ||||
| 447 | +\end{footnotesize} | ||||
| 448 | +\vspace{-6pt} | ||||
| 449 | +\tabsource{\synth{\texttt{data/synthetic/cas1\_gatineau\_couts.csv}, graine 20261031 ; regroupement \texttt{CORPS} de \texttt{analysis/python/cases/ch21\_cout\_neuf.py}}.} | ||||
| 450 | + | ||||
| 451 | +\begin{figure}[tbp] | ||||
| 452 | +\centering | ||||
| 453 | +\includegraphics[width=\linewidth]{ch22/ch22-fig-repartition-corps.pdf} | ||||
| 454 | +\caption{Répartition du devis du sujet du cas 1 par bloc de corps de métier (mêmes sept blocs et même ordre qu'à la \cref{fig:21:decomposition}) et par type d'unité : postes mesurés en volume, surface ou longueur, postes dénombrés, forfaits. La géométrie contrôle directement 48,2 \% du sous-total ; les forfaits, concentrés dans la mécanique et l'électricité et dans les indirects, en représentent 26,9 \%.}\label{fig:22:repartition} | ||||
| 455 | +\figsource{\synth{script \texttt{analysis/python/figures/ch22\_repartition.py}, graine 20261031}.} | ||||
| 456 | +\end{figure} | ||||
| 457 | + | ||||
| 458 | +\begin{table}[tbp] | ||||
| 459 | +\caption{Métré de contrôle du sujet du cas 1 : quantité du devis, quantité recalculée à partir du plan coté, écart relatif et verdict (tolérances de 5 et 10 \%). Les règles de mesure sont celles de la \cref{sec:22:regles}.}\label{tab:22:verification} | ||||
| 460 | +\centering\footnotesize | ||||
| 461 | +\begin{tabular}{@{}L{54mm} l S[table-format=3.0] S[table-format=3.2] S[table-format=+2.1] l@{}} | ||||
| 462 | +\toprule | ||||
| 463 | +Poste & Unité & {Devis} & {Recalcul} & {Écart (\%)} & Verdict \\ | ||||
| 464 | +\midrule | ||||
| 465 | +Excavation et remblai & m\textsuperscript{3} & 420 & 408.94 & -2.6 & conforme \\ | ||||
| 466 | +Fondations béton (semelles, murs) & m\textsuperscript{3} & 38 & 36.79 & -3.2 & conforme \\ | ||||
| 467 | +Dalle de sous-sol & m\textsuperscript{2} & 95 & 95.04 & +0.0 & conforme \\ | ||||
| 468 | +Drain français et imperméabilisation & m lin. & 42 & 42.24 & +0.6 & conforme \\ | ||||
| 469 | +Charpente murs et planchers & m\textsuperscript{2} & 330 & 324.65 & -1.6 & conforme \\ | ||||
| 470 | +Fermes de toit & m\textsuperscript{2} & 110 & 111.62 & +1.5 & conforme \\ | ||||
| 471 | +Escaliers & unité & 2 & 2.00 & +0.0 & conforme \\ | ||||
| 472 | +Couverture bardeaux d'asphalte & m\textsuperscript{2} & 125 & 124.79 & -0.2 & conforme \\ | ||||
| 473 | +Revêtement extérieur & m\textsuperscript{2} & 240 & 238.79 & -0.5 & conforme \\ | ||||
| 474 | +Isolation et pare-vapeur & m\textsuperscript{2} & 420 & 419.82 & -0.0 & conforme \\ | ||||
| 475 | +Fenêtres (PVC double vitrage) & unité & 16 & 16.00 & +0.0 & conforme \\ | ||||
| 476 | +Portes extérieures & unité & 3 & 3.00 & +0.0 & conforme \\ | ||||
| 477 | +Porte de garage & unité & 1 & 1.00 & +0.0 & conforme \\ | ||||
| 478 | +Gouttières et solins & m lin. & 48 & 48.80 & +1.7 & conforme \\ | ||||
| 479 | +Gypse et tirage de joints & m\textsuperscript{2} & 620 & 733.00 & +18.2 & à justifier \\ | ||||
| 480 | +Peinture intérieure & m\textsuperscript{2} & 620 & 733.00 & +18.2 & à justifier \\ | ||||
| 481 | +Planchers bois franc & m\textsuperscript{2} & 95 & 103.56 & +9.0 & à préciser \\ | ||||
| 482 | +Planchers céramique & m\textsuperscript{2} & 35 & 31.81 & -9.1 & à préciser \\ | ||||
| 483 | +Planchers flottants (sous-sol) & m\textsuperscript{2} & 70 & 70.09 & +0.1 & conforme \\ | ||||
| 484 | +Portes intérieures et moulures & unité & 14 & 14.00 & +0.0 & conforme \\ | ||||
| 485 | +Plomberie brute et finition & appareil & 14 & 14.00 & +0.0 & conforme \\ | ||||
| 486 | +Balcon et perron & m\textsuperscript{2} & 14 & 14.10 & +0.7 & conforme \\ | ||||
| 487 | +Entrée asphaltée & m\textsuperscript{2} & 55 & 55.00 & +0.0 & conforme \\ | ||||
| 488 | +Supervision de chantier (salaires) & semaine & 26 & 26.00 & +0.0 & conforme \\ | ||||
| 489 | +\midrule | ||||
| 490 | +\multicolumn{6}{@{}l}{Planchers finis hors sol (bois franc + céramique) : 130 au devis, 135,37 recalculés ($+4{,}1$ \%), conforme} \\ | ||||
| 491 | +\multicolumn{6}{@{}l}{Bilan : 20 postes conformes, 2 à préciser, 2 à justifier ; 14 forfaits contrôlés par ratios (\cref{tab:22:forfaits})} \\ | ||||
| 492 | +\bottomrule | ||||
| 493 | +\end{tabular} | ||||
| 494 | +\tabsource{\synth{\texttt{analysis/python/cases/ch22\_metre.py}, fonctions \texttt{quantites\_geometriques} et \texttt{verification}, graine 20261031}.} | ||||
| 495 | +\end{table} | ||||
| 496 | + | ||||
| 497 | +\begin{figure}[tbp] | ||||
| 498 | +\centering | ||||
| 499 | +\includegraphics[width=\linewidth]{ch22/ch22-fig-ecarts-metre.pdf} | ||||
| 500 | +\caption{Écarts du métré de contrôle du sujet du cas 1, par poste mesuré ou dénombré, dans l'ordre des blocs de corps de métier ; bandes de tolérance de ±5 \% (conforme) et ±10 \% (à préciser). Les dimensions de base et les dénombrements concordent ; le gypse et la peinture ressortent 18 \% au-dessus du devis et constituent la seule réserve matérielle ; le bois franc et la céramique se compensent.}\label{fig:22:ecarts} | ||||
| 501 | +\figsource{\synth{script \texttt{analysis/python/figures/ch22\_ecarts.py}, graine 20261031}.} | ||||
| 502 | +\end{figure} | ||||
| 503 | + | ||||
| 504 | +\begin{table}[tbp] | ||||
| 505 | +\caption{Contrôle par ratios des quatorze postes forfaitaires du sujet du cas 1 : montant, montant par mètre carré de superficie habitable (\msq{165.13}) et part du coût direct $D$.}\label{tab:22:forfaits} | ||||
| 506 | +\centering\footnotesize | ||||
| 507 | +\begin{tabular}{@{}L{62mm} S[table-format=5.2] S[table-format=3.0] S[table-format=1.1]@{}} | ||||
| 508 | +\toprule | ||||
| 509 | +Poste (forfait) & {Montant (\$)} & {\$/m\textsuperscript{2} hab.} & {Part de $D$ (\%)} \\ | ||||
| 510 | +\midrule | ||||
| 511 | +Armoires de cuisine et comptoirs & 17348.39 & 105 & 5.8 \\ | ||||
| 512 | +Électricité (entrée 200 A, filage, appareils) & 14095.57 & 85 & 4.7 \\ | ||||
| 513 | +Thermopompe centrale et plinthes & 10481.32 & 63 & 3.5 \\ | ||||
| 514 | +Plans et honoraires professionnels$^{\dagger}$ & 10119.90 & 61 & 3.4 \\ | ||||
| 515 | +Financement intérimaire$^{\dagger}$ & 8529.63 & 52 & 2.9 \\ | ||||
| 516 | +Raccordements aqueduc/égout & 6867.07 & 42 & 2.3 \\ | ||||
| 517 | +Ventilation (VRC) et conduits & 5638.23 & 34 & 1.9 \\ | ||||
| 518 | +Vanités et accessoires (2 salles de bain) & 5421.37 & 33 & 1.8 \\ | ||||
| 519 | +Aménagement paysager de base & 4698.52 & 28 & 1.6 \\ | ||||
| 520 | +Permis et études (arpentage, sol)$^{\dagger}$ & 4481.67 & 27 & 1.5 \\ | ||||
| 521 | +Assurances chantier et cautionnement$^{\dagger}$ & 3758.82 & 23 & 1.3 \\ | ||||
| 522 | +Éclairage et finition électrique & 3035.97 & 18 & 1.0 \\ | ||||
| 523 | +Nettoyage et conteneurs & 2746.83 & 17 & 0.9 \\ | ||||
| 524 | +Chauffe-eau (unité) & 1156.56 & 7 & 0.4 \\ | ||||
| 525 | +\midrule | ||||
| 526 | +Ensemble des forfaits & 97223.29 & 589 & 32.5 \\ | ||||
| 527 | +\bottomrule | ||||
| 528 | +\end{tabular} | ||||
| 529 | +\tabsource{\synth{\texttt{analysis/python/cases/ch22\_metre.py}} ; $^{\dagger}$ postes indirects, rapportés à $D$ pour la comparaison. La part cumulée dépasse la part des forfaits dans $D + I$ (26,9 \%) parce que le dénominateur est ici le seul coût direct.} | ||||
| 530 | +\end{table} | ||||
| 531 | + | ||||
| 532 | +\section{Analyse de sensibilité}\label{sec:22:sensibilite} | ||||
| 533 | + | ||||
| 534 | +Le métré de contrôle a borné l'erreur du devis du sujet à environ 1 \% du coût neuf ; l'analyse de sensibilité généralise ce résultat en demandant ce que coûterait une erreur de quantité uniforme sur un bloc entier de corps de métier, puis sur tous les postes directs. Comme les coûts indirects du devis sont des montants et non un taux, une erreur $e$ sur les quantités d'un bloc de montant $M_b$ se transmet au coût neuf par $\Delta C_N = e\,M_b\,(1 + \tau_E)$, c'est-à-dire multipliée par 1,10 ; si le taux d'indirects était maintenu, le multiplicateur serait $(1+\tau_I)(1+\tau_E) = 1{,}3304$. Le \cref{tab:22:sensibilite} donne l'effet pour des erreurs de $\pm 5$ et $\pm 10$ \%. Une erreur de 10 \% sur l'ensemble de l'enveloppe, le bloc le plus lourd avec 23,5 \% du coût direct, déplace le coût neuf de \dollars{7739} (1,95 \%) ; la même erreur sur la finition intérieure, de \dollars{7380} (1,86 \%) ; sur les aménagements extérieurs, de \dollars{1827} (0,46 \%) seulement. Une erreur uniforme de 10 \% sur tous les postes directs, qui correspond au cas des erreurs parfaitement corrélées de la \cref{prop:diversification}, déplace le coût neuf de \dollars{32871}, soit 8,27 \% : c'est le scénario d'une dimension de base mal lue ou d'une convention de superficie confondue, et c'est le seul scénario de quantités dont l'ampleur rivalise avec celle de la date des prix. Pour des erreurs indépendantes de 5 \% par poste, l'écart type du coût neuf n'est que de \dollars{4613}, soit 1,2 \%. | ||||
| 535 | + | ||||
| 536 | +\begin{table}[tbp] | ||||
| 537 | +\caption{Sensibilité du coût neuf du sujet du cas 1 à une erreur relative uniforme sur les quantités d'un bloc de corps de métier (indirects du devis fixés en dollars, incitatif de 10 \% sur $D + I$) ; cas de base $C_N = \dollars{397567}$.}\label{tab:22:sensibilite} | ||||
| 538 | +\centering\small | ||||
| 539 | +\begin{tabular}{@{}l S[table-format=3.1] S[table-format=+6.0] S[table-format=+6.0] S[table-format=+6.0] S[table-format=+6.0] S[table-format=1.2]@{}} | ||||
| 540 | +\toprule | ||||
| 541 | +Bloc & {Part de $D$ (\%)} & {$-10$ \%} & {$-5$ \%} & {$+5$ \%} & {$+10$ \%} & {$\pm 10$ \% en \% de $C_N$} \\ | ||||
| 542 | +\midrule | ||||
| 543 | +Fondations et site & 13.3 & -4380 & -2190 & +2190 & +4380 & 1.10 \\ | ||||
| 544 | +Structure et charpente & 18.0 & -5924 & -2962 & +2962 & +5924 & 1.49 \\ | ||||
| 545 | +Enveloppe & 23.5 & -7739 & -3869 & +3869 & +7739 & 1.95 \\ | ||||
| 546 | +Finition intérieure & 22.5 & -7380 & -3690 & +3690 & +7380 & 1.86 \\ | ||||
| 547 | +Mécanique et électricité & 17.1 & -5622 & -2811 & +2811 & +5622 & 1.41 \\ | ||||
| 548 | +Aménagements extérieurs & 5.6 & -1827 & -913 & +913 & +1827 & 0.46 \\ | ||||
| 549 | +\midrule | ||||
| 550 | +Tous les postes directs & 100.0 & -32871 & -16435 & +16435 & +32871 & 8.27 \\ | ||||
| 551 | +\bottomrule | ||||
| 552 | +\end{tabular} | ||||
| 553 | +\tabsource{\synth{\texttt{analysis/python/cases/ch22\_metre.py}, fonction \texttt{sensibilite\_quantites}} ; variations de $C_N$ en dollars.} | ||||
| 554 | +\end{table} | ||||
| 555 | + | ||||
| 556 | +Trois conclusions se dégagent, qui complètent celles du \cref{ch:21}. D'abord, la hiérarchie des risques de quantité suit la hiérarchie des poids : l'enveloppe et la finition intérieure, qui réunissent 46 \% du coût direct, méritent l'essentiel de l'attention, et c'est précisément là que le métré de contrôle du sujet a trouvé son seul écart matériel. Ensuite, la forme de l'erreur compte plus que sa taille : dix erreurs indépendantes de 5 \% pèsent moins qu'une seule erreur de 5 \% sur une dimension de base. Enfin, même dans le scénario défavorable d'une erreur corrélée de 10 \%, l'enjeu des quantités (8,3 \%) reste inférieur à celui d'une année d'indice de prix (16,5 \% d'étendue) ; dans la méthode du coût, la fraîcheur des prix unitaires domine la précision du métré, ce qui ne dispense pas de mesurer mais dit où placer l'effort. | ||||
| 557 | + | ||||
| 558 | +\begin{quebec}[Mesurage, construction et main-d'œuvre : le cadre québécois du métré] | ||||
| 559 | +\emph{Normes de mesurage du rôle.} Le Manuel d'évaluation foncière du Québec, dont le Règlement sur le rôle d'évaluation foncière rend les consignes obligatoires pour l'évaluateur municipal \parencite[art.~1 et 2]{reglrole}, définit au bloc 07 des dossiers de propriété des bâtiments résidentiels les dimensions de base que l'on a utilisées : aire au sol, périmètre au sol, aire des étages et périmètre des étages, mesures brutes prises à la face externe des murs, étage compté lorsque son plancher n'est pas plus bas que 0,4 m sous le niveau moyen du sol, murs mitoyens exclus du périmètre, garage intégré et verrière intégrée compris dans l'étage \parencite{mefqpartie2}. L'édition 2026 s'applique aux rôles entrant en vigueur le 1\ier{} janvier 2027 \parencite{mefq2026}. Les barèmes de coûts unitaires de la partie 3E du Manuel sont établis sur ces mesures ; ils sont librement consultables mais protégés par le droit d'auteur du gouvernement du Québec et ne sont pas reproduits ici. | ||||
| 560 | + | ||||
| 561 | +\emph{Code de construction.} Les quantités d'un coût de remplacement sont celles d'un bâtiment conforme aux normes actuelles. Le chapitre I du Code de construction, fondé sur le Code national du bâtiment 2020 modifié pour le Québec, est en vigueur depuis le 17 avril 2025, avec une période transitoire qui permet d'appliquer les dispositions antérieures aux travaux commencés avant le 17 octobre 2027 ; le chapitre I.1 porte sur l'efficacité énergétique du bâtiment \parencite{codeConstruction}. Les épaisseurs d'isolant, la ventilation mécanique et la séparation coupe-feu entre un garage et l'habitation sont autant de quantités que le Code impose et qu'un plan de 1998 ne montrait pas sous la même forme. | ||||
| 562 | + | ||||
| 563 | +\emph{Licence et main-d'œuvre.} Nul ne peut agir comme entrepreneur de construction sans une licence de la Régie du bâtiment du Québec \parencite[art.~46]{loibatiment}, le particulier qui construit sa propre maison unifamiliale en étant dispensé sauf pour le gaz, le pétrole et l'électricité \parencite[art.~49]{loibatiment} ; les catégories de licence sont décrites par la RBQ \parencite{rbqLicences}. Les salaires de l'industrie sont fixés par les conventions collectives sectorielles 2025-2029 administrées par la Commission de la construction du Québec dans quatre secteurs (génie civil et voirie, industriel, institutionnel et commercial, résidentiel), avec un outil public de consultation des taux par date et par secteur ; la convention prévoit des hausses annuelles, relayées comme étant de 8, 5, 5 et 4 \% sur quatre ans, et la majoration en vigueur au 26 avril 2026 est de l'ordre de 5 \% selon le secteur \parencite{ccqSalaires}. Les taux horaires eux-mêmes ne sont pas reproduits dans l'ouvrage ; ils doivent être lus dans la convention applicable à la date des travaux. | ||||
| 564 | +\end{quebec} | ||||
| 565 | + | ||||
| 566 | +\begin{erreurs} | ||||
| 567 | +\begin{itemize} | ||||
| 568 | +\item \emph{Mesurer dans une convention et chiffrer dans une autre.} Appliquer un prix de dalle calibré à l'aire au sol brute à une surface coulée nette, ou un prix de gypse net à une surface brute, fausse le poste de 10 à 20 \% ; la quantité et le prix doivent partager la même convention (\cref{eq:22:conversion}). | ||||
| 569 | +\item \emph{Confondre superficie habitable, aire des étages et aire nette.} Pour le sujet, le même coût neuf vaut 2 092, 2 408 ou \parmsq{2937} selon la convention ; un coût unitaire sans convention déclarée est inutilisable. | ||||
| 570 | +\item \emph{Compter les angles deux fois.} Mesurer les murs de fondation à la face externe au lieu de l'axe surestime leur volume ; pour le sujet, 39,84 m au lieu de 38,84 m, soit $+2{,}6$ \% sur le poste. | ||||
| 571 | +\item \emph{Oublier le facteur de pente.} Mesurer la couverture à la projection horizontale sous-estime la surface de 11,8 \% pour un toit à 6:12 et de 20,2 \% pour un toit à 8:12 (\cref{eq:22:toit}). | ||||
| 572 | +\item \emph{Compter les cloisons sur une face.} Le gypse couvre les deux faces de chaque cloison ; les compter une fois sous-estime le poste d'un tiers environ. | ||||
| 573 | +\item \emph{Ajouter les pertes à un prix installé.} Le prix unitaire installé inclut déjà les pertes et les chutes ; les ajouter de nouveau compte deux fois 5 à 15 \% des matériaux. | ||||
| 574 | +\item \emph{Vérifier les postes et non les dimensions de base.} Une erreur sur une cote de façade se propage à tous les postes dans le même sens et n'est pas diversifiée (\cref{prop:diversification}) ; le contrôle commence par l'aire au sol et le périmètre. | ||||
| 575 | +\item \emph{Rejeter un devis pour un écart non matériel.} Un écart de 18 \% sur le gypse ne vaut que 1,4 \% du coût direct ; la réserve se consigne et se chiffre, elle ne justifie pas de refaire le devis. | ||||
| 576 | +\end{itemize} | ||||
| 577 | +\end{erreurs} | ||||
| 578 | + | ||||
| 579 | +\begin{limites} | ||||
| 580 | +\begin{itemize} | ||||
| 581 | +\item Le plan coté du sujet est une construction pédagogique du chapitre, dessinée pour être cohérente avec les quantités d'un devis lui-même synthétique ; les écarts du métré de contrôle, y compris celui du gypse, sont ceux de cette construction et ne décrivent pas la fiabilité des devis réels. | ||||
| 582 | +\item Les taux de pertes et de chutes du \cref{tab:22:pertes} sont des ordres de grandeur illustratifs déclarés comme tels, sans source publique vérifiée ; les tolérances de 5 et 10 \% du métré de contrôle sont une convention de l'ouvrage, non une norme. | ||||
| 583 | +\item Aucun taux horaire de la construction n'est chiffré : les conventions collectives de la CCQ fixent les taux par métier, secteur et date, et seules la structure des secteurs, l'existence de l'outil de consultation et la majoration d'avril 2026 ont été lues sur la page de la CCQ le 31 octobre 2026 ; les hausses de 8, 5, 5 et 4 \% sont relayées par une source d'industrie et restent partiellement vérifiées. | ||||
| 584 | +\item La page d'accueil du Canadian Institute of Quantity Surveyors confirme le nom de l'organisme et ses titres (PQS, CEC), mais l'ouvrage n'a pas consulté ses méthodes de mesurage publiées ; les règles de la \cref{sec:22:regles} sont celles d'un métré de composantes et non d'une méthode normalisée de métré détaillé. | ||||
| 585 | +\item Les règles de mesure du devis (dalle et plancher flottant à l'aire brute, revêtement sans déduction des ouvertures, cloisons comprises dans le gypse) sont déduites de la cohérence des quantités et non d'un devis descriptif ; dans un mandat réel elles doivent être lues ou demandées à l'estimateur. | ||||
| 586 | +\item Les barèmes 3E du Manuel d'évaluation foncière et les tables des guides de coûts sous licence (Altus, Marshall \& Swift, RSMeans) ne sont ni reproduits ni dépouillés ; le chapitre y renvoie pour les pertes, les productivités et les prix unitaires. | ||||
| 587 | +\end{itemize} | ||||
| 588 | +\end{limites} | ||||
| 589 | + | ||||
| 590 | +\begin{synthese} | ||||
| 591 | +\begin{itemize} | ||||
| 592 | +\item Le métré relève les quantités d'ouvrage à partir des plans ; le bordereau les consigne par corps de métier avec leur unité ; le prix unitaire installé transforme chaque quantité en coût. L'évaluateur pratique un métré de contrôle au niveau des composantes, non un métré de soumission. | ||||
| 593 | +\item Trois classes de postes : mesurés (géométrie), dénombrés (comptage), forfaitaires (ratios). Pour le sujet, ils pèsent 48,2, 24,9 et 26,9 \% du sous-total. | ||||
| 594 | +\item Les dimensions de base (aire au sol, périmètre, hauteurs, ouvertures) engendrent toutes les conventions de superficie : pour le sujet, 190,08 (MEFQ), 165,13 (habitable) et \msq{135.37} (nette), d'où des coûts unitaires de 2 092 à \parmsq{2937}. | ||||
| 595 | +\item Règles clés : excavation par prismoïde (\cref{eq:22:prismoide}), béton à l'axe, murs nets d'ouvertures (\cref{eq:22:murs}), couverture par facteur de pente (\cref{eq:22:toit}), gypse sur deux faces des cloisons, quantité et prix dans la même convention (\cref{eq:22:conversion}). | ||||
| 596 | +\item Les pertes transforment la quantité mesurée en quantité à commander ($q(1+w)$) ; un prix installé les inclut déjà. Le prix unitaire se décompose en matériaux, main-d'œuvre (heures × taux chargé des conventions CCQ), équipement et marge du métier. | ||||
| 597 | +\item Les erreurs de métré indépendantes se diversifient ($\sigma_D/D = \sigma\sqrt{H}$, 18,6 postes effectifs pour le sujet) ; les erreurs sur une dimension de base ne se diversifient pas. Pour le sujet, le métré de contrôle borne l'écart à $+1{,}14$ \% de $D$ et $+0{,}94$ \% de $C_N$ ; le devis du \cref{ch:21} est conservé avec une réserve sur le gypse. | ||||
| 598 | +\end{itemize} | ||||
| 599 | +\end{synthese} | ||||
| 600 | + | ||||
| 601 | +\section*{Exercices} | ||||
| 602 | + | ||||
| 603 | +\begin{exercice}[1]{Conventions de superficie}{ex:22:1} | ||||
| 604 | +Un cottage à deux étages mesure 10,40 m sur 9,15 m à la face externe des murs, avec un garage intégré de 3,66 m sur 6,10 m dans un coin du rez-de-chaussée et un sous-sol sous la partie habitable. Calculez l'aire au sol, le périmètre au sol, l'aire des étages et le périmètre des étages au sens du Manuel d'évaluation foncière, la superficie habitable (brute hors garage) et une approximation de l'aire nette intérieure hors sol en supposant des murs extérieurs de 0,30 m, une séparation garage–maison de 0,15 m et aucune autre cloison. Exprimez l'aire des étages et la superficie habitable en pieds carrés. | ||||
| 605 | +\end{exercice} | ||||
| 606 | + | ||||
| 607 | +\begin{exercice}[1]{Murs nets d'ouvertures}{ex:22:2} | ||||
| 608 | +Pour le cottage de l'\cref{ex:22:1}, les murs d'ossature ont 2,44 m de hauteur par étage ; les élévations montrent douze fenêtres de $1{,}20 \times 1{,}40$ m, deux portes extérieures de $0{,}91 \times 2{,}03$ m et une porte de garage de $2{,}74 \times 2{,}13$ m. Calculez l'aire brute des murs extérieurs, l'aire des ouvertures, l'aire nette et la part des ouvertures dans l'aire brute. Expliquez pourquoi un prix unitaire de revêtement « ouvertures non déduites » est plus bas qu'un prix net pour le même ouvrage. | ||||
| 609 | +\end{exercice} | ||||
| 610 | + | ||||
| 611 | +\begin{exercice}[2]{Toiture et facteur de pente}{ex:22:3} | ||||
| 612 | +Le cottage de l'\cref{ex:22:1} a un toit à deux versants de pente 8:12 avec des débords de 0,40 m. Calculez la projection horizontale du toit, le facteur de pente, la surface de couverture et la quantité de bardeaux à commander avec un taux de pertes de 10 \%. De combien la surface de couverture dépasse-t-elle celle d'un toit à 6:12 de même projection ? Quelle unité convient aux fermes, et laquelle à la couverture ? | ||||
| 613 | +\end{exercice} | ||||
| 614 | + | ||||
| 615 | +\begin{exercice}[2]{Volume d'excavation}{ex:22:4} | ||||
| 616 | +Pour un sous-sol d'aire \msq{95.16} et de périmètre 39,10 m, l'excavation a 2,50 m de profondeur et un dégagement de 0,90 m au pied des murs. Calculez le volume excavé (a) en supposant des parois verticales, (b) avec des talus à 0,5 horizontal pour 1 vertical, (c) avec des talus à 1 pour 1, en utilisant l'\cref{eq:22:decalage} et la formule du prismoïde (\cref{eq:22:prismoide}). Commentez l'écart relatif entre les trois hypothèses et ce qu'il implique pour le contrôle du poste d'excavation d'un devis dont on ne connaît pas les hypothèses. | ||||
| 617 | +\end{exercice} | ||||
| 618 | + | ||||
| 619 | +\begin{exercice}[2]{Structure d'un prix unitaire installé}{ex:22:5} | ||||
| 620 | +Pour un poste de gypse posé et tiré, on suppose, à titre purement illustratif, un coût de matériaux de \parmsq{11.50} avant pertes, un taux de pertes de 12 \%, une productivité de 0,35 heure par mètre carré, un taux horaire chargé de \qty{62}{\dollar} (valeur hypothétique, qui n'est pas un taux de convention collective) et \parmsq{0.80} d'équipement et de consommables. Calculez le prix unitaire avant marge et la part de la main-d'œuvre, puis le prix avec une marge de 15 \% du corps de métier. Quel est l'effet d'une hausse de 5 \% du taux horaire ? D'un gain de productivité de 10 \% ? Reliez le résultat à la composition de l'indice des prix de la construction du \cref{ch:21}. | ||||
| 621 | +\end{exercice} | ||||
| 622 | + | ||||
| 623 | +\begin{exercice}[3]{Propagation des erreurs de métré}{ex:22:6} | ||||
| 624 | +À partir du bordereau du \cref{tab:22:bordereau}, calculez l'indice de Herfindahl des 33 postes directs et l'écart type relatif du coût direct pour des erreurs de quantité indépendantes de 5 \% puis de 10 \% par poste (\cref{eq:22:variance}). Comparez au cas de 33 postes de poids égaux et au cas d'un devis réduit à deux postes de poids égaux. Exprimez le résultat en dollars de coût neuf avec le multiplicateur $(1+\tau_I)(1+\tau_E)$ du \cref{ch:21}, puis expliquez pourquoi une erreur de 5 \% sur le périmètre au sol n'est pas protégée par la diversification de la \cref{prop:diversification}. | ||||
| 625 | +\end{exercice} | ||||
| 626 | + | ||||
| 627 | +\begin{exercice}[3]{Métré de contrôle d'un plain-pied}{ex:22:7} | ||||
| 628 | +Un plain-pied de 14,00 m sur 9,00 m (face externe), sans garage, a des murs extérieurs de 0,30 m, des murs d'ossature de 2,44 m, onze fenêtres de $1{,}20 \times 1{,}40$ m, deux portes extérieures de $0{,}91 \times 2{,}03$ m, neuf portes intérieures de $0{,}91 \times 2{,}03$ m, 38,0 m de cloisons intérieures et un toit à 6:12 avec débords de 0,40 m ; le sous-sol n'est pas fini. Le devis du constructeur indique \msq{300} de gypse, \msq{300} de peinture et \msq{150} de couverture, aux prix unitaires du devis du sujet (\parmsq{27.47}, \parmsq{10.12} et \parmsq{61.44}). Recalculez ces trois quantités avec les règles de la \cref{sec:22:regles} (plafond net, murs extérieurs nets, cloisons sur deux faces, portes intérieures déduites sur deux faces), qualifiez les écarts avec les tolérances du chapitre, chiffrez l'effet sur le coût direct puis sur le coût neuf avec un multiplicateur de 1,3304, et rédigez en quelques lignes la réserve que l'évaluateur consignerait dans son rapport. | ||||
| 629 | +\end{exercice} | ||||
| 630 | + | ||||
| 631 | +\section*{Pour aller plus loin} | ||||
| 632 | + | ||||
| 633 | +La hiérarchie des méthodes de coût, de la comparaison unitaire au métré détaillé, est exposée dans \textcite{appraisal2026}, dont les chapitres sur l'estimation du coût fixent le vocabulaire du \emph{quantity survey} et de l'\emph{unit-in-place} repris ici ; \textcite{rattermann2020} en offre une version pédagogique avec des exemples chiffrés, et \textcite{appraisalCdn} l'adapte au contexte canadien. Le glossaire de \textcite{aiDictionary2022} fixe les définitions, et \textcite{achour1992} donne la terminologie française du métré et du bordereau dans l'évaluation québécoise. La pratique du métré lui-même relève de la littérature de l'économie de la construction plutôt que de celle de l'évaluation : les données RSMeans \parencite{rsmeans2025} et le manuel de \textcite{marshallswift2025} documentent les conventions de mesure, les pertes et les productivités par poste, et le guide d'Altus \parencite{altus2026} situe les coûts canadiens par ville ; ces sources sous licence doivent être consultées dans leur édition courante. Pour la tradition britannique, où le \emph{quantity surveyor} est une profession réglementée distincte de l'évaluateur, \textcite{wyatt2022} et \textcite{scarrettOsborn2014} exposent la méthode de l'entrepreneur et ses limites. Deux lectures de la littérature empirique éclairent enfin le lien entre quantités et valeur : \textcite{sirmansMacphersonZietz2005} recensent les caractéristiques physiques que les modèles hédoniques retiennent, superficie, nombre de pièces, garage, sous-sol fini, qui sont précisément celles que le métré mesure, et \textcite{krauseLipscomb2016} rappellent les contrôles de cohérence d'unités et de plausibilité que toute donnée de superficie doit subir avant d'entrer dans un modèle, contrôles dont le métré de contrôle du présent chapitre est l'analogue pour les coûts. | ||||
added
references/lib-ch22.bib
+13 −0
@@ -0,0 +1,13 @@ | |||||
| 1 | +% Nouvelles références du chapitre 22 — à fusionner dans library.bib par l'orchestrateur. | ||||
| 2 | +% Non citées dans ch22.tex (pour éviter une citation non définie avant fusion) ; le texte nomme l'organisme en toutes lettres. | ||||
| 3 | +% La clé existante ccqSalaires (library.bib) a été revérifiée le 2026-10-31 : page « Salaire et taux » lue (quatre secteurs, | ||||
| 4 | +% outil des taux de salaire par date et par secteur, majoration annuelle au 26 avril 2026) ; proposer urldate = {2026-10-31}. | ||||
| 5 | + | ||||
| 6 | +@online{ciqs, | ||||
| 7 | + author = {{Canadian Institute of Quantity Surveyors}}, | ||||
| 8 | + title = {CIQS: The Voice for Canada's Construction Economists}, | ||||
| 9 | + year = {2026}, | ||||
| 10 | + url = {https://ciqs.org/}, | ||||
| 11 | + urldate = {2026-10-31}, | ||||
| 12 | + note = {Page d'accueil consultée le 31 octobre 2026 : l'organisme décerne les titres \emph{Professional Quantity Surveyor} (PQS) et \emph{Construction Estimator Certified} (CEC) ; aucune méthode de mesurage publiée n'a été consultée} | ||||
| 13 | +} | ||||
modified
references/library.bib
+9 −0
@@ -5029,3 +5029,12 @@ | |||||
| 5029 | url = {https://www.canada.ca/fr/agence-revenu/services/formulaires-publications/publications/rc4028/remboursement-tps-tvh-habitations-neuves.html}, | 5029 | url = {https://www.canada.ca/fr/agence-revenu/services/formulaires-publications/publications/rc4028/remboursement-tps-tvh-habitations-neuves.html}, | ||
| 5030 | urldate = {2026-10-31} | 5030 | urldate = {2026-10-31} | ||
| 5031 | } | 5031 | } | ||
| 5032 | + | ||||
| 5033 | +@online{ciqs, | ||||
| 5034 | + author = {{Canadian Institute of Quantity Surveyors}}, | ||||
| 5035 | + title = {CIQS: The Voice for Canada's Construction Economists}, | ||||
| 5036 | + year = {2026}, | ||||
| 5037 | + url = {https://ciqs.org/}, | ||||
| 5038 | + urldate = {2026-10-31}, | ||||
| 5039 | + note = {Page d'accueil consultée le 31 octobre 2026 : l'organisme décerne les titres \emph{Professional Quantity Surveyor} (PQS) et \emph{Construction Estimator Certified} (CEC) ; aucune méthode de mesurage publiée n'a été consultée} | ||||
| 5040 | +} | ||||
modified
solutions/ch13.tex
+43 −0
@@ -1 +1,44 @@ | |||||
| 1 | % Solutions du chapitre 13 — Transactions, inscriptions, loyers et coûts | 1 | % Solutions du chapitre 13 — Transactions, inscriptions, loyers et coûts | ||
| 2 | +% Chiffres recalculés par analysis/python/tests/test_ch13.py (classe TestExercices) à partir de analysis/python/cases/ch13_sources.py. | ||||
| 3 | + | ||||
| 4 | +\begin{solution}{ex:13:1}{Classer les sources et budgéter une collecte} | ||||
| 5 | +\emph{Classement.} (a) Prix médians de l'APCIQ : donnée d'industrie (ventes par courtier, système Centris) ; régime des conditions d'utilisation de l'association : attribution obligatoire (« Source : APCIQ par le système Centris »), usage commercial interdit sans consentement ; un rapport peut citer des valeurs ponctuelles avec la source et la période, non reproduire les tableaux. (b) Tableau 18-10-0289-01 : donnée officielle sous la Licence ouverte de Statistique Canada ; reproduction, transformation et redistribution libres avec la mention « Source : Statistique Canada, tableau 18-10-0289-01 » ; un rapport peut reproduire les séries. (c) Loyer moyen d'une zone de la SCHL : donnée officielle, mais diffusée sous les conditions d'utilisation de la SCHL (non ouvertes) ; citation avec attribution à des fins non commerciales et éducatives, pas de redistribution des fichiers ; citer la lettre de qualité avec la valeur. (d) Rôle en format ouvert : donnée officielle sous licence CC BY 4.0 ; réutilisation libre avec attribution au MAMH, interdiction de réidentifier les renseignements caviardés. (e) Barèmes 3E du Manuel : document public protégé par le droit d'auteur du gouvernement du Québec, sans licence ouverte ; on cite et on renvoie, on ne reproduit pas. (f) \emph{Canadian Cost Guide} : donnée d'industrie sous licence d'abonnement ; valeurs ponctuelles citées avec édition et page, aucun tableau reproduit. | ||||
| 6 | + | ||||
| 7 | +\emph{Budget.} Consultation : $(25 + 25) \times 1~\$ = 50~\$$. États certifiés : $3 \times (16 + 16) = 96~\$$. Total : \dollars{146}. Le poste dominant n'est pas le tarif mais le temps de lecture et d'extraction des cinquante documents. | ||||
| 8 | +\end{solution} | ||||
| 9 | + | ||||
| 10 | +\begin{solution}{ex:13:2}{Du prix d'acte au prix du comparable} | ||||
| 11 | +Prix de l'immeuble : $\tilde P - M = 612\,000 - 12\,000 = \dollars{600000}$ (\cref{eq:13:acte}, avec $F = \eta = 0$ faute d'indication contraire). Délai : du 2 juillet au 15 septembre 2026, 75 jours, soit $75 / 30{,}4375 = 2{,}464$ mois. Facteur de datation : $(1{,}06)^{2{,}464/12} = 1{,}0120$. Dater la vente à l'acte revient à appliquer un ajustement temporel vers la date d'évaluation plus faible du facteur $1{,}0120$ : sur \dollars{600000}, l'écart est de $600\,000 \times 0{,}0120 = \dollars{7222}$, soit 1,20~\% du prix. Le biais est négatif (sous-estimation du prix ajusté) parce que le marché est haussier : le prix a été convenu 2,5 mois avant l'acte, à un niveau de marché plus bas, et c'est de ce niveau qu'il faut partir pour l'indexer. Il ne se compense pas entre comparables parce que, dans un même marché, tous les comparables datés à l'acte subissent un décalage de même signe (\cref{prop:datation}) ; seul le délai varie d'une vente à l'autre, ce qui disperse le biais sans le centrer sur zéro. | ||||
| 12 | +\end{solution} | ||||
| 13 | + | ||||
| 14 | +\begin{solution}{ex:13:3}{Signatures des ventes non représentatives} | ||||
| 15 | +(a) Prix nominal (\dollars{1}, sous le seuil de \dollars{5000} du Règlement sur la proportion médiane), même nom de famille et exonération du droit de mutation fondée sur le lien (art.~20 LDMI) : vente liée, à exclure ; rien à vérifier ailleurs, le journal des exclusions note le motif. (b) Vendeur institutionnel, absence de garantie de qualité (art.~1731 C.c.Q.) et préavis d'exercice à l'index : reprise de finance, à exclure des comparables ; à compter dans l'étude de marché comme indicateur de tension. (c) Vendeur « Succession », mais inscription de 52 jours chez un courtier et acheteur sans lien : exposition normale au marché, à conserver ; vérifier sur la fiche de courtage le prix demandé et l'absence de condition particulière. (d) Premier transfert d'un lot nouvellement créé par une société de construction, taxes incluses, promesse seize mois avant l'acte : vente de promoteur ; comparable seulement à d'autres ventes neuves, après isolement des taxes et des incitatifs et datation à la promesse ; inutilisable pour un sujet existant. (e) Vente d'une moitié indivise au copropriétaire : droits transmis différents, prix d'une fraction, vente nécessairement non exposée au marché ; à exclure. (f) Balance de prix de vente de \dollars{200000} à 2~\% sur cinq ans : financement avantageux (terme $F$ de l'\cref{eq:13:acte}) ; ajuster par la valeur actuelle de l'avantage de taux (\cref{ch:17}) ou exclure si l'ajustement dépasse quelques points. (g) Parcelle de \dollars{4800} : sous le seuil de \dollars{5000} ; à exclure des ventes d'immeubles bâtis, à conserver éventuellement dans une base de terrains si la nature du bien est documentée. (h) Vente ordinaire dont le ratio prix/rôle uniformisé est de 0,55 : rien ne la disqualifie a priori, mais le ratio est très éloigné de la médiane du secteur ; vérifier l'acte (meubles, part indivise, contrepartie non monétaire), la fiche (état, sinistre, vente « sans garantie légale ») et le rôle (erreur de caractéristiques, travaux non inscrits) avant de la conserver. | ||||
| 16 | +\end{solution} | ||||
| 17 | + | ||||
| 18 | +\begin{solution}{ex:13:4}{Lire l'Enquête sur les logements locatifs} | ||||
| 19 | +(a) Variation brute du loyer moyen des deux chambres (\cref{eq:13:brute}) : Montréal $1\,346/1\,176 - 1 = 14{,}5~\%$ (estimative 7,2~\%) ; Québec $1\,277/1\,159 - 1 = 10{,}2~\%$ (6,1) ; Gatineau $1\,460/1\,353 - 1 = 7{,}9~\%$ (4,7) ; Sherbrooke $1\,062/1\,002 - 1 = 6{,}0~\%$ (9,8) ; Trois-Rivières $1\,016/885 - 1 = 14{,}8~\%$ (6,6) ; Saguenay $985/882 - 1 = 11{,}7~\%$ (10,9). L'écart est positif partout sauf à Sherbrooke : l'effet de composition n'a pas de signe fixe. | ||||
| 20 | + | ||||
| 21 | +(b) Vacants implicites (\cref{eq:13:vacants}) : Montréal $667\,266 \times 0{,}029 = 19\,351$ ; Québec $118\,693 \times 0{,}024 = 2\,849$ ; Gatineau $33\,553 \times 0{,}038 = 1\,275$ ; Sherbrooke $41\,949 \times 0{,}027 = 1\,133$ ; Trois-Rivières $22\,505 \times 0{,}027 = 608$ ; Saguenay $16\,241 \times 0{,}013 = 211$. | ||||
| 22 | + | ||||
| 23 | +(c) Loyer de \dollars{1300} indexé : par la variation brute, $1\,300 \times 1\,346/1\,176 = \dollars{1487.93}$ ; par la variation estimative, $1\,300 \times 1{,}072 = \dollars{1393.60}$. Écart : \dollars{94.33} par mois, soit \dollars{1132} par année. | ||||
| 24 | + | ||||
| 25 | +(d) La variation estimative mesure l'évolution du loyer des mêmes immeubles d'une année à l'autre : c'est elle qu'il faut appliquer pour indexer le loyer d'un logement donné ou un loyer de marché. La variation brute mesure l'évolution du loyer moyen du parc, composition comprise (livraisons de logements neufs plus chers, démolitions) : elle convient à l'analyse des revenus agrégés d'un marché, non à l'indexation d'un loyer. La lettre « c » (bon) attachée au taux d'inoccupation de Gatineau signale une précision statistique moindre que le « a » de Montréal ou de Québec ; la valeur de 3,8~\% doit être citée avec cette lettre et interprétée avec une marge plus large, ce qui compte d'autant plus qu'elle est proche du seuil de 3~\% du moratoire sur les évictions. | ||||
| 26 | +\end{solution} | ||||
| 27 | + | ||||
| 28 | +\begin{solution}{ex:13:5}{Lire un tableau de Statistique Canada par script} | ||||
| 29 | +(a) Montréal, bâtiments résidentiels, agrégat des divisions : première période 2017T1, 39 observations. RMR de Québec : première période 2023T1, 15 observations. Composite des quinze RMR : 2017T1, 39 observations. | ||||
| 30 | + | ||||
| 31 | +(b) Facteurs du T1 2023 au T3 2026 (quatorze trimestres, soit 3,5 ans) : Montréal $117{,}8/99{,}9 = 1{,}1792$, taux annuel composé $1{,}1792^{1/3{,}5} - 1 = 4{,}82~\%$ ; Québec $124{,}8/98{,}8 = 1{,}2632$, soit 6,90~\% par année ; composite $111{,}4/97{,}8 = 1{,}1391$, soit 3,79~\% par année. | ||||
| 32 | + | ||||
| 33 | +(c) Du T3 2019 au T3 2026 : Montréal $117{,}8/71{,}6 = 1{,}6453$ ; composite $111{,}4/64{,}0 = 1{,}7406$. Le calcul est impossible pour Québec parce que la série résidentielle de cette RMR n'existe dans le tableau qu'à partir du premier trimestre de 2023 : une absence de série se traduit par une absence de lignes dans le fichier, non par des valeurs manquantes, ce que seule la lecture du fichier brut révèle. | ||||
| 34 | + | ||||
| 35 | +(d) Coût de \dollars{350000} au T1 2023 à Québec exprimé au T3 2026 : avec la série de Québec, $350\,000 \times 1{,}2632 = \dollars{442105}$ ; avec la série de Montréal, $350\,000 \times 1{,}1792 = \dollars{412713}$, soit une sous-estimation de \dollars{29392} ($-6{,}6~\%$) ; avec le composite, $350\,000 \times 1{,}1391 = \dollars{398671}$, soit une sous-estimation de \dollars{43434} ($-9{,}8~\%$). La série nationale, qui ne progresse que de 2,7~\% sur un an au T3 2026 contre 9,2~\% à Québec, est la plus trompeuse. | ||||
| 36 | +\end{solution} | ||||
| 37 | + | ||||
| 38 | +\begin{solution}{ex:13:6}{Concevoir une base et mesurer sa couverture} | ||||
| 39 | +(a) Taux de couverture $\kappa = 1\,044/1\,500 = 0{,}696$ ; taux d'appariement $\alpha = 920/1\,044 = 0{,}881$. Prix moyen du marché (\cref{eq:13:composition}) : $\mu = 0{,}696 \times 510\,000 + 0{,}304 \times 455\,000 = \dollars{493280}$. Une statistique fondée sur le seul courtage, \dollars{510000}, surestime le marché de \dollars{16720}, soit 3,39~\%. Le biais est une fonction de la couverture et de l'écart entre les deux sous-marchés ; il ne diminue pas quand le nombre de ventes par courtier augmente, à couverture constante. Les 124 ventes de courtage non appariées (11,9~\%) doivent être examinées (adresse mal normalisée, acte non encore publié, vente annulée) et non supprimées. | ||||
| 40 | + | ||||
| 41 | +(b) Schéma : une table \emph{propriétés} (clé id\_propriete ; attributs du rôle ouvert : RL0101 adresse, RL0104 matricule, RL0105A utilisation, RL0107A unité de voisinage, RL0302A terrain, RL0307A/B année de construction, RL0308A aire d'étages, RL0311A logements ; coordonnées géocodées) ; une table \emph{transactions} (clé id\_vente, clé étrangère id\_propriete ; prix d'acte, meubles, prix retenu, dates de promesse et d'acte, codes du vendeur et de l'acheteur, garantie, financement, source, indicateurs d'épuration et motif d'exclusion) ; une table \emph{valeurs au rôle} (id\_propriete, millésime ; RL0401A à RL0405A, facteur comparatif) ; une table \emph{baux} si l'on traite des plex ; une table \emph{séries de contexte} (géographie, période ; indices et taux). Clés d'appariement : rôle $\leftrightarrow$ courtage par l'adresse normalisée (et la date pour lever les ambiguïtés d'immeubles à plusieurs logements) ; registre $\leftrightarrow$ courtage par l'adresse et la date d'acte ; registre $\leftrightarrow$ rôle par l'adresse, le lot étant caviardé dans le rôle ouvert ; le matricule relie le rôle à l'avis d'évaluation du propriétaire, non aux autres sources. | ||||
| 42 | + | ||||
| 43 | +(c) Le fichier de sources comporte, pour chaque fichier brut, une ligne : nom, adresse exacte, date de téléchargement, taille, version ou période, licence et conditions (Licence ouverte de Statistique Canada ; CC BY 4.0 du MAMH avec interdiction de réidentification ; conditions de la SCHL, citation sans redistribution ; conditions de l'APCIQ, attribution et usage non commercial ; droit d'auteur de JLR, mention « Source : JLR.ca » ; registre foncier, usage dans le cadre du mandat), responsable et description. Le journal des exclusions comporte, pour chaque enregistrement écarté, l'identifiant de la vente, la source, la date de la décision, la règle appliquée (vente liée, reprise, prix nominal, part indivise, financement, hors période, hors secteur, ratio prix/rôle hors bornes) et, le cas échéant, la pièce qui l'a motivée. Le rapport peut reproduire les séries de Statistique Canada et les champs du rôle ouvert ; il cite les valeurs de la SCHL, de l'APCIQ et de JLR avec attribution, et il ne reproduit ni fiche de courtage ni acte, dont il conserve copie au dossier pendant au moins cinq ans. | ||||
| 44 | +\end{solution} | ||||
modified
solutions/ch22.tex
+59 −0
@@ -1 +1,60 @@ | |||||
| 1 | % Solutions du chapitre 22 — Métrés et quantités | 1 | % Solutions du chapitre 22 — Métrés et quantités | ||
| 2 | +% Chiffres recalculés par analysis/python/tests/test_ch22.py (classe TestExercices). | ||||
| 3 | + | ||||
| 4 | +\begin{solution}{ex:22:1}{Conventions de superficie} | ||||
| 5 | +Dimensions à la face externe : $L = 10{,}40$ m, $W = 9{,}15$ m ; garage $g_x \times g_y = 3{,}66 \times 6{,}10$ m. | ||||
| 6 | + | ||||
| 7 | +\emph{Manuel d'évaluation foncière (bloc 07).} Aire au sol $A_0 = 10{,}40 \times 9{,}15 = \msq{95.16}$ ; périmètre au sol $P = 2(10{,}40 + 9{,}15) = 39{,}10$ m. Deux étages hors sol : aire des étages $A_{\text{ét}} = 2 \times 95{,}16 = \msq{190.32}$ (le garage intégré fait partie de l'étage) et périmètre des étages $2 \times 39{,}10 = 78{,}20$ m. Le sous-sol, dont le plancher est à plus de 0,4 m sous le niveau moyen du sol, n'est pas un étage. | ||||
| 8 | + | ||||
| 9 | +\emph{Superficie habitable} (brute hors garage, \cref{eq:22:conventions}) : $G = 3{,}66 \times 6{,}10 = \msq{22.33}$ et $A_{\text{hab}} = 190{,}32 - 22{,}33 = \msq{167.99}$. | ||||
| 10 | + | ||||
| 11 | +\emph{Aire nette intérieure} (approximation sans cloisons) : chaque étage a une aire intérieure de $(10{,}40 - 0{,}60)(9{,}15 - 0{,}60) = 9{,}80 \times 8{,}55 = \msq{83.79}$ ; on retranche au rez-de-chaussée l'aire intérieure du garage, limitée par le mur extérieur (0,30 m) sur deux côtés et par la demi-séparation (0,075 m) sur les deux autres : $(3{,}66 - 0{,}375)(6{,}10 - 0{,}375) = 3{,}285 \times 5{,}725 = \msq{18.81}$. D'où $A_{\text{nette}} \approx 2 \times 83{,}79 - 18{,}81 = \msq{148.77}$, soit 88,6 \% de la superficie habitable et 78,2 \% de l'aire des étages ; les cloisons et la trémie, ignorées ici, abaisseraient encore ce chiffre de quelques pour cent (pour le sujet du chapitre, 82,0 \% et 71,2 \%). | ||||
| 12 | + | ||||
| 13 | +\emph{Pieds carrés} : $190{,}32 \times 10{,}7639 = \pisq{2049}$ et $167{,}99 \times 10{,}7639 = \pisq{1808}$. | ||||
| 14 | +\end{solution} | ||||
| 15 | + | ||||
| 16 | +\begin{solution}{ex:22:2}{Murs nets d'ouvertures} | ||||
| 17 | +Aire brute des murs extérieurs (\cref{eq:22:murs}) : $P \times h_{\text{mur}} \times 2 = 39{,}10 \times 2{,}44 \times 2 = \msq{190.81}$. Ouvertures : douze fenêtres de $1{,}20 \times 1{,}40 = \msq{1.68}$, soit \msq{20.16} ; deux portes de $0{,}91 \times 2{,}03 = \msq{1.847}$, soit \msq{3.69} ; une porte de garage de $2{,}74 \times 2{,}13 = \msq{5.84}$ ; total \msq{29.70}, soit 15,6 \% de l'aire brute. Aire nette : $190{,}81 - 29{,}70 = \msq{161.11}$. | ||||
| 18 | + | ||||
| 19 | +Un prix unitaire « ouvertures non déduites » s'applique à la quantité brute ; pour produire le même montant que le prix net appliqué à la quantité nette, il doit vérifier $p^{\text{brut}} = p^{\text{net}}\,q^{\text{net}}/q^{\text{brut}}$ (\cref{eq:22:conversion}), soit ici $p^{\text{brut}} = 0{,}844\,p^{\text{net}}$ : il est 15,6 \% plus bas. La convention brute est courante pour les revêtements parce que la main-d'œuvre des retours, cadrages et solins autour des ouvertures compense approximativement la surface non couverte ; la convention n'est ni meilleure ni pire que l'autre, mais la quantité et le prix doivent la partager. | ||||
| 20 | +\end{solution} | ||||
| 21 | + | ||||
| 22 | +\begin{solution}{ex:22:3}{Toiture et facteur de pente} | ||||
| 23 | +Projection horizontale, débords compris : $(10{,}40 + 0{,}80)(9{,}15 + 0{,}80) = 11{,}20 \times 9{,}95 = \msq{111.44}$ ; c'est la quantité des fermes, facturées à la projection. Facteur de pente pour 8:12, $p = 8/12 = 0{,}6667$ : $\sqrt{1 + 0{,}6667^2} = 1{,}2019$. Surface de couverture (\cref{eq:22:toit}) : $111{,}44 \times 1{,}2019 = \msq{133.93}$ ; quantité de bardeaux à commander avec 10 \% de pertes (\cref{eq:22:pertes}) : $133{,}93 \times 1{,}10 = \msq{147.33}$. Pour un toit à 6:12, le facteur serait $\sqrt{1{,}25} = 1{,}1180$ et la couverture $\msq{124.59}$ ; le toit à 8:12 couvre $1{,}2019/1{,}1180 - 1 = 7{,}5$ \% de plus pour la même projection. Les fermes se mesurent en mètres carrés de projection (c'est ainsi que le fabricant les conçoit et les facture, la pente étant un attribut de la ferme) ; la couverture se mesure en mètres carrés de versant, parce que les bardeaux, la membrane et la main-d'œuvre se comptent à la surface réellement couverte. | ||||
| 24 | +\end{solution} | ||||
| 25 | + | ||||
| 26 | +\begin{solution}{ex:22:4}{Volume d'excavation} | ||||
| 27 | +Aire du fond de fouille (\cref{eq:22:decalage}) avec $d = 0{,}90$ m : $A(0{,}90) = 95{,}16 + 39{,}10 \times 0{,}90 + 4 \times 0{,}81 = \msq{133.59}$. | ||||
| 28 | + | ||||
| 29 | +(a) Parois verticales : $V = 133{,}59 \times 2{,}50 = \qty{333.98}{\metre\cubed}$. | ||||
| 30 | + | ||||
| 31 | +(b) Talus à 0,5 pour 1 : à mi-hauteur le décalage est $0{,}90 + 0{,}5 \times 1{,}25 = 1{,}525$ m, $A = 95{,}16 + 39{,}10 \times 1{,}525 + 4 \times 1{,}525^2 = \msq{164.09}$ ; en surface, $0{,}90 + 0{,}5 \times 2{,}50 = 2{,}15$ m, $A = \msq{197.72}$. Prismoïde (\cref{eq:22:prismoide}) : $V = \tfrac{2{,}50}{6}(133{,}59 + 4 \times 164{,}09 + 197{,}72) = \qty{411.53}{\metre\cubed}$, soit $+23{,}2$ \% par rapport aux parois verticales. | ||||
| 32 | + | ||||
| 33 | +(c) Talus à 1 pour 1 : décalages de 2,15 m à mi-hauteur ($A = \msq{197.72}$) et de 3,40 m en surface ($A = 95{,}16 + 132{,}94 + 46{,}24 = \msq{274.34}$) ; $V = \tfrac{2{,}50}{6}(133{,}59 + 4 \times 197{,}72 + 274{,}34) = \qty{499.50}{\metre\cubed}$, soit $+49{,}6$ \%. | ||||
| 34 | + | ||||
| 35 | +Le volume excavé varie donc de 334 à \qty{500}{\metre\cubed} selon la seule hypothèse de talus, un écart de 50 \% que les tolérances de 5 ou 10 \% du métré de contrôle ne peuvent absorber. Le contrôle du poste d'excavation d'un devis dont on ignore les hypothèses n'a de sens que si l'on reconstitue d'abord la convention de l'estimateur (dégagement, talus, profondeur, tranchées comprises ou non) ; à défaut, on compare le prix total du poste à des ratios ($\$/\text{m}^2$ d'aire au sol) plutôt que la quantité. Pour le sujet du chapitre, les hypothèses $d = 0{,}90$ m, $m = 0{,}5$ et $h = 2{,}60$ m reproduisent le devis à 2,6 \% près. | ||||
| 36 | +\end{solution} | ||||
| 37 | + | ||||
| 38 | +\begin{solution}{ex:22:5}{Structure d'un prix unitaire installé} | ||||
| 39 | +Par l'\cref{eq:22:prix-unitaire} avec $m = 11{,}50$, $w = 0{,}12$, $h = 0{,}35$ h/m\textsuperscript{2}, $s = 62$ \$/h (valeur hypothétique) et $e = 0{,}80$ : matériaux pertes comprises $11{,}50 \times 1{,}12 = \parmsq{12.88}$ ; main-d'œuvre $0{,}35 \times 62 = \parmsq{21.70}$ ; équipement \parmsq{0.80} ; prix avant marge $p = \parmsq{35.38}$, dont la main-d'œuvre représente $21{,}70/35{,}38 = 61{,}3$ \%. Avec une marge de 15 \% : $35{,}38 \times 1{,}15 = \parmsq{40.69}$. | ||||
| 40 | + | ||||
| 41 | +Une hausse de 5 \% du taux horaire porte la main-d'œuvre à \parmsq{22.79} et le prix avant marge à \parmsq{36.47}, soit $+3{,}07$ \% : l'élasticité du prix au taux horaire est la part de la main-d'œuvre (0,613). Un gain de productivité de 10 \% ($h = 0{,}315$) ramène la main-d'œuvre à \parmsq{19.53} et le prix à \parmsq{33.21}, soit $-6{,}13$ \%. Pour un poste à forte intensité de main-d'œuvre comme le tirage de joints, le prix suit donc de près les conventions collectives et la productivité ; pour un poste dominé par le matériau (fenêtres, thermopompe), il suit les prix industriels. L'indice des prix de la construction de bâtiments du \cref{ch:21} agrège ces deux dynamiques selon la composition d'un bâtiment type ; un devis dont la composition s'en écarte, par exemple parce qu'il comporte beaucoup de finition, s'indexe imparfaitement par cet indice unique. | ||||
| 42 | +\end{solution} | ||||
| 43 | + | ||||
| 44 | +\begin{solution}{ex:22:6}{Propagation des erreurs de métré} | ||||
| 45 | +Les parts $\omega_k$ des 33 postes directs dans $D = \dollars{298826.17}$ donnent un indice de Herfindahl $H = \sum_k \omega_k^2 = 0{,}0539$, soit $1/H = 18{,}6$ postes effectifs ; le poste le plus lourd, la charpente, pèse 13,2 \%. Par l'\cref{eq:22:variance}, pour $\sigma = 5$ \% : $\sigma_D/D = 0{,}05\sqrt{0{,}0539} = 1{,}16$ \%, soit $\sigma_D = \dollars{3468}$ ; pour $\sigma = 10$ \%, le double : 2,32 \% et \dollars{6936}. Trente-trois postes de poids égaux donneraient $H = 1/33$ et $\sigma_D/D = 0{,}05/\sqrt{33} = 0{,}87$ \% ; deux postes de poids égaux, $H = 0{,}5$ et $0{,}05 \times 0{,}707 = 3{,}54$ \%. Le devis du sujet est donc presque aussi diversifié qu'un devis uniforme de 19 postes. En dollars de coût neuf, avec le multiplicateur $(1+\tau_I)(1+\tau_E) = 1{,}3304$ du \cref{ch:21} : $3468 \times 1{,}3304 = \dollars{4613}$ pour $\sigma = 5$ \% et \dollars{9227} pour $\sigma = 10$ \%, soit 1,2 et 2,3 \% de $C_N$. | ||||
| 46 | + | ||||
| 47 | +Une erreur de 5 \% sur le périmètre au sol n'est pas protégée parce qu'elle n'est pas indépendante d'un poste à l'autre : elle affecte dans le même sens les fondations, le drain, la charpente des murs, le revêtement, l'isolation, le gypse des murs extérieurs et les gouttières, c'est-à-dire tous les postes proportionnels au périmètre. Pour ces postes, l'\cref{eq:22:propagation} donne une erreur commune de 5 \% et la \cref{prop:diversification} place le résultat à sa borne supérieure ; la racine de $H$ ne s'applique qu'aux erreurs non corrélées. C'est pourquoi le métré de contrôle vérifie d'abord les dimensions de base, dont une erreur se propage sans atténuation, avant de vérifier les postes, dont les erreurs se compensent en partie. | ||||
| 48 | +\end{solution} | ||||
| 49 | + | ||||
| 50 | +\begin{solution}{ex:22:7}{Métré de contrôle d'un plain-pied} | ||||
| 51 | +Dimensions de base : aire au sol $14{,}00 \times 9{,}00 = \msq{126.00}$, périmètre $P = 46{,}00$ m. | ||||
| 52 | + | ||||
| 53 | +\emph{Gypse.} Plafond net : $(14{,}00 - 0{,}60)(9{,}00 - 0{,}60) = 13{,}40 \times 8{,}40 = \msq{112.56}$. Murs extérieurs, face intérieure, nets d'ouvertures (\cref{eq:22:murs}) : $46{,}00 \times 2{,}44 = 112{,}24$ moins onze fenêtres (\msq{18.48}) et deux portes (\msq{3.69}), soit \msq{90.06}. Cloisons sur deux faces : $38{,}0 \times 2{,}44 \times 2 = \msq{185.44}$. Portes intérieures déduites sur deux faces : $2 \times 9 \times 1{,}847 = \msq{33.25}$. Total : $112{,}56 + 90{,}06 + 185{,}44 - 33{,}25 = \msq{354.76}$, contre 300 au devis, soit $+18{,}2$ \% : poste à justifier (au-delà de 10 \%). La peinture, mesurée sur la même surface, porte le même écart. | ||||
| 54 | + | ||||
| 55 | +\emph{Couverture.} Projection $(14{,}00 + 0{,}80)(9{,}00 + 0{,}80) = \msq{145.04}$ ; facteur de pente 1,1180 ; couverture \msq{162.16}, contre 150 au devis, soit $+8{,}1$ \% : poste à préciser (entre 5 et 10 \%) ; l'écart s'explique si le devis a mesuré sans débords ($126 \times 1{,}118 = \msq{140.9}$) ou à la projection avec débords (145,0), deux conventions courantes qu'il faut faire préciser. | ||||
| 56 | + | ||||
| 57 | +\emph{Effet sur le coût.} Aux prix du devis : gypse $54{,}76 \times 27{,}47 = \dollars{1504.26}$ ; peinture $54{,}76 \times 10{,}12 = \dollars{554.17}$ ; couverture $12{,}16 \times 61{,}44 = \dollars{747.09}$ ; total $\Delta D = \dollars{2805.52}$. Avec le multiplicateur de 1,3304 (taux d'indirects et d'incitatif maintenus) : $\Delta C_N = \dollars{3732.46}$. | ||||
| 58 | + | ||||
| 59 | +\emph{Réserve.} « Le métré de contrôle effectué à partir du plan coté donne \msq{355} de gypse et de peinture contre \msq{300} au devis du constructeur ($+18$ \%) et \msq{162} de couverture contre 150 ($+8$ \%). Les écarts pourraient provenir d'une convention de mesure différente (déduction des ouvertures, cloisons comptées sur une face, projection sans débords) ou d'une omission ; ils n'ont pu être confirmés auprès de l'estimateur à la date du rapport. Leur effet, aux prix unitaires du devis, est de \dollars{2806} sur le coût direct et d'environ \dollars{3700} sur le coût neuf, soit moins de 1 \% ; le coût neuf retenu n'est pas modifié, mais l'indication par la méthode du coût est considérée comme comportant une incertitude d'au moins cet ordre, en sus de celle des prix et de la dépréciation. » | ||||
| 60 | +\end{solution} | ||||
modified
sources/registry.csv
+2 −0
@@ -347,4 +347,6 @@ SRC-18-003,article,"A Simple Test for Heteroscedasticity and Random Coefficient | |||||
| 347 | SRC-18-004,article,"Detection of Influential Observation in Linear Regression (Cook, R. D.)",Technometrics 19(1) 15-18,1977,https://doi.org/10.1080/00401706.1977.10489493,2026-10-31,verifie,18,Vérifié via api.crossref.org ; clé cook1977 | 347 | SRC-18-004,article,"Detection of Influential Observation in Linear Regression (Cook, R. D.)",Technometrics 19(1) 15-18,1977,https://doi.org/10.1080/00401706.1977.10489493,2026-10-31,verifie,18,Vérifié via api.crossref.org ; clé cook1977 | ||
| 348 | SRC-18-005,livre,"Regression Diagnostics: Identifying Influential Data and Sources of Collinearity (Belsley, Kuh, Welsch)",John Wiley & Sons,1980 (DOI de la réimpression Wiley 2005),https://doi.org/10.1002/0471725153,2026-10-31,partiellement_verifie,18,Notice Wiley non ouverte à la page ; clé belsleyKuhWelsch1980 | 348 | SRC-18-005,livre,"Regression Diagnostics: Identifying Influential Data and Sources of Collinearity (Belsley, Kuh, Welsch)",John Wiley & Sons,1980 (DOI de la réimpression Wiley 2005),https://doi.org/10.1002/0471725153,2026-10-31,partiellement_verifie,18,Notice Wiley non ouverte à la page ; clé belsleyKuhWelsch1980 | ||
| 349 | SRC-21-001,guide,RC4028 — Remboursement de la TPS/TVH pour habitations neuves,Agence du revenu du Canada,Rév. 10/2026,https://www.canada.ca/fr/agence-revenu/services/formulaires-publications/publications/rc4028/remboursement-tps-tvh-habitations-neuves.html,2026-10-31,partiellement_verifie,21,"Lu par agent web-fetch le 2026-10-31 : seuil 450 000 $ (maison construite par le propriétaire) verbatim ; remboursement premiers acheteurs (travaux dès le 20 mars 2025, 1 M$ / 1,5 M$) verbatim ; 36 % / 6 300 $ / 350 000 $ non vérifiés mot à mot. Pages Revenu Québec (TVQ) HTTP 403." | 349 | SRC-21-001,guide,RC4028 — Remboursement de la TPS/TVH pour habitations neuves,Agence du revenu du Canada,Rév. 10/2026,https://www.canada.ca/fr/agence-revenu/services/formulaires-publications/publications/rc4028/remboursement-tps-tvh-habitations-neuves.html,2026-10-31,partiellement_verifie,21,"Lu par agent web-fetch le 2026-10-31 : seuil 450 000 $ (maison construite par le propriétaire) verbatim ; remboursement premiers acheteurs (travaux dès le 20 mars 2025, 1 M$ / 1,5 M$) verbatim ; 36 % / 6 300 $ / 350 000 $ non vérifiés mot à mot. Pages Revenu Québec (TVQ) HTTP 403." | ||
| 350 | +SRC-22-001,page_web,Salaire et taux — conventions collectives 2025-2029 (outil des taux de salaire),Commission de la construction du Québec,Page consultée le 2026-10-31,https://www.ccq.org/fr-CA/avantages-sociaux/salaire-taux,2026-10-31,verifie,22,"Lu par agent web-fetch : « L'employeur a l'obligation de payer les salariés selon les conventions collectives en vigueur » ; quatre secteurs (A génie civil et voirie, B industriel, C institutionnel et commercial, D résidentiel) ; outil des taux par date et secteur ; majoration annuelle au 26 avril 2026 (résidentiel léger 5,5 %, autres secteurs 5 % — association des pourcentages peu lisible dans l'extrait) ; priorité des textes des conventions sur l'outil. Taux horaires par métier non relevés. Clé bib existante : ccqSalaires (urldate à mettre à jour)." | ||||
| 351 | +SRC-22-002,page_web,CIQS — Canadian Institute of Quantity Surveyors (page d'accueil),Canadian Institute of Quantity Surveyors,Page consultée le 2026-10-31,https://ciqs.org/,2026-10-31,verifie,22,"Nom de l'organisme et titres décernés (Professional Quantity Surveyor, PQS ; Construction Estimator Certified, CEC) lus sur la page ; le nom français et les méthodes de mesurage publiées n'y figurent pas. Entrée bib proposée : ciqs (lib-ch22.bib), non citée." | ||||
| 350 | # Aucune nouvelle source : le chapitre 47 ne cite que des clés déjà présentes dans references/library.bib (voir ch47.md).,,,,,,,,, | 352 | # Aucune nouvelle source : le chapitre 47 ne cite que des clés déjà présentes dans references/library.bib (voir ch47.md).,,,,,,,,, | ||
modified
verification/calculations.csv
+14 −0
@@ -289,3 +289,17 @@ CALC-19-11,19,Indications sujet : 637 953 / 664 342 / 624 799 / 633 352 / 654 42 | |||||
| 289 | CALC-19-12,19,Sensibilité à W : rho 0.2359 (k=4) → 0.6537 (k=16) ; lambda 0.5066 → 0.7855 ; I stable 0.32-0.33,analysis/python/cases/ch19_spatial.py,analysis/python/tests/test_ch19.py::test_sensibilite,voir description,idem,verifie,2026-10-31 | 289 | CALC-19-12,19,Sensibilité à W : rho 0.2359 (k=4) → 0.6537 (k=16) ; lambda 0.5066 → 0.7855 ; I stable 0.32-0.33,analysis/python/cases/ch19_spatial.py,analysis/python/tests/test_ch19.py::test_sensibilite,voir description,idem,verifie,2026-10-31 | ||
| 290 | CALC-19-13,19,Solutions des exercices 19.1 (I = 0.6917 ; alternés -1) 19.3 19.4 19.5 19.6 (krigeage 0.0489 var 0.00869) 19.7 (SEM k=4/8/16 : 656 724 / 633 352 / 628 672 $),solutions/ch19.tex,analysis/python/tests/test_ch19.py::test_solutions_exercices et ::test_solution_exercice_7,voir description,idem,verifie,2026-10-31 | 290 | CALC-19-13,19,Solutions des exercices 19.1 (I = 0.6917 ; alternés -1) 19.3 19.4 19.5 19.6 (krigeage 0.0489 var 0.00869) 19.7 (SEM k=4/8/16 : 656 724 / 633 352 / 628 672 $),solutions/ch19.tex,analysis/python/tests/test_ch19.py::test_solutions_exercices et ::test_solution_exercice_7,voir description,idem,verifie,2026-10-31 | ||
| 291 | CALC-19-14,19,Fonctions génériques ajoutées à traite.hedonique (sem_mv sar_mv tests_lm_spatial effets_sar gwr variogramme krigeage W spatio-temporelle),analysis/python/traite/hedonique.py,analysis/python/tests/test_ch19.py (8 tests de simulation),recouvrement des paramètres simulés ; identités (total = direct + indirect ; W_st nilpotente ; krigeage exact),idem,verifie,2026-10-31 | 291 | CALC-19-14,19,Fonctions génériques ajoutées à traite.hedonique (sem_mv sar_mv tests_lm_spatial effets_sar gwr variogramme krigeage W spatio-temporelle),analysis/python/traite/hedonique.py,analysis/python/tests/test_ch19.py (8 tests de simulation),recouvrement des paramètres simulés ; identités (total = direct + indirect ; W_st nilpotente ; krigeage exact),idem,verifie,2026-10-31 | ||
| 292 | +CALC-22-001,22,Cohérence avec le ch. 21 : D / I / C_N inchangés (38 postes) et bordereau q × p = montant,analysis/python/cases/ch22_metre.py,analysis/python/tests/test_ch22.py::TestCoherenceCh21,298826.17 ; 62598.68 ; 397567.33 ; 361424.85,idem,verifie,2026-10-31 | ||||
| 293 | +CALC-22-002,22,"Dimensions de base du plan coté : aire au sol, périmètre, garage, sous-sol ; invariance du périmètre en L",analysis/python/cases/ch22_metre.py,analysis/python/tests/test_ch22.py::TestGeometrie::test_empreinte_et_perimetre,95.04 m² ; 39.84 m ; 24.95 m² ; 70.09 m²,idem,verifie,2026-10-31 | ||||
| 294 | +CALC-22-003,22,"Superficies selon les conventions : aire des étages MEFQ, périmètre des étages, habitable, nette hors sol, sous-sol net et fini",analysis/python/cases/ch22_metre.py,analysis/python/tests/test_ch22.py::TestGeometrie::test_superficies_conventions,190.08 (2046 pi²) ; 79.68 m ; 165.13 (1777 pi²) ; 135.37 (58.56 + 76.81) ; 58.65 ; 49.31,idem,verifie,2026-10-31 | ||||
| 295 | +CALC-22-004,22,Couverture des niveaux par les pièces (somme des aires brutes = 95.04 / 95.04 / 70.09) et longueurs de cloisons,analysis/python/cases/ch22_metre.py,analysis/python/tests/test_ch22.py::TestGeometrie::test_pieces_couvrent_les_niveaux ; test_cloisons,21.52 / 47.94 / 20.80 m ; séparation 10.26 m,idem,verifie,2026-10-31 | ||||
| 296 | +CALC-22-005,22,"Formules élémentaires : aire décalée A + P·e + 4e², prismoïde (exact pour un tronc de pyramide), facteur de pente √(1+p²)",analysis/python/cases/ch22_metre.py,analysis/python/tests/test_ch22.py::TestGeometrie::test_formules_elementaires,identités à 1e-9 ; 1.1180,idem,verifie,2026-10-31 | ||||
| 297 | +CALC-22-006,22,"Quantités géométriques des 17 postes mesurés (excavation 408.94 m³, fondations 36.79 m³, dalle 95.04, drain 42.24 m, charpente 324.65, fermes 111.62, couverture 124.79, revêtement 238.79, isolation 419.82, gypse/peinture 733.00, bois franc 103.56, céramique 31.81, flottant 70.09, gouttières 48.80 m, balcon 14.10, entrée 55.00)",analysis/python/cases/ch22_metre.py,analysis/python/tests/test_ch22.py::TestQuantites::test_mesures_citees ; test_details_cites,voir description (tolérance 0.05),idem,verifie,2026-10-31 | ||||
| 298 | +CALC-22-007,22,"Dénombrements : 16 fenêtres (6/8/2), 3 portes ext., 1 porte de garage, 2 escaliers, 14 portes int. (4/7/3), 14 appareils, 26 semaines",analysis/python/cases/ch22_metre.py,analysis/python/tests/test_ch22.py::TestQuantites::test_denombrements,exact,idem,verifie,2026-10-31 | ||||
| 299 | +CALC-22-008,22,"Métré de contrôle : verdicts (20 conformes, 2 à préciser, 2 à justifier, 14 forfaits) ; écarts cités (gypse +18.2 %, bois franc +9.0 %, céramique −9.1 %, excavation −2.6 %, fondations −3.2 %, charpente −1.6 %) ; planchers hors sol 135.37 vs 130",analysis/python/cases/ch22_metre.py,analysis/python/tests/test_ch22.py::TestVerification::test_verdicts ; test_ecarts_cites,voir description,idem,verifie,2026-10-31 | ||||
| 300 | +CALC-22-009,22,Effet du métré de contrôle sur D et C_N (ΔD = +3410.22 $ = +1.14 % ; D' = 302236.39 ; C_N' = 401318.58 ; ΔC_N = +3751.24 $ = +0.94 % ; ΔC_N = ΔD × 1.10 ; multiplicateur 1.3304),analysis/python/cases/ch22_metre.py,analysis/python/tests/test_ch22.py::TestVerification::test_effet_metre_controle,voir description,idem,verifie,2026-10-31 | ||||
| 301 | +CALC-22-010,22,Sensibilité : erreur uniforme ±5/±10 % par bloc (enveloppe ±7739 $ = 1.95 % ; tous les directs ±32871 $ = 8.27 %) ; linéarité ΔC_N = e·M·1.10,analysis/python/cases/ch22_metre.py,analysis/python/tests/test_ch22.py::TestSensibilitePropagation::test_sensibilite,voir description,idem,verifie,2026-10-31 | ||||
| 302 | +CALC-22-011,22,"Propagation : Herfindahl 0.0539 (18.6 postes effectifs), σ_D/D = 1.16 % (σ = 5 %), σ_D = 3467.78 $, poste max charpente 13.2 % ; bornes 1/n ≤ H ≤ 1",analysis/python/cases/ch22_metre.py,analysis/python/tests/test_ch22.py::TestSensibilitePropagation::test_propagation,voir description,idem,verifie,2026-10-31 | ||||
| 303 | +CALC-22-012,22,"Pertes et chutes (taux illustratifs) : gypse 694.4, bardeaux 137.5 ; surplus valorisé au prix posé 11283.78 $ ; répartition par type d'unité (mesuré 174351.56 / dénombré 89850.00 / forfait 97223.29)",analysis/python/cases/ch22_metre.py,analysis/python/tests/test_ch22.py::TestSensibilitePropagation::test_pertes ; test_repartition_types,voir description,idem,verifie,2026-10-31 | ||||
| 304 | +CALC-22-013,22,"Coûts unitaires de C_N selon la convention (190.08 → 2092 ; 165.13 → 2408 ; 135.37 → 2937 $/m²) et ratios nette/habitable 82.0 %, nette/étages 71.2 %",analysis/python/cases/ch22_metre.py,analysis/python/tests/test_ch22.py::TestGeometrie::test_couts_unitaires_conventions,voir description,idem,verifie,2026-10-31 | ||||
| 305 | +CALC-22-014,22,Exercices 22.1 à 22.7 (solutions),analysis/python/tests/test_ch22.py,analysis/python/tests/test_ch22.py::TestExercices,voir solutions/ch22.tex,idem,verifie,2026-10-31 | ||||
added
verification/chapters/ch19.md
+41 −0
@@ -0,0 +1,41 @@ | |||||
| 1 | +# Chapitre 19 — Modèles spatiaux et temporels : bilan de rédaction (2026-10-31) | ||||
| 2 | + | ||||
| 3 | +## Compteurs | ||||
| 4 | +- Prose : ≈ 10 800 mots hors tableaux, figures, équations et commandes (≈ 15 000 avec la regex de `tools/check_manuscript.py`, qui compte aussi les cellules des tableaux et les arguments de commandes) ; 39 pages compilées (chapitre + solutions + bibliographie du chapitre). | ||||
| 5 | +- Figures : 8 (7 PDF Matplotlib + 1 schéma TikZ) — `ch19-fig-carte-residus`, `ch19-fig-correlogramme`, `ch19-fig-gwr-coefficients`, `ch19-fig-gwr-bande`, `ch19-fig-variogramme`, `ch19-fig-krigeage`, `ch19-fig-sensibilite-W` ; taxonomie dépendance/hétérogénéité (TikZ). Toutes sur coordonnées synthétiques en km (projection locale), sans fond de carte, étiquetées « coordonnées synthétiques ». | ||||
| 6 | +- Tableaux : 8 (Moran × 3 matrices, tests LM, coefficients MCO/SAR/SEM/SDM + référence, effets directs/indirects/totaux, quartiles GWR, effets fixes, validation croisée + indications sujet, sensibilité à W). | ||||
| 7 | +- Équations numérotées : 20 ; 2 définitions ; 2 propositions démontrées (jacobien d'une matrice spatio-temporelle unidirectionnelle ; effet total = β/(1 − ρ)). | ||||
| 8 | +- Exercices : 7 (niveaux 1, 1, 2, 2, 2, 3, 3) ; solutions détaillées dans `solutions/ch19.tex`, chiffres testés. | ||||
| 9 | +- Encadrés : objectifs, 2 définitions, pratique, synthetique, exemple intégral (six indications pour le sujet), 2 × quebec, erreurs, limites, synthese. | ||||
| 10 | +- Citations : 32 clés distinctes, toutes déjà dans `references/library.bib` ; `references/lib-ch19.bib` ne contient aucune nouvelle entrée (commentaire explicatif). | ||||
| 11 | + | ||||
| 12 | +## Contrôles | ||||
| 13 | +- `tools/compile_chapter.sh 19` → `OK ch19 : 39 pages, 0 references/citations non definies, 0 overfull hbox`. | ||||
| 14 | +- `python3 -m pytest -q analysis/python/tests/test_ch19.py` → 22 passed (8 tests de simulation des fonctions génériques, 13 tests des chiffres du chapitre, 1 test des solutions + 1 test de l'exercice 7). `test_hedonique.py` et `test_cas1.py` restent verts (aucune fonction existante modifiée). | ||||
| 15 | +- `python3 tools/check_manuscript.py --no-log` : aucun problème pour ch19 (les 4 problèmes signalés concernent ch13). | ||||
| 16 | +- Contrôle croisé PySAL (`ch19_spatial.py --controle`) : ρ, λ, β, erreurs-types et log-vraisemblances identiques à spreg `ML_Lag`/`ML_Error` (méthode `full`) à 1e-6 ; tests LM identiques à `spreg.OLS(spat_diag=True)` ; z de Moran identique à `esda.Moran` (z_norm) ; GWR : mêmes coefficients et même AICc que `mgwr` à bande égale (bande CV 4,99 km maison vs 4,87 km mgwr, score plat à 1e-4). | ||||
| 17 | +- PDF relu (planches de contact des 39 pages + pages 3, 21, 25, 27 à plus forte résolution) : aucun débordement après corrections (TikZ en `\resizebox`, tableaux en `\footnotesize`). | ||||
| 18 | +- Convention `\cref` sans article respectée (articles/prépositions écrits à la main). | ||||
| 19 | + | ||||
| 20 | +## Fichiers livrés | ||||
| 21 | +`manuscript/chapters/ch19.tex`, `solutions/ch19.tex`, `analysis/python/cases/ch19_spatial.py`, `analysis/python/figures/ch19_figures.py`, `analysis/python/tests/test_ch19.py`, `assets/figures/ch19/*.pdf` (7), `verification/chapters/ch19-{figures,calculations,claims,registry}.csv`, `references/lib-ch19.bib`, ce bilan. **Bibliothèque** : fonctions génériques ajoutées en fin de `analysis/python/traite/hedonique.py` sans modifier les fonctions existantes — `coordonnees_km`, `sar_mv` (SAR/SDM, MV concentrée, erreurs-types analytiques), `sem_mv`, `tests_lm_spatial`, `effets_sar`, `matrice_poids_spatio_temporelle`, `moran_par_distance`, `gwr`, `gwr_bande_cv`, `variogramme_empirique`, `variogramme_exponentiel`, `ajuster_variogramme`, `krigeage_ordinaire`, `krigeage_validation_croisee`, `sem_esperance_conditionnelle`. Rien d'écrit dans les CSV globaux ni dans `library.bib`. | ||||
| 22 | + | ||||
| 23 | +## Résultats clés (données synthétiques, cas 1) | ||||
| 24 | +- Résidus du modèle de référence (indicatrices de secteur + gradient) : I = −0,014 (z = −0,63), tests LM tous non significatifs, ρ et λ non significatifs → aucune dépendance spatiale résiduelle, conformément au générateur (bruit iid). | ||||
| 25 | +- Sans indicatrices de secteur : I = 0,32 (z = 17,1) ; LM robustes désignent le SEM (RLM-lag p = 0,30) ; SAR ρ = 0,44 (artefact de la prime omise ; effet total ln S = 0,99 vs 0,55 vrai) ; SEM λ = 0,65 ; SDM meilleur AIC (−1 163) mais loin du modèle de référence (−1 266). | ||||
| 26 | +- GWR : bande 4,99 km, tr(S) 44,8, AICc −1 233 ; retrouve Buckingham/Masson-Angers, lisse la frontière Hull–Aylmer. | ||||
| 27 | +- Variogramme : plateau initial = σ² du bruit (0,0069), composante de secteur visible seulement au-delà de 6 km ; krigeage au sujet −0,060. | ||||
| 28 | +- Indications sujet : référence 637 953 $ ; sans secteur 664 342 $ ; + krigeage 624 799 $ ; SEM 633 352 $ ; SAR 654 429 $ ; GWR 627 519 $. | ||||
| 29 | + | ||||
| 30 | +## Points non vérifiés ou partiellement vérifiés (voir ch19-claims.csv) | ||||
| 31 | +1. Tests LM robustes attribués à Anselin, Bera, Florax et Yoon (1996) : article absent de `library.bib` ; le texte renvoie à Elhorst (2014) ; référence non ajoutée (CLM-19-06, non_verifie). | ||||
| 32 | +2. Normes IAAO (évaluation de masse 2025, AVM 2018) : affirmation générale sur la modélisation de la localisation, sections non relues pour ce chapitre (CLM-19-05, partiellement_verifie). | ||||
| 33 | +3. Portées de plusieurs kilomètres (Basu–Thibodeau 1998) et anisotropie (Gillen et al. 2001) : citées d'après les résumés de notes-D, sans chiffre précis (CLM-19-10). | ||||
| 34 | +4. Le paramètre de portée du variogramme exponentiel bute sur la borne de 5 km imposée à l'ajustement (processus non stationnaire par paliers) : signalé dans le texte et dans `limites`. | ||||
| 35 | +5. La version « résidus MCO » de la statistique de Moran (Anselin–Kelejian) n'est pas implémentée dans `traite.hedonique` ; le texte donne la valeur de spreg (17,3 vs 17,1). | ||||
| 36 | + | ||||
| 37 | +## Suggestions pour l'harmonisation | ||||
| 38 | +- Le ch. 18 devrait annoncer le diagnostic spatial des résidus (renvoi au ch. 19) et reprendre la même notation W, ρ, λ ; le ch. 38 (SIG) peut réutiliser `coordonnees_km`, `gwr` et le krigeage ; le ch. 35 peut partir des 14 indicatrices trimestrielles (`effets_fixes()`, attribut `indice_trimestriel`) ; le ch. 20 peut intégrer les six indications du tableau 19.7 à la réconciliation. | ||||
| 39 | +- Si `library.bib` intègre un jour Anselin–Bera–Florax–Yoon (1996), citer la source primaire à la section 19.3. | ||||
| 40 | +- `sar_lag_mv` (existante, grille sur ρ avec valeurs propres réelles) et `sar_mv` (nouvelle, raffinement et valeurs propres complexes) coexistent ; l'harmonisation pourrait faire de la première un alias de la seconde (test de cohérence déjà en place : écart < 0,01). | ||||
| 41 | +- Le titre d'encadré `quebec` ne doit pas contenir de virgule (clé pgfkeys) — à noter dans CONVENTIONS si d'autres rédacteurs rencontrent l'erreur. | ||||
added
verification/chapters/ch22-calculations.csv
+15 −0
@@ -0,0 +1,15 @@ | |||||
| 1 | +id,chapitre,description,script,test,resultat_attendu,resultat_obtenu,statut,date | ||||
| 2 | +CALC-22-001,22,Cohérence avec le ch. 21 : D / I / C_N inchangés (38 postes) et bordereau q × p = montant,analysis/python/cases/ch22_metre.py,analysis/python/tests/test_ch22.py::TestCoherenceCh21,298826.17 ; 62598.68 ; 397567.33 ; 361424.85,idem,verifie,2026-10-31 | ||||
| 3 | +CALC-22-002,22,"Dimensions de base du plan coté : aire au sol, périmètre, garage, sous-sol ; invariance du périmètre en L",analysis/python/cases/ch22_metre.py,analysis/python/tests/test_ch22.py::TestGeometrie::test_empreinte_et_perimetre,95.04 m² ; 39.84 m ; 24.95 m² ; 70.09 m²,idem,verifie,2026-10-31 | ||||
| 4 | +CALC-22-003,22,"Superficies selon les conventions : aire des étages MEFQ, périmètre des étages, habitable, nette hors sol, sous-sol net et fini",analysis/python/cases/ch22_metre.py,analysis/python/tests/test_ch22.py::TestGeometrie::test_superficies_conventions,190.08 (2046 pi²) ; 79.68 m ; 165.13 (1777 pi²) ; 135.37 (58.56 + 76.81) ; 58.65 ; 49.31,idem,verifie,2026-10-31 | ||||
| 5 | +CALC-22-004,22,Couverture des niveaux par les pièces (somme des aires brutes = 95.04 / 95.04 / 70.09) et longueurs de cloisons,analysis/python/cases/ch22_metre.py,analysis/python/tests/test_ch22.py::TestGeometrie::test_pieces_couvrent_les_niveaux ; test_cloisons,21.52 / 47.94 / 20.80 m ; séparation 10.26 m,idem,verifie,2026-10-31 | ||||
| 6 | +CALC-22-005,22,"Formules élémentaires : aire décalée A + P·e + 4e², prismoïde (exact pour un tronc de pyramide), facteur de pente √(1+p²)",analysis/python/cases/ch22_metre.py,analysis/python/tests/test_ch22.py::TestGeometrie::test_formules_elementaires,identités à 1e-9 ; 1.1180,idem,verifie,2026-10-31 | ||||
| 7 | +CALC-22-006,22,"Quantités géométriques des 17 postes mesurés (excavation 408.94 m³, fondations 36.79 m³, dalle 95.04, drain 42.24 m, charpente 324.65, fermes 111.62, couverture 124.79, revêtement 238.79, isolation 419.82, gypse/peinture 733.00, bois franc 103.56, céramique 31.81, flottant 70.09, gouttières 48.80 m, balcon 14.10, entrée 55.00)",analysis/python/cases/ch22_metre.py,analysis/python/tests/test_ch22.py::TestQuantites::test_mesures_citees ; test_details_cites,voir description (tolérance 0.05),idem,verifie,2026-10-31 | ||||
| 8 | +CALC-22-007,22,"Dénombrements : 16 fenêtres (6/8/2), 3 portes ext., 1 porte de garage, 2 escaliers, 14 portes int. (4/7/3), 14 appareils, 26 semaines",analysis/python/cases/ch22_metre.py,analysis/python/tests/test_ch22.py::TestQuantites::test_denombrements,exact,idem,verifie,2026-10-31 | ||||
| 9 | +CALC-22-008,22,"Métré de contrôle : verdicts (20 conformes, 2 à préciser, 2 à justifier, 14 forfaits) ; écarts cités (gypse +18.2 %, bois franc +9.0 %, céramique −9.1 %, excavation −2.6 %, fondations −3.2 %, charpente −1.6 %) ; planchers hors sol 135.37 vs 130",analysis/python/cases/ch22_metre.py,analysis/python/tests/test_ch22.py::TestVerification::test_verdicts ; test_ecarts_cites,voir description,idem,verifie,2026-10-31 | ||||
| 10 | +CALC-22-009,22,"Effet du métré de contrôle sur D et C_N (ΔD = +3410.22 $ = +1.14 % ; D' = 302236.39 ; C_N' = 401318.58 ; ΔC_N = +3751.24 $ = +0.94 % ; ΔC_N = ΔD × 1.10 ; multiplicateur 1.3304)",analysis/python/cases/ch22_metre.py,analysis/python/tests/test_ch22.py::TestVerification::test_effet_metre_controle,voir description,idem,verifie,2026-10-31 | ||||
| 11 | +CALC-22-010,22,"Sensibilité : erreur uniforme ±5/±10 % par bloc (enveloppe ±7739 $ = 1.95 % ; tous les directs ±32871 $ = 8.27 %) ; linéarité ΔC_N = e·M·1.10",analysis/python/cases/ch22_metre.py,analysis/python/tests/test_ch22.py::TestSensibilitePropagation::test_sensibilite,voir description,idem,verifie,2026-10-31 | ||||
| 12 | +CALC-22-011,22,"Propagation : Herfindahl 0.0539 (18.6 postes effectifs), σ_D/D = 1.16 % (σ = 5 %), σ_D = 3467.78 $, poste max charpente 13.2 % ; bornes 1/n ≤ H ≤ 1",analysis/python/cases/ch22_metre.py,analysis/python/tests/test_ch22.py::TestSensibilitePropagation::test_propagation,voir description,idem,verifie,2026-10-31 | ||||
| 13 | +CALC-22-012,22,"Pertes et chutes (taux illustratifs) : gypse 694.4, bardeaux 137.5 ; surplus valorisé au prix posé 11283.78 $ ; répartition par type d'unité (mesuré 174351.56 / dénombré 89850.00 / forfait 97223.29)",analysis/python/cases/ch22_metre.py,analysis/python/tests/test_ch22.py::TestSensibilitePropagation::test_pertes ; test_repartition_types,voir description,idem,verifie,2026-10-31 | ||||
| 14 | +CALC-22-013,22,"Coûts unitaires de C_N selon la convention (190.08 → 2092 ; 165.13 → 2408 ; 135.37 → 2937 $/m²) et ratios nette/habitable 82.0 %, nette/étages 71.2 %",analysis/python/cases/ch22_metre.py,analysis/python/tests/test_ch22.py::TestGeometrie::test_couts_unitaires_conventions,voir description,idem,verifie,2026-10-31 | ||||
| 15 | +CALC-22-014,22,Exercices 22.1 à 22.7 (solutions),analysis/python/tests/test_ch22.py,analysis/python/tests/test_ch22.py::TestExercices,voir solutions/ch22.tex,idem,verifie,2026-10-31 | ||||
added
verification/chapters/ch22-figures.csv
+6 −0
@@ -0,0 +1,6 @@ | |||||
| 1 | +fichier,chapitre,script,donnees,type_donnees,legende_courte,statut | ||||
| 2 | +ch22/ch22-fig-repartition-corps.pdf,22,analysis/python/figures/ch22_repartition.py,data/synthetic/cas1_gatineau_couts.csv,synthetique,"Répartition du devis du cas 1 par bloc de corps de métier (mêmes 7 blocs que ch. 21) et par type d'unité : mesuré / dénombré / forfait [données synthétiques]",verifie | ||||
| 3 | +ch22/ch22-fig-ecarts-metre.pdf,22,analysis/python/figures/ch22_ecarts.py,"data/synthetic/cas1_gatineau_couts.csv;analysis/python/cases/ch22_metre.py (PLAN, PIECES)",synthetique,"Écarts du métré de contrôle par poste mesuré ou dénombré avec bandes de tolérance ±5 % / ±10 % ; 20 conformes, 2 à préciser, 2 à justifier [données synthétiques]",verifie | ||||
| 4 | +ch22/schema-processus-metre (TikZ),22,manuscript/chapters/ch22.tex,,schema,"Processus du métré : plans → dimensions de base → règles par corps de métier → bordereau → prix unitaires → coût direct ; boucle du métré de contrôle",verifie | ||||
| 5 | +ch22/plan-cote-sujet (TikZ),22,manuscript/chapters/ch22.tex,analysis/python/cases/ch22_metre.py (PLAN, PIECES ; code TikZ généré par --tikz),synthetique,"Plan coté du sujet du cas 1 : rez-de-chaussée (garage intégré 3,96 × 6,30 m) et étage, 12,00 × 7,92 m, aires brutes des pièces [données synthétiques]",verifie | ||||
| 6 | +ch22/coupe-transversale-sujet (TikZ),22,manuscript/chapters/ch22.tex,analysis/python/cases/ch22_metre.py (PLAN),synthetique,"Coupe transversale schématique : fondation 2,44 m, deux niveaux de 2,75 m, toit 6:12 avec débords 0,40 m, prisme d'excavation (dégagement 0,90 m, talus 0,5:1, profondeur 2,60 m) [données synthétiques]",verifie | ||||
added
verification/chapters/ch22-registry.csv
+3 −0
@@ -0,0 +1,3 @@ | |||||
| 1 | +id,type,titre,organisme,version_ou_date,url,date_consultation,statut,utilise_dans,notes | ||||
| 2 | +SRC-22-001,page_web,"Salaire et taux — conventions collectives 2025-2029 (outil des taux de salaire)",Commission de la construction du Québec,Page consultée le 2026-10-31,https://www.ccq.org/fr-CA/avantages-sociaux/salaire-taux,2026-10-31,verifie,22,"Lu par agent web-fetch : « L'employeur a l'obligation de payer les salariés selon les conventions collectives en vigueur » ; quatre secteurs (A génie civil et voirie, B industriel, C institutionnel et commercial, D résidentiel) ; outil des taux par date et secteur ; majoration annuelle au 26 avril 2026 (résidentiel léger 5,5 %, autres secteurs 5 % — association des pourcentages peu lisible dans l'extrait) ; priorité des textes des conventions sur l'outil. Taux horaires par métier non relevés. Clé bib existante : ccqSalaires (urldate à mettre à jour)." | ||||
| 3 | +SRC-22-002,page_web,"CIQS — Canadian Institute of Quantity Surveyors (page d'accueil)",Canadian Institute of Quantity Surveyors,Page consultée le 2026-10-31,https://ciqs.org/,2026-10-31,verifie,22,"Nom de l'organisme et titres décernés (Professional Quantity Surveyor, PQS ; Construction Estimator Certified, CEC) lus sur la page ; le nom français et les méthodes de mesurage publiées n'y figurent pas. Entrée bib proposée : ciqs (lib-ch22.bib), non citée." | ||||
modified
verification/figures.csv
+5 −0
@@ -104,3 +104,8 @@ ch19/ch19-fig-variogramme.pdf,19,analysis/python/figures/ch19_figures.py,data/sy | |||||
| 104 | ch19/ch19-fig-krigeage.pdf,19,analysis/python/figures/ch19_figures.py,data/synthetic/cas1_gatineau_ventes.csv,synthetique,Surface krigée des résidus du modèle sans secteur [données synthétiques],verifie | 104 | ch19/ch19-fig-krigeage.pdf,19,analysis/python/figures/ch19_figures.py,data/synthetic/cas1_gatineau_ventes.csv,synthetique,Surface krigée des résidus du modèle sans secteur [données synthétiques],verifie | ||
| 105 | ch19/ch19-fig-sensibilite-W.pdf,19,analysis/python/figures/ch19_figures.py,data/synthetic/cas1_gatineau_ventes.csv,synthetique,"I de Moran, rho du SAR et lambda du SEM selon le nombre de voisins [données synthétiques]",verifie | 105 | ch19/ch19-fig-sensibilite-W.pdf,19,analysis/python/figures/ch19_figures.py,data/synthetic/cas1_gatineau_ventes.csv,synthetique,"I de Moran, rho du SAR et lambda du SEM selon le nombre de voisins [données synthétiques]",verifie | ||
| 106 | ch19/tikz-taxonomie-effets-spatiaux,19,manuscript/chapters/ch19.tex,,schema,Taxonomie dépendance / hétérogénéité spatiales et outils (TikZ),verifie | 106 | ch19/tikz-taxonomie-effets-spatiaux,19,manuscript/chapters/ch19.tex,,schema,Taxonomie dépendance / hétérogénéité spatiales et outils (TikZ),verifie | ||
| 107 | +ch22/ch22-fig-repartition-corps.pdf,22,analysis/python/figures/ch22_repartition.py,data/synthetic/cas1_gatineau_couts.csv,synthetique,Répartition du devis du cas 1 par bloc de corps de métier (mêmes 7 blocs que ch. 21) et par type d'unité : mesuré / dénombré / forfait [données synthétiques],verifie | ||||
| 108 | +ch22/ch22-fig-ecarts-metre.pdf,22,analysis/python/figures/ch22_ecarts.py,"data/synthetic/cas1_gatineau_couts.csv;analysis/python/cases/ch22_metre.py (PLAN, PIECES)",synthetique,"Écarts du métré de contrôle par poste mesuré ou dénombré avec bandes de tolérance ±5 % / ±10 % ; 20 conformes, 2 à préciser, 2 à justifier [données synthétiques]",verifie | ||||
| 109 | +ch22/schema-processus-metre (TikZ),22,manuscript/chapters/ch22.tex,,schema,Processus du métré : plans → dimensions de base → règles par corps de métier → bordereau → prix unitaires → coût direct ; boucle du métré de contrôle,verifie | ||||
| 110 | +ch22/plan-cote-sujet (TikZ),22,manuscript/chapters/ch22.tex,analysis/python/cases/ch22_metre.py (PLAN,PIECES ; code TikZ généré par --tikz),synthetique,"Plan coté du sujet du cas 1 : rez-de-chaussée (garage intégré 3,96 × 6,30 m) et étage, 12,00 × 7,92 m, aires brutes des pièces [données synthétiques]" | ||||
| 111 | +ch22/coupe-transversale-sujet (TikZ),22,manuscript/chapters/ch22.tex,analysis/python/cases/ch22_metre.py (PLAN),synthetique,"Coupe transversale schématique : fondation 2,44 m, deux niveaux de 2,75 m, toit 6:12 avec débords 0,40 m, prisme d'excavation (dégagement 0,90 m, talus 0,5:1, profondeur 2,60 m) [données synthétiques]",verifie | ||||
| 107 | 112 | ||||