#!/usr/bin/env catnip
# Seaborn : visualisation statistique où la segmentation vit en Catnip pur.
# NumPy tire un échantillon reproductible, Catnip segmente chaque bien par une
# règle pure et matchable, Seaborn dessine la distribution du prix par segment.
#
# Reproductible et offline : pas de seaborn.load_dataset (réseau), données
# synthétiques à graine fixe, backend matplotlib non-interactif (Agg).
#
# DEPS: seaborn matplotlib numpy
np = import('numpy')
mpl = import('matplotlib')
mpl.use('Agg') # backend headless : rendu fichier, aucune fenêtre
plt = import('matplotlib.pyplot')
sns = import('seaborn')
pathlib = import('pathlib')
tempfile = import('tempfile')
# sample — NumPy tire un nuage reproductible : surface (m²) et prix (k€),
# le prix corrélé à la surface plus un bruit. C'est le métier de NumPy.
rng = np.random.default_rng(7)
n = 240
surfaces_arr = np.clip(rng.normal(72, 30, n), 18, 210)
prices_arr = 2.4 * surfaces_arr + 60 + rng.normal(0, 35, n)
surfaces = surfaces_arr.tolist()
# La règle de segmentation est en Catnip : pure, isolée, testable seule.
# Seaborn regroupera les boîtes selon ce label ; NumPy ne le connaît pas.
@pure
segment = (m2: float): str => {
match m2 {
x if x < 40 => { "studio" }
x if x < 90 => { "familial" }
_ => { "grand" }
}
}
# transform — broadcast Catnip de la règle sur la colonne surface
segments = surfaces.[segment]
# plot — Seaborn dessine la distribution du prix par segment Catnip
sns.set_theme(style='whitegrid')
fig, ax = plt.subplots(figsize=tuple(8, 5))
order = list("studio", "familial", "grand")
sns.boxplot(x=segments, y=prices_arr.tolist(), order=order, ax=ax)
ax.set_title("Prix par segment (segmentation Catnip, données NumPy)")
ax.set_xlabel("Segment")
ax.set_ylabel("Prix (k€)")
out_dir = pathlib.Path(tempfile.gettempdir()) / "catnip_seaborn_examples"
out_dir.mkdir(parents=True, exist_ok=True)
out_file = out_dir / "seaborn_price_by_segment.png"
fig.savefig(str(out_file), dpi=120, bbox_inches='tight')
# agrégat — effectif et prix moyen par segment, via masques NumPy
seg_arr = np.array(segments)
print("⇒ Prix par segment")
for label in order {
mask = np.equal(seg_arr, label) # np.equal : évite la coercition bool() de ==
subset = prices_arr[mask]
print(label, "| n =", int(mask.sum()), "| prix moyen =", round(float(subset.mean()), 1), "k€")
}
print()
print("Image PNG :", out_file)