Chantiers perturbants

Données - Ville de Paris

Code
source(here::here("_rinit.R"))
source(here::here("data", "paris", "_paris.R"))   # wkb2sfc(), paris_basemap(), arrondissements_sf()
invisible(Sys.setlocale("LC_TIME", "fr_FR.UTF-8"))
# cd ~/iCloud/website/data/paris; /usr/local/bin/R -e 'quarto::quarto_render("chantiers-perturbants.qmd")'

knitr::opts_chunk$set(echo = TRUE, message = FALSE, warning = FALSE,
                      fig.width = 8, fig.height = 5, dpi = 150)

ch_path <- here::here("data", "paris", "chantiers-perturbants.parquet")
chantiers <- arrow::read_parquet(ch_path) |>
  dplyr::mutate(ar = suppressWarnings(as.integer(substr(cp_arrondissement, 4, 5))))

n_tot  <- nrow(chantiers)
arr_sf <- arrondissements_sf()
pts_sf <- chantiers |>
  dplyr::filter(lengths(geo_point_2d) > 0) |>   # 1 chantier sans localisation
  dplyr::mutate(geometry = wkb2sfc(geo_point_2d)) |>
  sf::st_as_sf(crs = 4326)

theme_carte <- theme_void(base_size = 12) +
  theme(plot.title = element_text(face = "bold"),
        plot.subtitle = element_text(colour = "grey35"),
        plot.margin = margin(5, 12, 5, 5))
theme_barres <- theme_minimal(base_size = 12) +
  theme(plot.title = element_text(face = "bold"),
        plot.subtitle = element_text(colour = "grey35"),
        panel.grid.major.y = element_blank())

Les 113 grands chantiers ayant un impact notable sur la circulation — réseaux de chaleur (CPCU/Fraîcheur de Paris), RATP, RTE, SNCF, Eau de Paris… — avec leur emprise, leurs dates prévisionnelles (certaines courent jusqu’en 2031) et leur impact sur la voirie.

Code
chantiers |>
  dplyr::arrange(dplyr::desc(date_debut)) |>
  dplyr::transmute(Voie = voie, Arrondissement = ar, `Maître d'ouvrage` = maitre_ouvrage,
                   Objet = objet, Début = date_debut, Fin = date_fin,
                   `Impact circulation` = impact_circulation) |>
  head(8) |>
  gt::gt() |>
  gt::sub_missing(missing_text = "—") |>
  gt::tab_header(title = "8 chantiers les plus récemment ouverts") |>
  gt::tab_options(table.width = "100%")
8 chantiers les plus récemment ouverts
Voie Arrondissement Maître d'ouvrage Objet Début Fin Impact circulation
22-24 quai d'Austerlitz 13 REHABILITATION_IMMEUBLE 2027-03-29 2027-11-26 RESTREINTE
boulevard du Palais 75004_ 4 APIJ REHABILITATION_IMMEUBLE 2026-11-16 2031-03-31 RESTREINTE
rue de Vaugirard 75006_ 6 Sénat REHABILITATION_IMMEUBLE 2026-11-13 2027-08-31 RESTREINTE
46 rue des Fossés Saint Bernard 5 Fraicheur de Paris RACCORDEMENT_RESEAU 2026-11-02 2026-11-16 RESTREINTE
avenue de la Porte de Pouchet 75017 17 Ville de Paris REAMENAGEMENT_VOIRIE 2026-10-26 2026-12-11 RESTREINTE
1 rue des Ecoles 5 Fraicheur de Paris RACCORDEMENT_RESEAU 2026-10-19 2026-11-02 RESTREINTE
rue de l'université 7 Fraîcheur de Paris CREATION_RESEAUX 2026-10-19 2026-12-18 RESTREINTE
40 quai des Célestins 4 SAP ENTRETIEN_RESEAU 2026-09-30 2027-05-14 RESTREINTE

Carte

Code
pal <- leaflet::colorFactor("Set1", domain = chantiers$impact_circulation)

leaflet::leaflet(pts_sf, options = leaflet::leafletOptions(minZoom = 11)) |>
  paris_basemap() |>
  leaflet::addPolygons(data = arr_sf, fill = FALSE, color = "#999", weight = 1) |>
  leaflet::addCircleMarkers(
    radius = 6, stroke = FALSE, fillOpacity = 0.8,
    fillColor = ~pal(impact_circulation),
    label = ~sprintf("%s — %s", voie, maitre_ouvrage),
    popup = ~sprintf("<b>%s</b><br>%s<br>%s<br>Du %s au %s<br>Impact : %s",
                     voie, maitre_ouvrage, objet, format(date_debut, "%d/%m/%Y"),
                     format(date_fin, "%d/%m/%Y"), impact_circulation)
  ) |>
  leaflet::addLegend("bottomright", pal = pal, values = ~impact_circulation,
                     title = "Impact circulation", opacity = 0.9)

Combien de chantiers en même temps

Code
mois_seq <- seq(as.Date(cut(min(chantiers$date_debut, na.rm = TRUE), "month")),
                as.Date(cut(max(chantiers$date_fin, na.rm = TRUE), "month")), by = "month")

n_actifs <- vapply(mois_seq, function(m)
  sum(chantiers$date_debut <= m & chantiers$date_fin >= m, na.rm = TRUE), integer(1))

tibble::tibble(mois = mois_seq, n = n_actifs) |>
  ggplot(aes(mois, n)) +
  geom_area(fill = "#7a5a2b", alpha = 0.3) +
  geom_line(colour = "#7a5a2b", linewidth = 0.9) +
  scale_x_date(date_labels = "%Y", date_breaks = "1 year") +
  labs(title = "Nombre de chantiers perturbants simultanément actifs",
       subtitle = "D'après les dates de début/fin prévisionnelles renseignées",
       x = NULL, y = NULL) +
  theme_barres

Qui creuse, et où

Code
chantiers |>
  dplyr::filter(!is.na(maitre_ouvrage)) |>
  dplyr::count(maitre_ouvrage, sort = TRUE) |>
  head(10) |>
  dplyr::mutate(maitre_ouvrage = forcats::fct_reorder(maitre_ouvrage, n)) |>
  ggplot(aes(n, maitre_ouvrage)) +
  geom_col(fill = "#8a5a2b", width = 0.6) +
  geom_text(aes(label = n), hjust = -0.2, size = 3) +
  scale_x_continuous(expand = expansion(mult = c(0, 0.12))) +
  labs(title = "Maîtres d'ouvrage les plus présents",
       subtitle = "Le réseau de chaleur urbain (CPCU / Fraîcheur de Paris) domine",
       x = NULL, y = NULL) +
  theme_barres

Code
chantiers |>
  dplyr::filter(!is.na(impact_circulation)) |>
  dplyr::count(impact_circulation, sort = TRUE) |>
  dplyr::mutate(impact_circulation = forcats::fct_reorder(impact_circulation, n)) |>
  ggplot(aes(n, impact_circulation)) +
  geom_col(fill = "#c0392b", width = 0.55) +
  geom_text(aes(label = n), hjust = -0.2, size = 3.2) +
  scale_x_continuous(expand = expansion(mult = c(0, 0.12))) +
  labs(title = "Impact sur la circulation", x = NULL, y = NULL) +
  theme_barres

Le jeu de données porte aussi des codes niveau_perturbation, statut et typologie — non documentés par la source (pas de légende publiée dans le catalogue ODS), donc non repris ici pour éviter d’en inventer le sens.

Tous les chantiers

Code
chantiers |>
  dplyr::arrange(date_debut) |>
  dplyr::transmute(Voie = voie, Arrondissement = ar, `Maître d'ouvrage` = maitre_ouvrage,
                   Objet = objet, Début = date_debut, Fin = date_fin,
                   `Impact` = impact_circulation) |>
  reactable::reactable(
    searchable = TRUE,
    filterable = TRUE,
    pagination = TRUE,
    defaultPageSize = 20,
    compact = TRUE,
    resizable = TRUE,
    highlight = TRUE,
    wrap = TRUE,
    defaultColDef = reactable::colDef(
      align = "left",
      headerStyle = list(fontWeight = "bold"),
      style = list(whiteSpace = "normal", wordBreak = "break-word")
    ),
    columns = list(
      Voie = reactable::colDef(minWidth = 160),
      Arrondissement = reactable::colDef(minWidth = 70, maxWidth = 110),
      `Maître d'ouvrage` = reactable::colDef(minWidth = 130),
      Objet = reactable::colDef(minWidth = 130),
      Début = reactable::colDef(minWidth = 90, maxWidth = 110),
      Fin = reactable::colDef(minWidth = 90, maxWidth = 110),
      Impact = reactable::colDef(minWidth = 100)
    )
  )

Source & données

Code
tibble::tibble(
  ` ` = c("Jeu de données", "Producteur", "Licence", "Fichier", "Mise à jour", "Observations"),
  `  ` = c(
    "[Chantiers perturbants](https://opendata.paris.fr/explore/dataset/chantiers-perturbants/information/)",
    "Direction de la Voirie et des Déplacements — Ville de Paris",
    "Open Database License (ODbL)",
    sprintf("`data/paris/chantiers-perturbants.parquet` (%s ko) + `arrondissements.parquet`",
            round(file.size(ch_path) / 1024)),
    format(as.Date(file.mtime(ch_path)), "%d %B %Y"),
    sprintf("%d chantiers, %s à %s", n_tot, format(min(chantiers$date_debut, na.rm = TRUE), "%Y"),
            format(max(chantiers$date_fin, na.rm = TRUE), "%Y"))
  )
) |>
  gt::gt() |> gt::fmt_markdown(columns = `  `) |>
  gt::tab_options(table.width = "100%", column_labels.hidden = TRUE)
Jeu de données Chantiers perturbants
Producteur Direction de la Voirie et des Déplacements — Ville de Paris
Licence Open Database License (ODbL)
Fichier data/paris/chantiers-perturbants.parquet (36 ko) + arrondissements.parquet
Mise à jour 05 septembre 2026
Observations 113 chantiers, 2018 à 2031