Notebook d'exploration data répondant à la question :
Au-delà du prix au m², quels facteurs (accessibilité, emploi, climat, attractivité touristique, qualité de vie perçue) déterminent la valeur réelle d'un territoire, et comment aider un acheteur à identifier les communes sous-cotées ?
- DuckDB comme moteur unique de la couche data (ingestion, nettoyage, jointures, spatial), matérialisé dans
data/exploration.duckdb. - pandas + scikit-learn pour l'analyse en aval (stats, régression, normalisation, score composite).
- Données opendata nationales, téléchargées et mises en cache dans
data/raw/. - Clé de jointure universelle : code commune INSEE (
VARCHAR(5), zéro-paddé). - Politique « rejeter + compter » : chaque source passe par un nettoyage actif avec rapport de rejets par motif (
dq_*_rejets).
| Dimension | Source | Table DuckDB |
|---|---|---|
| Prix immobilier | DVF 2024 — geo-dvf (data.gouv) | dvf, commune_agg |
| Contours géographiques | Etalab 2025 (GeoJSON) | commune_geom, dept_geom |
| Transport | Arrêts nationaux (transport.data.gouv) → jointure spatiale ST_Contains | arrets, commune_transport |
| Performance énergétique | DPE ADEME (API data-fair, échantillon 200k) | dpe |
| Risques naturels | Géorisques GASPAR — arrêtés catnat | risques |
| Tourisme | Résidences secondaires INSEE RP 2021 (IRIS → commune) | tourisme |
| Revenus | INSEE Filosofi 2021 — revenu médian/UC | revenus |
| Sécurité | SSMSI — délinquance enregistrée communale | securite |
| Équipements | BPE INSEE 2024 — services/santé & loisirs/culture | equipements |
| Climat | Météo-France normales 1991-2020 — ensoleillement & température (rattachement par station la plus proche) | climat |
| Emploi | INSEE RP 2021 — taux de chômage BIT & taux de couverture emploi | emploi |
| Dynamique de marché | DVF millésimes 2021→2024 | commune_prix_<année> |
| Perception (NLP) | Avis d'habitants | (source à brancher — pas de simulation) |
Le score composite agrège 9 dimensions par pondération explicite (somme = 1) :
| Dimension | Poids | Sens |
|---|---|---|
| Accessibilité financière (prix/revenu) | 30 % | malus si inaccessible |
| Emploi (chômage + couverture) | 15 % | bonus si dynamique |
| Transport (densité d'arrêts/km²) | 11 % | bonus |
| Sécurité (taux délinquance) | 11 % | malus si élevé |
| Services & santé (densité/1000 hab) | 11 % | bonus |
| Loisirs & culture (densité/1000 hab) | 8 % | bonus |
| Ensoleillement (h/an) | 7 % | bonus |
| Risques naturels (arrêtés catnat) | 4 % | malus |
| Tourisme (part rés. secondaires) | 3 % | bonus |
Gap = score_valeur − prix_normalisé. Un gap positif signale une commune qui offre beaucoup de qualité pour un prix encore modéré : candidate sous-cotée.
Le classement est testé en robustesse (4 variantes de poids et de normalisation) et backtesté sur l'évolution des prix DVF 2021→2024 (ρ Spearman = +0.245).
uv sync
uv run jupyter lab notebooks/exploration.ipynb
# ou exécution complète :
uv run jupyter nbconvert --to notebook --execute --inplace notebooks/exploration.ipynbLe premier run télécharge les sources (~1 Go au total) et matérialise toutes les tables ; les runs suivants sont quasi instantanés (cache disque + base DuckDB persistante).
src/
io.py connexion DuckDB, téléchargements cachés, résolution data.gouv
ingest.py socle stable : DVF, contours géo, transport (spatial)
ingest_extra.py sources complémentaires : DPE, risques, tourisme, revenus,
sécurité, équipements, prix millésimés, climat, emploi
preprocess.py nettoyage actif par source (clean_*) + seuils de plausibilité
quality.py profilage, règles de validation, couverture, taux d'appariement
notebooks/
exploration.ipynb livrable narratif — ~12 visualisations, score composite,
analyse de robustesse, backtest, top 25 communes sous-cotées