1. Prix ≠ attractivité — Corrélation prix × SMA = 0,34 (ZE). Le prix capte autant la rente foncière que l’attractivité courante. Corrélation prix × revenu bien plus forte (0,75 DEP).
2. Construction en chute — 823k logements commencés (22-24), soit 67,1 M m² de surface. Médiane 12,2 logements / 1 000 hab.
3. Vacance = thermomètre déprise — Vacance 2+ ans corrèle à 0,02 avec le SMA (DEP). 174 EPCI voient leur vacance augmenter 2020-2024.
4. Loyers en hausse modérée — Médiane loyer appt 11,5 EUR/m² (+11,4 % 22-25), maison 10,2 EUR/m².
Données : DVF 2014-2024 · LOVAC 2020-2024 · SITADEL 2019-2024 · ANIL 2022-2025 · INSEE RP 2016-2022
Hypothèses : H4 La pression immobilière est un proxy de l’attractivité résidentielle · H6 Le cycle foncier prédit les dynamiques territoriales
Cadrage : distributions clés
Le marché du logement est un révélateur structurel des dynamiques territoriales. Contrairement aux flux migratoires — qui captent le mouvement des personnes — le logement traduit la résultante matérielle de l’attractivité : prix, vacance, construction. Un territoire qui attire voit ses prix monter, sa vacance baisser et sa construction accélérer.
plot_distribution(dep, "logd_px2_global_24", bins =25,title ="Prix concentrés sous 3 000 EUR/m²",xlab ="Prix médian m² (EUR)", fill = col_cyan) +geom_vline(xintercept = fr_px, linetype ="solid", color = col_orange, linewidth =0.7) +annotate("text", x = fr_px +200, y =Inf,label =glue("France {fmt_fr(fr_px, 0)}"),color = col_orange, size =3, vjust =2, fontface ="italic") +labs(y ="Nombre de DEP",caption =make_source("DVF 2024"))plot_distribution(dep, "logv_vac2ans_pct_24", bins =20,title ="Vacance bimodale : tension vs déprise",xlab ="Vacance longue durée (%)", fill = col_green) +labs(y ="Nombre de DEP",caption =make_source("LOVAC 2024"))plot_distribution(dep, "logs_logcom_tx1000_2224", bins =20,title ="Construction neuve très inégale",xlab ="Logements commencés / 1 000 hab", fill = col_magenta) +labs(y ="Nombre de DEP",caption =make_source("SITADEL 2022-2024"))
Warning: Removed 3 rows containing non-finite outside the scale range (`stat_bin()`).
Warning: Removed 3 rows containing missing values or values outside the scale range (`geom_rug()`).
Les distributions révèlent des marchés asymétriques. Les prix sont concentrés sous 3 000 EUR/m² avec queue droite (IDF, littoral). La vacance est bimodale (tension <2% vs déprise >5%). La construction neuve varie d’un facteur 10 entre départements.
QE3.1 — Géographie des prix
16 départements en baisse de prix 2022-2024 (médiane : +2,64 %). Le retournement post-2022 touche inégalement les territoires.
[v3->v4] `tm_layout()`: use text.fontfamily instead of fontfamily
[v3->v4] `tm_layout()`: use text.fontfamily instead of fontfamily
Gauche : prix au m² médian DVF 2024. Droite : évolution récente 2022-2024. Le retournement post-COVID (hausse des taux) touche surtout l’IDF et les grandes métropoles.
plot_bar_ranked( dep, var ="logd_px2_global_24", label_col ="libelle",n_show =15,title =glue("Facteur {ratio_px} entre extrêmes"),subtitle =glue("Top/Bottom 15 départements — prix m² DVF 2024"),xlab ="Prix m² (EUR)",caption =make_source("DVF 2024"))
Warning: Specifying width/height in layout() is now deprecated.
Please specify in ggplotly() or plot_ly()
tm_shape(map_epci) +tm_polygons(fill ="logd_px2_global_24",fill.scale =tm_scale_intervals(breaks = breaks_px,values =make_pal(pal_urbn_seq_blue, 8)),fill.legend =tm_legend_clean("EUR/m²"),col ="grey90", lwd =0.1) +tm_urbn("Prix m² global — EPCI, DVF 2024") +tm_source(make_source("DVF"))
[v3->v4] `tm_layout()`: use text.fontfamily instead of fontfamily
plot_bar_ranked( epci %>%filter(!is.na(logd_px2_global_24)),var ="logd_px2_global_24", label_col ="libelle",n_show =20,title ="Extrêmes de prix au m² — EPCI",subtitle =glue("Top/Bottom 20 — {N_EPCI} EPCI métropolitains"),xlab ="Prix m² (EUR)",caption =make_source("DVF 2024"))
Warning: Specifying width/height in layout() is now deprecated.
Please specify in ggplotly() or plot_ly()
Warning: Removed 23 rows containing missing values or values outside the scale range (`geom_point()`).
Taille = population 2022. Orange = France (2 725 EUR/m²). ZE en bas-droite (SMA positif, prix modérés) = attractivité non encore capitalisée.
QE3.2 — Construction neuve et surfaces (SITADEL)
67,1 millions de m² commencés 2022-2024 — la concentration de la construction est plus forte que celle de la population (Gini = 0,448).
La construction neuve traduit la capacité d’un territoire à répondre à la demande. Le taux de construction (logements commencés pour 1 000 habitants) est l’indicateur le plus discriminant : il reflète à la fois la pression démographique, la disponibilité foncière et l’effort des collectivités.
[v3->v4] `tm_layout()`: use text.fontfamily instead of fontfamily
[v3->v4] `tm_layout()`: use text.fontfamily instead of fontfamily
Gauche : taux de construction rapporté à la population. Droite : volume brut de surface de plancher commencée (m²). Les littoraux et couronnes métropolitaines construisent le plus.
plot_bar_ranked( dep, var ="logs_logcom_tx1000_2224", label_col ="libelle",n_show =15,title ="Taux de construction — Top/Bottom 15 DEP",subtitle ="Logements commencés / 1 000 hab (2022-2024)",xlab ="Log commencés / 1 000 hab",caption =make_source("SITADEL"))plot_bar_ranked( dep, var ="logs_sdpcom_vol_2224", label_col ="libelle",n_show =15,title ="Surface m² commencée — Top/Bottom 15 DEP",subtitle ="Cumul 2022-2024 (m² de plancher)",xlab ="Surface commencée (m²)",caption =make_source("SITADEL"))
Warning: Specifying width/height in layout() is now deprecated.
Please specify in ggplotly() or plot_ly()
Warning: Specifying width/height in layout() is now deprecated.
Please specify in ggplotly() or plot_ly()
[v3->v4] `tm_layout()`: use text.fontfamily instead of fontfamily
sdp_vals <- dep$logs_sdpcom_vol_2224[!is.na(dep$logs_sdpcom_vol_2224) & dep$logs_sdpcom_vol_2224 >0]sdp_sorted <-sort(sdp_vals)n_sdp <-length(sdp_sorted)cum_share <-cumsum(sdp_sorted) /sum(sdp_sorted)pop_share <-seq_len(n_sdp) / n_sdplorenz_df <-data.frame(pop =c(0, pop_share), sdp =c(0, cum_share))p80_idx <-which.min(abs(pop_share -0.80))sdp_at_80 <- cum_share[p80_idx] *100ggplot(lorenz_df, aes(x = pop, y = sdp)) +geom_line(color = col_cyan, linewidth =1.2) +geom_abline(slope =1, intercept =0, linetype ="dashed", color = col_gray) +geom_segment(aes(x =0.80, xend =0.80, y =0, yend = cum_share[p80_idx]),linetype ="dotted", color = col_orange) +geom_segment(aes(x =0, xend =0.80, y = cum_share[p80_idx], yend = cum_share[p80_idx]),linetype ="dotted", color = col_orange) +annotate("text", x =0.55, y = cum_share[p80_idx] +0.04,label =glue("80% des DEP = {fmt_pct(sdp_at_80, 0)} m²"),size =3.5, color = col_orange, fontface ="bold") +annotate("text", x =0.35, y =0.85,label =glue("Gini = {fmt_fr(gini_sdp, 3)}"),size =4, color = col_cyan, fontface ="bold") +scale_x_continuous(labels =percent_format(), expand =c(0, 0.01)) +scale_y_continuous(labels =percent_format(), expand =c(0, 0.01)) +labs(title ="Construction neuve : forte concentration territoriale",subtitle ="Courbe de Lorenz — surface commencée par département",x ="Part cumulée des départements",y ="Part cumulée des m² commencés",caption =make_source("SITADEL 2022-2024"))
Warning in geom_segment(aes(x = 0.8, xend = 0.8, y = 0, yend = cum_share[p80_idx]), : All aesthetics have length 1, but the data has 97 rows.
ℹ Please consider using `annotate()` or provide this layer with data containing a single row.
Warning in geom_segment(aes(x = 0, xend = 0.8, y = cum_share[p80_idx], yend = cum_share[p80_idx]), : All aesthetics have length 1, but the data has 97 rows.
ℹ Please consider using `annotate()` or provide this layer with data containing a single row.
Courbe de Lorenz sur la surface de plancher commencée (m²). Plus la courbe s’éloigne de la diagonale, plus la construction est concentrée géographiquement. Gini = 0,448.
Vacance 2+ ans : 174 EPCI en hausse 2020-2024. La corrélation vacance × SMA = 0,02 (DEP) confirme le lien entre déprise démographique et abandon du parc.
La vacance structurelle (LOVAC >2 ans) discrimine mieux la dévitalisation que la vacance du recensement. Elle capte les logements durablement hors marché — un signal fort de déprise territoriale.
[v3->v4] `tm_layout()`: use text.fontfamily instead of fontfamily
[v3->v4] `tm_layout()`: use text.fontfamily instead of fontfamily
[scale] tm_polygons:() the data variable assigned to 'fill' contains positive and negative values, so midpoint is set to 0. Set 'midpoint = NA' in 'fill.scale = tm_scale_intervals(<HERE>)' to use all visual values (e.g. colors)
Gauche : taux de vacance longue durée 2024. Droite : évolution 2020-2024 (points de %). Nord-est et Massif central concentrent vacance élevée et aggravation.
[v3->v4] `tm_layout()`: use text.fontfamily instead of fontfamily
scatter_quadrants( dep, x ="dm_sma_vtcam_1622", y ="logv_vac2ans_pct_24",title ="Déclin démographique = vacance longue durée",subtitle =glue("r = {fmt_fr(cor_vac_sma_dep, 2)} | LOVAC 2+ ans vs SMA 16-22 | {N_DEP} DEP"),xlab ="SMA TCAM 16-22 (%/an)", ylab ="Vacance 2+ ans (%)",hline = med_vac_dep, vline =0,quad_labels =c("Attractif tendu", "Attractif détendu","Déclin détendu", "Déclin tendu")) +labs(caption =make_source("LOVAC", "INSEE RP"))
plot_bar_ranked( dep, var ="logv_vac2ans_pct_24", label_col ="libelle",n_show =15,title ="Vacance 2+ ans — Top/Bottom 15 DEP",subtitle =glue("LOVAC 2024 | Médiane = {fmt_pct(med_vac_dep)}"),xlab ="Vacance 2+ ans (%)",caption =make_source("LOVAC 2024"))
Warning: Specifying width/height in layout() is now deprecated.
Please specify in ggplotly() or plot_ly()
QE3.4 — Loyers et accessibilité (ANIL)
Loyer médian appt : 11,5 EUR/m² (hausse médiane +11,4 % 22-25). L’accessibilité se dégrade dans les marchés déjà tendus.
Les données ANIL (Observatoires Locaux des Loyers) permettent de compléter le tableau DVF par les prix à la location. La comparaison prix d’achat / loyer / revenu médian donne un indicateur d’accessibilité territoriale.
[v3->v4] `tm_layout()`: use text.fontfamily instead of fontfamily
[v3->v4] `tm_layout()`: use text.fontfamily instead of fontfamily
Gauche : loyer médian appt tous types (EUR/m²) 2025. Droite : évolution 2022-2025 (%). Les loyers augmentent partout, mais l’accélération est plus forte en province qu’en IDF.
Warning: Specifying width/height in layout() is now deprecated.
Please specify in ggplotly() or plot_ly()
labs_loyer <-label_top_bottom(dep, "logl_app_m2_25", n =8)ggplot(dep %>%filter(!is.na(logl_app_m2_25), !is.na(logl_mai_m2_25)),aes(x = logl_mai_m2_25, y = logl_app_m2_25)) +geom_abline(slope =1, intercept =0, linetype ="dashed", color = col_gray) +geom_point(aes(size = P22_POP), alpha =0.5, color = col_cyan) +geom_text_repel(data = dep %>%filter(libelle %in% labs_loyer),aes(label = libelle), size =2.8, max.overlaps =15,color = col_spacegray, segment.color = col_gray ) +scale_size_continuous(range =c(1, 7), guide ="none") +labs(title ="Loyer appt systématiquement supérieur au loyer maison",subtitle =glue("{N_DEP} départements | Diagonale = parité"),x ="Loyer maison (EUR/m²)", y ="Loyer appt (EUR/m²)",caption =make_source("ANIL/OLL 2025") )
Warning: ggrepel: 8 unlabeled data points (too many overlaps). Consider increasing max.overlaps
Tous les points sont au-dessus de la diagonale : le loyer au m² des appartements est toujours plus élevé que celui des maisons. L’écart s’accentue dans les marchés tendus (IDF, métropoles).
QE3.5 — Indices composites : tension et gentrification
idxlogtens corrèle à 0,76 avec les prix et -0,28 avec la vacance — un signal composite cohérent.
L’indice de tension logement synthétise prix, vacance et dynamique du parc. Sa corrélation modérée avec l’indice résidentiel confirme que les deux ne sont pas redondants : l’idxresid capte les flux humains, l’idxlogtens traduit la résultante immobilière.
scatter_quadrants( ze, x ="idxresid_dyn_ind_1623", y ="idxlogtens_ind_22",title ="Flux humains ≠ tension immobilière",subtitle =glue("r = {fmt_fr(cor_lt_resid, 2)} | Résidentiel vs tension logement"),xlab ="Indice résidentiel T2 (0-100)", ylab ="Indice tension logement (0-100)",hline =50, vline =50,quad_labels =c("Attractif + tendu", "Peu attractif + tendu","Peu attractif + détendu", "Attractif + détendu")) +labs(caption =make_source("MIGCOM", "DVF", "LOVAC"))labs_g <-label_top_bottom(ze, "idxgentri_ind_1622", n =10)ggplot(ze, aes(x = dmf_tmi_cscadre_22, y = idxgentri_ind_1622)) +geom_hline(yintercept =50, linetype ="dashed", color = col_gray) +geom_vline(xintercept =0, linetype ="dashed", color = col_gray) +geom_point(aes(size = P22_POP, color = logd_px2_global_vevol_1624), alpha =0.7) +geom_text_repel(data = ze %>%filter(libelle %in% labs_g),aes(label = libelle), size =2.8, max.overlaps =20,color = col_spacegray, segment.color = col_gray ) +scale_size_continuous(range =c(1, 7), guide ="none") +scale_color_gradient2(low = col_magenta, mid ="grey90", high = col_green,midpoint =0, name ="Evol prix (%)" ) +labs(title ="Gentrification = afflux cadres + hausse prix",subtitle =glue("r cadres = {fmt_fr(cor_gentri_cadre, 2)} | r prix = {fmt_fr(cor_gentri_prix, 2)}"),x ="TMI cadres 2022 (pts)", y ="Indice gentrification (0-100)",caption =make_source("MIGCOM", "DVF") )
Gauche : les quadrants montrent que tension et attractivité ne coïncident pas toujours — certaines ZE sont tendues sans être attractives (inertie foncière). Droite : couleur = évolution prix (vert = hausse, violet = baisse).