---
title: "Production thermique à partir de la chaleur ambiante"
subtitle: "Chaleur extraite de l'environnement et consommation électrique des PAC, Vaud"
lang: fr
author: "DGE-DIREN"
date: last-modified # Renvoie automatiquement la date de dernière modification du .qmd
params: # ! `open_params_metadata_help()` pour des instructions de remplissage détaillées
fonction: 3 # Valeur numérique : 0=Non-défini/1=Description/2=Orientation/3=Pilotage
nature: 2 # Valeur numérique : 0=Non-défini/1=Actions/2=Effets/3=Impacts
idThematique: 08.02.05.62 # Identifiant selon nomenclature obsind theme/sous-theme/objet/id (p.ex. 08.03.01)
niveauPublication: 2 # Valeur numérique : 0=Non-défini/1=Interne/2=Public. Tout autre choix génère un avertissement
niveauDetail: Canton # Texte libre qui indique le niveau minimal d'agrégation disponible pour l'indicateur (canton, commune, région, installation, véhicule, etc.)
frequenceMAJ: Annuel # Texte libre, idéalement à choisir parmi les codes suivants : mensuel/semestriel/annuel/biannuel/mensuel/tous les x ans/non-défini
moisMAJ: 9 # Valeur numérique : 0=Non-défini/1=Janvier/2=Février, etc.
disponibleDepuis: 2015 # Valeur numérique Année (aaaa) (p.ex. 2000)
personneReference: Steve Ducommun # Prénom+Nom de la personne référente de l'indicateur
mailReference: stat.energie@vd.ch # E-mail ACV (générique ou nominal, se terminant par @vd.ch)
uuid: d9c347b1-ec46-4c03-96a6-7aeb153da7a8 # !NE PAS MODIFIER! Identifiant unique généré automatiquement à la création de la fiche
uuidParent: null # Identifiant(s) unique(s) des indicateurs parents de l'indicateur actuel (format uuid avec séparateur '/' si plusieurs uuid)
uuidEnfant: null # Identifiant(s) unique(s) des indicateurs enfants de l'indicateur actuel (format uuid avec séparateur '/' si plusieurs uuid)
uuidConnexe: null # Identifiant(s) unique(s) des indicateurs connexes à l'indicateur actuel (format uuid avec séparateur '/' si plusieurs uuid)
majCatalogue: 1 # Valeur numérique : 0=Non/1=Oui pour mettre à jour les métadonnées dans le catalogue des indicateurs (connexion au disque partagé ObsInd requise)
format:
html:
other-links: # Copier la structure ci-dessous pour remplacer/ajouter d'autres liens sous la table des matières
- text: Infos statistiques énergie
href: 'https://www.vd.ch/environnement/energie/chiffres-cles-et-statistiques-energie-vaud/'
target: '_blank'
- text: Profil climatique communes
href: 'https://stat-climat-vd.ch/profil-climat/'
target: '_blank'
- text: Direction de l'énergie
href: 'https://www.vd.ch/djes/dge/dge-diren'
target: '_blank'
metadata-files: # Ne pas supprimer !
- assets/format-options.yml
editor_options:
chunk_output_type: console
---
<!-- Les métadonnées ci-dessus doivent être remplies pour chaque fiche. Lorsqu'un champ n'est disponible, il est possible d'écrire "" ou NULL -->
<!-- Aide au remplissage : `obsindVD::open_aide_remplissage_help()` (lancer la ligne de code dans la console) -->
```{r setup}
#| echo: false
#| warning: false
#| message: false
#| results: asis
# version: 1.2.2 (01.09.2026)
# -----------------------------------------------------------------------------
# Ne rien modifier dans ce bloc de code !
# Ce bloc doit être lancé pour charger les métadonnées dans l'environnement !
# -----------------------------------------------------------------------------
# update_model_setup_code() pour mettre à jour ce bloc avec la version du dernier modèle
# Chargement (ou installation) des librairies disponibles sur CRAN
if (!require("pacman")) install.packages("pacman")
pacman::p_load(tidyverse, readxl, glue, gt, DT, ggiraph, scales, ggtext)
# Chargement de la librairie obsindVD privée
# Pour l'installation : suivre les instructions dans le BitBucket : https://dsigit.etat-de-vaud.ch/outils/git/projects/DGE/repos/obsind/
# Si l'accès n'est pas autorisé, faire une demande à l'Observatoire des indicateurs
library(obsindVD)
# Par défaut : ouvrir l'aide obsindVD (supprimer cette ligne si superflu)
open_fiche_quarto_help()
# Vérifie, ajoute et insère des valeurs par défaut pour les métadonnées manquantes (en-tête YAML)
complete_metadata_params()
# Extraction + validation des métadonnées (en-tête YAML)
selected_metadata <- return_selected_metadata()
# Ajout de l'identifiant dans les en-têtes du document html
display_identifiant(value = selected_metadata[['Identifiant thématique']])
```
::: {.callout-tip .narrow icon="false" collapse="true"}
# Métadonnées de l'indicateur
```{r}
# --------------------------------------
# Présentation des métadonnées ----
# --------------------------------------
tidyr::tibble(
`Attribut` = names(selected_metadata),
`Valeur` = selected_metadata
) |>
gt_table_ind()
```
:::
```{r}
# Préciser quelle est l'année maximale recherchée (permet d'automatiser la recherche du bon dossier et fichier pour les données PRONOVO)
an_max <- 2025
```
```{r}
# ---------------------------------------------------------
# Tableau de synthèse ----
# ---------------------------------------------------------
# Pour de l'aide sur comment remplir ce tableau de synthèse lancer la commande suivante dans la console :
# obsindVD::open_tableau_synthese_help()
# Pour afficher l'aide spécifique à une fonction, ajouter '?' avant l'appel de la fonction :
# ?icon_up()
tableau_synthese <- list(
# Premier indicateur... attention à la structure !
list(
titre_indicateur = "Production thermique à partir de la chaleur ambiante, Vaud <b>[GWh]</b>",
valeur_2025 = 1674,
obj_2030 = 1100, # valeur numérique OU icônes de flèches
obj_2040 = NA,
obj_2050 = 1600,
tendance_observée = icon_up(type = "trend", text = paste0("2019-", an_max)), # icon_up(), icon_flat(), icon_down()
tendance_évaluée = icon_happy() # icon_happy(), icon_meh(), icon_sad()
),
# Second indicateur... Répliquer la même structure autant de fois que d'indicateurs à afficher dans le tableau de synthèse
list(
titre_indicateur = "Production thermique extraite de l'environnement, Vaud <b>[GWh]</b>",
valeur_2025 = 1175,
obj_2030 = 810, # valeur numérique OU icônes de flèches
obj_2040 = NA, #icon_up(type = "obj"), # On peut modifier 'Cible non chiffrée' en modifiant l'argument text = "" par exemple pour ne rien afficher
obj_2050 = 1170,
tendance_observée = icon_up(type = "trend", text = paste0("2019-", an_max)), # text obligatoire pour type = 'trend'
tendance_évaluée = icon_happy() # (tooltip = "Exemple d'info-bulle personnalisé") # 'tooltip' modifie l'info-bulle par défaut
)
)
# Impression du tableau de synthèse
print_tableau_synthese(tableau_synthese) # Le résultat peut être customisé comme un objet {gt}
```
# Description {#sec-description}
Cet indicateur informe sur la quantité totale d’énergie thermique produite annuellement à partir de pompes à chaleur (PAC) installées sur le territoire vaudois. Il traduit l’évolution de la production locale de chaleur obtenue à partir de la valorisation de la chaleur ambiante de l’environnement (air, eau ou sol).
# Cadre de référence {#sec-cadre-reference}
Les objectifs de la production d’énergie thermique à partir de la chaleur ambiante sont définis dans la Conception cantonale de l’énergie ([CoCEn 2019](https://www.vd.ch/fileadmin/user_upload/themes/environnement/energie/fichiers_pdf/CoCEn_Pub_complete_20190816.pdf)). L’objectif est d’atteindre une production thermique totale de 1100 GWh<sub>th</sub> par an dès 2030, correspondant à 810 GWh<sub>th</sub> de chaleur extraite de l’environnement (après déduction de l’électricité nécessaire pour le fonctionnement des PAC). Pour 2050, l’objectif est de produire chaque année un total de 1600 GWh<sub>th</sub> à partir de la chaleur ambiante, dont 1'170 GWh<sub>th</sub> de chaleur extraite de l’environnement.
# Graphique {#sec-graphique}
```{r}
# Lecture des données
#--------------------------------------------------------------------------
# 1 - Données de production
#Les données du document data_brut.xlsx doit avoir été préparé
# setwd("P:/DIREN/11 POLITIQUE ENERG/11.08 Indicateurs et stat/1 Indicateurs DIREN/3-Fiches IND MET OBJ/INDicateur/Documents de travail - Quarto/Premières versions test/IND_08.01.03.02_Consommation_Batiments_Renouvelables")
data_brut_read <- readxl::read_excel(("./data/data_brut.xlsx"),
sheet = "data_final")
data_long <- data_brut_read |>
pivot_longer(
cols = -1, # toutes les colonnes sauf la 1ère
names_to = "ANNEE",
values_to = "VALEUR"
)
# ---------------------------------------------------------
# 2 - Objectifs CoCEn
# A créer une fois
# # obj_tot : objectifs de production totale à partir de PAC
# obj_tot <- tibble(
# ANNEE = c(2030, 2050),
# GWH = c(1100, 1600)
# )
# write_delim(obj_tot,"./data/obj_tot.csv", delim = ";")
# # obj_environnement : objectifs de chaleur extraite de l'environnement
# obj_environnement <- tibble(
# ANNEE = c(2030, 2050),
# GWH = c(810, 1170)
# )
# write_delim(obj_environnement,"./data/obj_environnement.csv", delim = ";")
# # obj_elec : objectifs de consommation d'électricité pour les PAC
# obj_elec <- tibble(
# ANNEE = c(2030, 2050),
# GWH = c(290, 430)
# )
# write_delim(obj_elec,"./data/obj_elec.csv", delim = ";")
obj_tot <- read_delim("./data/obj_tot.csv", delim = ";")
obj_environnement <- read_delim("./data/obj_environnement.csv", delim = ";")
obj_elec <- read_delim("./data/obj_elec.csv", delim = ";")
# ---------------------------------------------------------
# 4 - Population
# Variables sont : ANNEE et HABITANTS
tryCatch(
expr = {
read_delim("P:/DIREN/02 PILOTAGE DIREN/02.11 Bases de donnees/POPULATION/04_extractions_traitees/population.csv", delim=";") |>
write_delim("./data/population.csv", delim = ";")
},
error = function(e) message("Attention: la table population n'a pas pu être réactualisée avec les données brutes du P:/ ", e$message)
)
population <- read_delim("./data/population.csv", delim = ";") |>
filter(ANNEE >= 2015 & ANNEE <= an_max)
```
```{r }
#| label: fig-G1
##| fig-cap: Production thermique à partir de la chaleur ambiante, Vaud
#| fig.width: 8
#| fig.asp: 0.6
# créer data ressources (enlever total et années avec objectifs)
ressources <- data_long |>
# ne garder que Chaleur extraite de l'environnement et Electricité
filter(VARIABLES %in% c("chaleur_environnement", "conso_elec")) |>
rename(GWH = VALEUR) |>
mutate(ANNEE = as.numeric(ANNEE))
# Uniquement total pour valeur txt dans graphique
production_total <- data_long |>
filter(VARIABLES %in% c("prod_tot"))|>
rename(GWH = VALEUR) |>
mutate(ANNEE = as.numeric(ANNEE))
# créer data objectifs (uniquement objectifs des totaux)
objectifs <- obj_tot |>
mutate(ANNEE = as.numeric(ANNEE))
# Ajouter un trou pour séparer les consommations des objectifs
last_year <- max(ressources$ANNEE, na.rm = TRUE)
gap1 <- last_year + 1 # entre dernière année et 2030
gap2 <- 2030 + 1 # entre 2030 et 2050
annees_hist <- sort(unique(ressources$ANNEE))
annees_levels <- c(
annees_hist,
gap1,
2030,
gap2,
2050
)
# Ajout les trous à chaque dataset
add_missing_years_prod <- function(df) {
df |>
tidyr::complete(
ANNEE = annees_levels,
VARIABLES
)
}
add_missing_years_simple <- function(df) {
df |>
tidyr::complete(
ANNEE = annees_levels
)
}
ressources <- add_missing_years_prod(ressources)
#|>
# mutate(GWH = tidyr::replace_na(GWH, 0))
objectifs <- add_missing_years_simple(objectifs)
# ordrer les ressources selon la quantité
ordre_type <- ressources |>
filter(ANNEE == last_year) |>
arrange(GWH) |>
pull(VARIABLES)
tous_les_types <- c(
"chaleur_environnement",
"conso_elec",
"Objectifs CoCEn 2019"
)
annees_labels <- as.character(annees_levels)
ressources <- ressources |>
mutate(
ANNEE = factor(as.character(ANNEE), levels = annees_labels),
VARIABLES = factor(as.character(VARIABLES), levels = tous_les_types),
GWH = as.numeric(tidyr::replace_na(GWH, 0))
)
objectifs <- objectifs |>
mutate(
ANNEE = factor(as.character(ANNEE), levels = annees_labels),
VARIABLES = factor("Objectifs CoCEn 2019", levels = tous_les_types),
GWH = as.numeric(tidyr::replace_na(GWH, 0))
)
production_total <- production_total |>
mutate(
ANNEE = factor(as.character(ANNEE), levels = annees_labels),
VARIABLES = factor(as.character(VARIABLES), levels = tous_les_types),
GWH = as.numeric(tidyr::replace_na(GWH, 0))
)
labels_vars <- c(
"conso_elec" = "Electricité consommée pour le fonctionnement des PAC",
"chaleur_environnement" = "Chaleur extraite de l'environnement",
"Objectifs CoCEn 2019" = "Objectifs CoCEn de production thermique en"
)
g1_plot <- ggplot() +
# Bars (objectives )
geom_col_interactive(
data = objectifs,
aes(x = ANNEE, y = GWH, fill = VARIABLES, group = VARIABLES,
tooltip = paste0(labels_vars[as.character(VARIABLES)], " ", ANNEE, " : ", round(GWH, 0), " GWh"),
data_id = as.character(ANNEE)),
width = 0.7,
position = "stack",
color = NA
) +
geom_col_interactive(
data = ressources,
aes(
x = ANNEE,
y = GWH,
fill = VARIABLES,
group = VARIABLES,
tooltip =paste0(labels_vars[as.character(VARIABLES)], " ", ANNEE, " : ", round(GWH, 0), " GWh"),
data_id = paste0(as.character(ANNEE), as.character(VARIABLES))),
width = 0.7,
position = "stack",
color = NA
) +
# ajout des valeurs total au-dessus des colonnes
geom_text(
data = production_total |>
bind_rows(objectifs) |> # ajout des objectifs au cas où
filter(!is.na(GWH) & GWH != 0),
inherit.aes = FALSE,
aes(
x = as.factor(ANNEE),
y = GWH,
label = label_number(accuracy = 1, big.mark = "'")(GWH)
),
vjust = -0.5,
size = 3
) +
scale_fill_manual(
values = c(
"Objectifs CoCEn 2019" = "grey80",
"conso_elec" ="yellow2",
"chaleur_environnement" ="orange"
),
breaks = tous_les_types,
labels = c(
"Objectifs CoCEn 2019" = "Objectifs CoCEn 2019",
"conso_elec" = "Consommation électrique des PAC",
"chaleur_environnement" = "Chaleur extraite de l'environnement"
),
name = NULL
) +
scale_y_continuous(
name = "Production thermique [GWh]",
labels = scales::label_number(big.mark = "'", decimal.mark = "."),
expand = expansion(mult = c(0, 0.1))
) +
scale_x_discrete(
drop = FALSE,
labels = function(x) {
num_x <- as.numeric(as.character(x))
ifelse(
num_x %in% c(gap1, gap2),
"", # cacher les gaps
ifelse(num_x %% 5 == 0, num_x, "") # afficher seulement tous les 5 ans
)
}
)+
guides(
fill = guide_legend(nrow = 2, byrow = FALSE) # légendes sur 2 lignes d'un histogramme
#color = guide_legend(nrow = 1, byrow = FALSE) # légendes sur 2 lignes d'un graphique en ligne
)+
# Titles and caption
labs(
title = str_wrap("**Production thermique à partir de la chaleur ambiante**", width = 73) |>
stringr::str_replace_all("\n", "<br>") ,
subtitle = str_wrap("Chaleur extraite de l'environnement et consommation électrique des pompes à chaleur (PAC), Vaud", width = 73) |>
stringr::str_replace_all("\n", "<br>") ,
x = NULL,
caption = "Source: DGE-DIREN<br>Etat au 18.08.2025"
) +
theme_minimal(base_size = 13) +
theme(
plot.title = element_markdown(face = "bold", size = 12),
plot.subtitle = element_markdown(size = 10),
plot.caption = element_markdown(hjust = 0, size = 9, margin = margin(t = 5), face = "italic"), # !! MWR: rajout italic
plot.caption.position = "plot",
plot.margin = margin(10, 10, 30, 10),
legend.position = "bottom",
legend.box = "vertical",
legend.text = element_text(size = 10),
legend.title = element_text(size = 12),
axis.text = element_text(size = 8),
axis.title = element_text(size = 10)
)
obsindVD::girafe_light(g1_plot,
# !!MWR : modification du comportement de surlignage : on ajoute de la transparence aux éléments non-survolés !
options = list(
opts_hover_inv(css = "opacity:0.5;"),
opts_hover(css = "opacity:1;"),
# Ajout du nom du PNG téléchargé + remplacement de 'download' par 'télécharger' (survol icône)
opts_toolbar(
position = "topright",
hidden = c("zoom", "selection"),
pngname = paste0(selected_metadata[['Identifiant thématique']], "_G1"),
tooltips = list(
saveaspng = "Télécharger"
)
)
)
)
ggsave(glue("./images/g1_Production_thermique_chaleur_ambiante_sources_2015-{an_max}.png"), width = 8, height = 6, dpi = 300)
```
```{r}
#| label: fig-G2
##| fig-cap: "Production thermique à partir de la chaleur ambiante par type de pompe à chaleur, Vaud"
#| fig.width: 8
#| fig.asp: 0.6
# créer data ressources (enlever total et années avec objectifs)
ressources <- data_long |>
# ne garder que Chaleur extraite de l'environnement et Electricité
filter(VARIABLES %in% c("prod_cad", "prod_eau_eau", "prod_sol_eau", "prod_air_eau")) |>
rename(GWH = VALEUR) |>
mutate(ANNEE = as.numeric(ANNEE))
# ordrer les ressources selon la quantité
ordre_type <- ressources |>
filter(ANNEE == last_year) |>
arrange(GWH) |>
pull(VARIABLES)
# annees_labels <- as.character(annees_levels)
ressources <- ressources |>
mutate(
ANNEE = factor(as.character(ANNEE)), #, levels = annees_labels),
VARIABLES = factor(as.character(VARIABLES), levels = ordre_type),
GWH = as.numeric(tidyr::replace_na(GWH, 0))
)
labels_pac <- c(
"prod_cad" ="PAC eau-eau (CAD)",
"prod_eau_eau" ="PAC eau-eau (hors CAD)",
"prod_sol_eau" = "PAC sol-eau",
"prod_air_eau" = "PAC air-eau"
)
g2_plot <- ggplot() +
geom_col_interactive(
data = ressources,
aes(
x = ANNEE,
y = GWH,
fill = VARIABLES,
tooltip =paste0("Production de chaleur par ", labels_pac[as.character(VARIABLES)], " ", ANNEE, " : ", round(GWH, 0), " GWh"),
data_id = paste0(as.character(ANNEE), as.character(VARIABLES))),
width = 0.7,
position = "stack",
color = NA
) +
# ajout des valeurs total au-dessus des colonnes
geom_text(
data = production_total,
# bind_rows(objectifs) |> # ajout des objectifs au cas où
# filter(!is.na(GWH) & GWH != 0),
# inherit.aes = FALSE,
aes(
x = as.factor(ANNEE),
y = GWH,
label = label_number(accuracy = 1, big.mark = "'")(GWH)
),
vjust = -0.5,
size = 3
) +
scale_fill_manual(
values = c(
"prod_cad" ="#08519c",
"prod_eau_eau" ="#6baed6",
"prod_sol_eau" = "#238b45",
"prod_air_eau" = "#fb9a99"
),
# breaks = ordre_type,
labels = c(
"prod_cad" ="PAC eau-eau (CAD)",
"prod_eau_eau" ="PAC eau-eau (hors CAD)",
"prod_sol_eau" = "PAC sol-eau",
"prod_air_eau" = "PAC air-eau"
),
name = NULL
) +
scale_y_continuous(
name = "Production thermique [GWh]",
labels = scales::label_number(big.mark = "'", decimal.mark = "."),
expand = expansion(mult = c(0, 0.1))
) +
scale_x_discrete(
limits = levels(ressources$ANNEE),
drop = FALSE,
labels = function(x) {
num_x <- as.numeric(as.character(x))
ifelse(
num_x %in% c(gap1, gap2),
"", # cacher les gaps
ifelse(num_x %% 5 == 0, num_x, "") # afficher seulement tous les 5 ans
)
}
)+
guides(
fill = guide_legend(nrow = 2, byrow = FALSE) # légendes sur 2 lignes d'un histogramme
)+
# Titles and caption
labs(
title = str_wrap("**Production thermique à partir de la chaleur ambiante**", width = 73) |>
stringr::str_replace_all("\n", "<br>") ,
subtitle = str_wrap("Selon le type de pompe à chaleur (PAC), Vaud", width = 73) |>
stringr::str_replace_all("\n", "<br>") ,
x = NULL,
caption = "Source: DGE-DIREN<br>Etat au 18.08.2026"
) +
theme_minimal(base_size = 13) +
theme(
plot.title = element_markdown(face = "bold", size = 12),
plot.subtitle = element_markdown(size = 10),
plot.caption = element_markdown(hjust = 0, size = 9, margin = margin(t = 5), face = "italic"), # !! MWR: rajout italic
plot.caption.position = "plot",
plot.margin = margin(10, 10, 30, 10),
legend.position = "bottom",
legend.box = "vertical",
legend.text = element_text(size = 10),
legend.title = element_text(size = 12),
axis.text = element_text(size = 8),
axis.title = element_text(size = 10)
)
obsindVD::girafe_light(g2_plot,
# !!MWR : modification du comportement de surlignage : on ajoute de la transparence aux éléments non-survolés !
options = list(
opts_hover_inv(css = "opacity:0.5;"),
opts_hover(css = "opacity:1;"),
# Ajout du nom du PNG téléchargé + remplacement de 'download' par 'télécharger' (survol icône)
opts_toolbar(
position = "topright",
hidden = c("zoom", "selection"),
pngname = paste0(selected_metadata[['Identifiant thématique']], "_G2"),
tooltips = list(
saveaspng = "Télécharger"
)
)
)
)
ggsave(glue("./images/g2_Production_thermique_chaleur ambiante_type_PAC_2015-{an_max}.png"), width = 8, height = 6, dpi = 300)
```
# Analyse {#sec-analyse}
<!-- Aide au remplissage : consulter la section correspondante avec `obsindVD::open_aide_remplissage_help()` -->
## Description statistique {#sec-analyse-description}
La production d’énergie thermique issue de la chaleur ambiante sur le territoire vaudois s’élevait à 1'674 GWh<sub>th</sub> en 2025. En hausse constante depuis 2019, elle a progressé de 15 % par an en moyenne (voir @fig-G1). Cette production annuelle dépasse déjà les objectifs de 1'600 GWh<sub>th</sub> qui avaient été fixés pour 2050. Pour produire les 1’674 GWh<sub>th</sub> en 2025, une consommation électrique de 499 GWh<sub>él</sub> a été nécessaire pour alimenter les pompes à chaleur (PAC). La chaleur extraite de l’environnement correspond ainsi à 1'175 GWh<sub>th</sub> (production thermique à laquelle a été soustraite la consommation électrique).
La production thermique des PAC air-eau a plus que quadruplé entre 2015 et 2025 pour atteindre une production annuelle de 1'155 GWh<sub>th</sub> en 2025 (69% du total; voir @fig-G2). La production thermique des PAC sol-eau représente un peu moins de 30% du total, celle des PAC eau-eau (CAD) 2% et celle des PAC eau-eau (hors CAD) moins de 1% (voir @tbl-T2).
## Interprétation {#sec-analyse-interpretation}
La tendance est qualifiée de bonne : la production de 2025 dépasse déjà les objectifs de 2050.
## Périmètre et limites {#sec-analyse-perimetre}
La production d’énergie thermique à partir de la chaleur ambiante est estimée en se basant sur certaines hypothèses (voir la section @sec-methode). Il est par conséquent nécessaire d’interpréter avec prudence les résultats obtenus.
# Tableaux {#sec-tableaux}
<!-- Aide au remplissage : consulter la section correspondante avec `obsindVD::open_aide_remplissage_help()` -->
```{r}
#| label: tbl-T1
##| tbl-cap: "Production thermique à partir de la chaleur ambiante: total et par habitant, Vaud"
# Prod_tot_tab
prod_tot_temp <- data_long |>
# ne garder que le total
filter(VARIABLES == "prod_tot") |>
rename(GWH = VALEUR) |>
mutate(ANNEE = as.numeric(ANNEE))
obj_tot_temp <- obj_tot |>
mutate(VARIABLES = "prod_tot")
prod_tot_tab <- prod_tot_temp |>
bind_rows(obj_tot_temp) |>
mutate(GWH_TOT = GWH) |>
select(ANNEE, GWH_TOT)
# Prod_environnement_tab
prod_environnement_temp <- data_long |>
# ne garder que la chaleur extraite de l'environnement
filter(VARIABLES == "chaleur_environnement") |>
rename(GWH = VALEUR) |>
mutate(ANNEE = as.numeric(ANNEE))
obj_environnement_temp <- obj_environnement |>
mutate(VARIABLES = "chaleur_environnement")
prod_environnement_tab <- prod_environnement_temp |>
bind_rows(obj_environnement_temp) |>
mutate(GWH_ENVIRONNEMENT = GWH) |>
select(ANNEE, GWH_ENVIRONNEMENT)
# conso_elec_tab
conso_elec_temp <- data_long |>
# ne garder que la chaleur extraite de l'environnement
filter(VARIABLES == "conso_elec") |>
rename(GWH = VALEUR) |>
mutate(ANNEE = as.numeric(ANNEE))
obj_elec_temp <- obj_elec |>
mutate(VARIABLES = "conso_elec") |>
mutate(GWH = GWH_TOT) |>
select(-GWH_TOT)
conso_elec_tab <- conso_elec_temp |>
bind_rows(obj_elec_temp) |>
mutate(GWH_ELEC = GWH) |>
select(ANNEE, GWH_ELEC)
# Données de production par habitantpopulation
prod_hab <- prod_tot_temp |>
left_join(population, by = "ANNEE") |>
mutate(KWH_HAB = (GWH*1e6) / HABITANTS) |>
select(ANNEE, KWH_HAB)
df <- prod_tot_tab |>
left_join(prod_environnement_tab, by = "ANNEE") |>
left_join(conso_elec_tab, by = "ANNEE") |>
left_join(prod_hab, by = "ANNEE")|>
select(ANNEE, GWH_TOT, GWH_ENVIRONNEMENT, GWH_ELEC, KWH_HAB)
t1 <- df |>
mutate(across(everything(), \(col) na_if(col, y = 0))) |> # !! MWR: on change les 0 en NA comme ça sub_missing() ci-après transforme les 0 et les NA en "-" (par exemple)
gt() |>
tab_header(title = md("**Production thermique à partir de la chaleur ambiante: total et par habitant**"),
subtitle = "Chaleur extraite de l'environnement et consommation électrique des PAC, Vaud") |>
fmt_number(columns = -ANNEE, sep_mark = "'", decimals = 0) |>
cols_label(
ANNEE = "Année",
GWH_TOT = "Total",
GWH_ENVIRONNEMENT = "Chaleur extraite de l'environnement",
GWH_ELEC = "Consommation électrique PAC",
KWH_HAB = "Production thermique par habitant"
) |>
# Regrouper les colonnes avec un seul titre
tab_spanner(label = "Production thermique",
columns = c(GWH_TOT, GWH_ENVIRONNEMENT, GWH_ELEC), level = 1) |>
cols_width(everything() ~ pct(100 / ncol(df))) |>
tab_style(style = cell_text(weight = "bold"),
locations = list(cells_body(columns = c("ANNEE", "GWH_TOT", "KWH_HAB")),
cells_column_labels(columns = c("ANNEE", "GWH_TOT", "GWH_ENVIRONNEMENT", "GWH_ELEC", "KWH_HAB")))) |>
tab_style(
style = cell_text(align = "center"),
locations = cells_column_labels()
) |>
tab_style(
style = cell_text(align = "left"),
locations = cells_column_labels(columns = ANNEE)
) |>
tab_style(
style = cell_text(align = "left"),
locations = list(cells_footnotes(), cells_source_notes())
) |>
tab_style(
style = cell_text(weight = "bold"),
locations = list(cells_column_spanners(), cells_column_labels())) |>
cols_align(align = "center", columns = -ANNEE) |>
cols_align(align = "left", columns = ANNEE) |>
cols_label_with(
columns = -c(ANNEE, KWH_HAB),
fn = \(col) md(paste0(col, "\n\n[GWh]"))
) |>
cols_label_with(
columns = c(KWH_HAB),
fn = \(col) md(paste0(col, "\n\n[kWh / hab]"))
) |>
tab_style(style = cell_borders(sides = "all"),
locations = list(cells_column_labels(), cells_column_spanners())) |>
tab_style(style = cell_borders(sides = c("left", "right")),
locations = list(cells_body())) |>
tab_options(column_labels.border.bottom.color = "black") |>
fmt_missing(columns = everything(), missing_text = "-") |>
tab_footnote(footnote = "Objectifs de la Conception cantonale de l'énergie (CoCEn 2019).",
locations = cells_body(columns = ANNEE, rows = ANNEE > year(Sys.Date())),
placement = "right") |>
tab_footnote(footnote = "Production thermique (PAC) : quantité totale de chaleur produite par les pompes à chaleur sur une période donnée.",
locations = cells_column_labels(columns = GWH_TOT),
placement = "right") |>
tab_footnote(footnote = "Chaleur extraite de l’environnement : part de la chaleur produite par la PAC provenant des ressources naturelles (air, sol ou eau). .",
locations = cells_column_labels(columns = GWH_ENVIRONNEMENT),
placement = "right") |>
tab_footnote(footnote = "Consommation électrique des PAC : quantité d’électricité utilisée par les pompes à chaleur pour fonctionner.",
locations = cells_column_labels(columns = GWH_ELEC),
placement = "right") |>
tab_style(
style = cell_borders(sides = "top", style = "dashed", color = "lightgrey", weight = px(1)),
locations = cells_body(rows = ANNEE == min(obj_tot$ANNEE)) # applies to first row
) |>
opt_table_outline(style = "solid", width = px(2), color = "lightgrey") |>
tab_source_note(
source_note = md("*Sources : DGE-DIREN<br>Etat au 18.08.2026*")
)
t1
gtsave(t1, glue("./images/t1_Production_thermique_chaleur_ambiante_sources_2015-{an_max}.html"))
```
```{r}
#| label: tbl-T2
##| tbl-cap: "Production thermique à partir de la chaleur ambiante, selon le type de pompe à chaleur, Vaud"
# Prod_tot_tab
prod_tot <- data_long |>
# ne garder que le total
filter(VARIABLES == "prod_tot") |>
rename(TOT_GWH = VALEUR) |>
mutate(ANNEE = as.numeric(ANNEE))|>
select(ANNEE, TOT_GWH)
# prod_air_eau
prod_air_eau <- data_long |>
# ne garder que les PAC air-eau
filter(VARIABLES == "prod_air_eau") |>
rename(AIR_EAU_GWH = VALEUR) |>
mutate(ANNEE = as.numeric(ANNEE)) |>
left_join(prod_tot, by = "ANNEE") |>
mutate(AIR_EAU_PERC = AIR_EAU_GWH * 100 / TOT_GWH) |>
select(-VARIABLES, -TOT_GWH)
# prod_sol_eau
prod_sol_eau <- data_long |>
# ne garder que les PAC sol-eau
filter(VARIABLES == "prod_sol_eau") |>
rename(SOL_EAU_GWH = VALEUR) |>
mutate(ANNEE = as.numeric(ANNEE)) |>
left_join(prod_tot, by = "ANNEE") |>
mutate(SOL_EAU_PERC = SOL_EAU_GWH * 100 / TOT_GWH) |>
select(-VARIABLES, -TOT_GWH)
# prod_eau_eau (CAD)
prod_cad <- data_long |>
# ne garder que les PAC eau-eau (CAD)
filter(VARIABLES == "prod_cad") |>
rename(CAD_GWH = VALEUR) |>
mutate(ANNEE = as.numeric(ANNEE)) |>
left_join(prod_tot, by = "ANNEE") |>
mutate(CAD_PERC = CAD_GWH * 100 / TOT_GWH) |>
select(-VARIABLES, -TOT_GWH)
# prod_eau_eau (hors CAD)
prod_eau_eau <- data_long |>
# ne garder que les PAC air-eau
filter(VARIABLES == "prod_eau_eau") |>
rename(EAU_EAU_GWH = VALEUR) |>
mutate(ANNEE = as.numeric(ANNEE)) |>
left_join(prod_tot, by = "ANNEE") |>
mutate(EAU_EAU_PERC = EAU_EAU_GWH * 100 / TOT_GWH) |>
select(-VARIABLES, -TOT_GWH)
# Kier es 4 df
df <- prod_tot |>
left_join(prod_air_eau, by = "ANNEE") |>
left_join(prod_sol_eau, by = "ANNEE") |>
left_join(prod_cad, by = "ANNEE")|>
left_join(prod_eau_eau, by = "ANNEE") |>
select(ANNEE, TOT_GWH, AIR_EAU_GWH, AIR_EAU_PERC, SOL_EAU_GWH, SOL_EAU_PERC, CAD_GWH, CAD_PERC, EAU_EAU_GWH, EAU_EAU_PERC)
t2 <- df |>
mutate(across(everything(), \(col) na_if(col, y = 0))) |> # !! MWR: on change les 0 en NA comme ça sub_missing() ci-après transforme les 0 et les NA en "-" (par exemple)
gt() |>
tab_header(title = md("**Production thermique à partir de la chaleur ambiante, selon le type de pompe à chaleur**"),
subtitle = "Chaleur extraite de l'environnement et consommation électrique des PAC, Vaud") |>
fmt_number(
columns = c(TOT_GWH, AIR_EAU_GWH, SOL_EAU_GWH, CAD_GWH, EAU_EAU_GWH),
sep_mark = "'",
decimals = 0
) |>
# % → 1 décimale
fmt_number(
columns = ends_with("_PERC"),
decimals = 1
) |>
cols_label(
ANNEE = "Année",
TOT_GWH = "Total",
AIR_EAU_GWH = "[GWH]",
SOL_EAU_GWH = "[GWH]",
CAD_GWH = "[GWH]",
EAU_EAU_GWH = "[GWH]",
AIR_EAU_PERC = "[%]",
SOL_EAU_PERC = "[%]",
CAD_PERC = "[%]",
EAU_EAU_PERC = "[%]"
) |>
cols_width(everything() ~ pct(100 / ncol(df))) |>
tab_style(style = cell_text(weight = "bold"),
locations = list(cells_body(columns = c("ANNEE", "TOT_GWH", "AIR_EAU_GWH", "SOL_EAU_GWH", "CAD_GWH", "EAU_EAU_GWH")),
cells_column_labels(columns = c("ANNEE", "TOT_GWH", "AIR_EAU_GWH", "SOL_EAU_GWH", "CAD_GWH", "EAU_EAU_GWH")))) |>
# spanners
tab_spanner(label = "PAC air-eau",
columns = c(AIR_EAU_GWH, AIR_EAU_PERC), level = 1) |>
tab_spanner(label = "PAC sol-eau",
columns = c(SOL_EAU_GWH, SOL_EAU_PERC), level = 1) |>
tab_spanner(label = "PAC eau-eau (hors CAD)",
columns = c(EAU_EAU_GWH, EAU_EAU_PERC), level = 1) |>
tab_spanner(label = "PAC eau-eau (CAD)",
columns = c(CAD_GWH, CAD_PERC), level = 1) |>
tab_style(
style = cell_text(align = "center"),
locations = cells_column_labels()
) |>
tab_style(
style = cell_text(align = "left"),
locations = cells_column_labels(columns = ANNEE)
) |>
tab_style(
style = cell_text(align = "left"),
locations = list(cells_footnotes(), cells_source_notes())
) |>
tab_style(
style = cell_text(weight = "bold"),
locations = list(
cells_column_spanners(), cells_column_labels())) |>
cols_align(align = "center", columns = -ANNEE) |>
cols_align(align = "left", columns = ANNEE) |>
cols_label_with(
columns = c(TOT_GWH),
fn = \(col) md(paste0(col, "\n\n[GWh]"))
) |>
# cols_label_with(
# columns = c(AIR_EAU_PERC, SOL_EAU_PERC, CAD_PERC, EAU_EAU_PERC),
# fn = \(col) md(paste0(col, "\n\n[%]"))
# ) |>
tab_style(style = cell_borders(sides = "all"),
locations = list(cells_column_labels(), cells_column_spanners())) |>
tab_style(style = cell_borders(sides = c("left", "right")),
locations = list(cells_body())) |>
tab_options(column_labels.border.bottom.color = "black") |>
fmt_missing(columns = everything(), missing_text = "") |>
tab_style(
style = cell_borders(sides = "top", style = "dashed", color = "lightgrey", weight = px(1)),
locations = cells_body(rows = ANNEE == min(obj_tot$ANNEE)) # applies to first row
) |>
opt_table_outline(style = "solid", width = px(2), color = "lightgrey") |>
tab_source_note(
source_note = md("*Sources : DGE-DIREN<br>Etat au 18.08.2026*")
)
t2
gtsave(t2, glue("./images/t2_Production_thermique_chaleur_ambiante_type_PAC_2015-{an_max}.html"))
```
# Méthode {#sec-methode}
La production d’énergie thermique issue de la chaleur ambiante est estimée pour chaque type de pompe à chaleur (PAC) : air-eau, sol-eau et eau-eau. Ces estimations reposent sur plusieurs éléments, notamment :
* le nombre d'annonces de forages réalisés,
* le nombre d’autorisations délivrées pour les forages,
* la production thermique moyenne théorique de chaque type de PAC,
* la répartition estimée des différents types de PAC installées,
* ainsi que leur coefficient de performance (COP) moyen.
Pour les PAC eau-eau, une différentiation est effectuée entre ceux alimentant un chauffageà distance (CAD) et les autres. Les quantités de chaleur produites par ces derniers sont estimées, alors que celles produites par des CAD proviennent du relevé exhaustif auprès de tous les réseaux thermiques du canton de Vaud.
Les performances énergétiques varient selon les types de pompes à chaleur. Le coefficient de performance (COP) permet de mesurer leur efficacité : il exprime la quantité de chaleur produite par rapport à l’électricité consommée. Plus le COP est élevé, plus la pompe à chaleur est performante, car elle valorise davantage les ressources naturelles pour produire de la chaleur.
* Une PAC air-eau a un COP d’environ 3 : pour 1 unité d’électricité consommée, elle restitue environ 3 unités de chaleur en exploitant l’énergie contenue dans l’air extérieur.
* Une PAC sol-eau (géothermie entre 50 et 300 m) présente un COP d’environ 4,5.
* Une PAC eau-eau (utilisant l’eau des lacs, rivières ou nappes phréatiques) atteint un COP d’environ 5.
L’ensemble de la méthodologie et le détail des calculs utilisés pour ces estimations sont présentés dans une fiche dédiée (voir @sec-ref-fiches).
# Comparaison {#sec-comparaison}
Aucune comparaison n'a été effectuée avec la situation dans d'autres cantons ou au niveau fédéral.
# Références {#sec-ref}
<!-- Aide au remplissage : consulter la section correspondante avec `obsindVD::open_aide_remplissage_help()` -->
## Fiches associées {#sec-ref-fiches}
**Fiches Méthode** :
* MET_8.02.05.62 : Méthode pour le calcul de la production thermique par la chaleur ambiante (*disponible sur demande*)
**Fiches Indicateur** :
* [IND_08.02.03.02 : Production thermique de sources renouvelables, Vaud](https://stat-climat-vd.ch/fiches-indicateurs/themes/energie/IND_08.02.03.02_Production_Thermique_Renouvelable.html)
## Autres références {#sec-ref-autres}
* [DGE-DIREN - Conception cantonale de l’énergie (CoCEn 2019)](https://www.vd.ch/fileadmin/user_upload/themes/environnement/energie/fichiers_pdf/CoCEn_Pub_complete_20190816.pdf)
# Glossaire {#sec-glossaire}
```{r}
# ---------------------------------------------------------
# Bloc pour lecture du file BRUT où se trouvent toutes les définition pour le glossaire et création du data.frame "definition" ----
# ---------------------------------------------------------
tryCatch(
expr = {readxl::read_excel("P:/DIREN/11 POLITIQUE ENERG/11.08 Indicateurs et stat/1 Indicateurs DIREN/3-Fiches IND MET OBJ/Liste Definitions.xlsx",
skip = 2) |>
janitor::clean_names(case="screaming_snake") |>
select(TERME, DEFINITION) |>
readr::write_csv2("./data/definitions.csv")
},
error = function(e) message("Attention: la table définition n'a pas pu être réactualisée avec les données brutes du P:/ ", e$message),
warning = function(w) message("Attention: la table définition n'a pas pu être réactualisée avec les données brutes du P:/ ", w$message)
)
```
```{r}
# ---------------------------------------------------------
# Bloc pour sélectionner les définitions à apparaître dans le glossaire ----
# ---------------------------------------------------------
# Lecture du file
def_tot <- readr::read_delim(file = "./data/definitions.csv",
delim = ";",
show_col_types = FALSE) |>
# Mettre les premières lettres de chaque définition en majuscule
dplyr::mutate(DEFINITION = stringr::str_replace(DEFINITION,"^\\p{L}",stringr::str_to_upper))
# Sélection des définitions
definitions <- def_tot |>
filter(TERME %in% c(
"Gigawattheure (GWh)",
"Coefficient de performance (COP)"
))
# Print de la table avec modification des columns
definitions |>
gt_table_ind() |>
gt::cols_label(TERME = "", DEFINITION ="Définition") |>
gt::tab_options(table.align = "left")
```
# Annexes {#sec-annexes .unnumbered}
<!-- Aide au remplissage : consulter la section correspondante avec `obsindVD::open_aide_remplissage_help()` -->