Ce document a été généré avec l’outil R Markdown. Le code R et les données qui ont été utilisées sont ainsi mis à disposition et permettent donc la reproductibilité des résultats obtenus.
Par ailleurs, le document est mis à jour automatiquement chaque jour. Pour consulter les archives, cliquer ici.
Source de données utilisées:
Données hospitalières relatives à l’épidémie de COVID-19 : https://www.data.gouv.fr/fr/datasets/donnees-hospitalieres-relatives-a-lepidemie-de-covid-19/
Données relatives aux résultats des tests virologiques COVID-19 : https://www.data.gouv.fr/fr/datasets/donnees-relatives-aux-resultats-des-tests-virologiques-covid-19/
Questions de recherche:
Peut-on expliquer le nombre de nouvelles entrées par semaine en fonction du nombre de personnes testées positives quelques jours auparavant ?
Peut-on expliquer les entrées en réanimation par les entrées en hospitalisations ?
Peut-on expliquer les nouveaux décès par les entrées réanimations ?
En fonction des réponses aux questions précédentes :
Packages et fonctions locales à charger:
library(cartogram)
library(cartography)
## Warning in fun(libname, pkgname): rgeos: versions of GEOS runtime 3.9.0-CAPI-1.16.2
## and GEOS at installation 3.8.0-CAPI-1.13.1differ
library(forecast)
library(kableExtra)
library(rgdal)
library(tidyverse)
library(vistime)
library(zoo)
source("fonctions.R")
Version de R utilisée:
R.version
## _
## platform x86_64-pc-linux-gnu
## arch x86_64
## os linux-gnu
## system x86_64, linux-gnu
## status
## major 4
## minor 0.4
## year 2021
## month 02
## day 15
## svn rev 80002
## language R
## version.string R version 4.0.4 (2021-02-15)
## nickname Lost Library Book
Dans un premier temps, on met à jour les données tous les jours de façon automatique.
# Date du jour pour actualiser les données:
<- Sys.Date()
to_day <- "https://www.data.gouv.fr/fr/datasets/r/6fadff46-9efd-4c53-942a-54aca783c30c"
my_url if (!file.exists(paste0(getwd(), "/data/", to_day, ".csv"))) {
download.file(my_url, destfile = paste0(getwd(), "/data/", to_day, ".csv"))
}<- read.csv(paste0(getwd(), "/data/", to_day, ".csv"), sep = ";")
hospital # On ajoute le nom des régions:
<- merge(hospital, dep_region, by = "dep")
hospital # On utilise le format date pour coder le jour:
$jour <- as.Date(hospital$jour) hospital
Comment se présente les données du Ministère de la Santé ?
<- hospital[hospital$dep == "69" & hospital$jour > to_day - 5, ]
temp ::kbl(temp) kableExtra
dep | jour | incid_hosp | incid_rea | incid_dc | incid_rad | nom_dep | region | |
---|---|---|---|---|---|---|---|---|
24969 | 69 | 2021-03-12 | 50 | 6 | 7 | 40 | Rhône | Auvergne-Rhône-Alpes |
25030 | 69 | 2021-03-13 | 28 | 6 | 4 | 15 | Rhône | Auvergne-Rhône-Alpes |
25070 | 69 | 2021-03-11 | 44 | 15 | 4 | 24 | Rhône | Auvergne-Rhône-Alpes |
25131 | 69 | 2021-03-14 | 6 | 1 | 3 | 7 | Rhône | Auvergne-Rhône-Alpes |
Ici il s’agit des données qui donnent chaque jour par département :
On créé des fenêtres de 7 jour à partir du dernier jour observé. Par exemple si nous avons les données d’hospitalisation jusqu’au 14 mars 2021 la semaine qui correspond à la semaine t0 correspond à la fenêtre [08 mars 2021; 14 mars 2021]. Dans chaque fenêtre, on calcule le nombre de nouvelles hospitalisations, réanimations et décès par département.
$semaine <- num_semaine(hospital$jour)
hospital# On aggrège les données en fonction de cette fenêtre et on garde tous les départements:
<- hospital %>%
my_basis group_by(dep, semaine) %>%
::summarize(hosp = sum(incid_hosp),
dplyrrea = sum(incid_rea),
rad = sum(incid_rad),
dc = sum(incid_dc),
jour = max(jour),
region = unique(region))
<- data.frame(event = c("Semaine t0", "Semaine t1", "Semaine t2", "Semaine t3"),
timeline_data start = c(to_day - 8, to_day - 15, to_day - 22, to_day - 29),
end = c(to_day - 1, to_day - 8, to_day - 15, to_day - 22), group = "temps")
vistime(timeline_data)
On dispose égaglement des données d’hospitalisations/réanimations/décès par classe d’âge à la différence qu’il s’agit de données régionales et qu’il s’agit des données de stock (nombre d’hospitalisations et réanimations en cours) et pas du nombre de nouvelles hospitalisations. On peut toutefois estimer le nombre de nouvelles hospitalisations ou décès en faisant les différences des valeurs d’un jour sur l’autre.
<- "https://www.data.gouv.fr/fr/datasets/r/08c18e08-6780-452d-9b8c-ae244ad529b3"
my_url if (!file.exists(paste0(getwd(), "/data/age", to_day, ".csv"))) {
download.file(my_url, destfile = paste0(getwd(), "/data/age", to_day, ".csv"))
}<- read.csv(paste0(getwd(), "/data/age", to_day, ".csv"), sep = ";")
hospital_age # On ajoute le nom des régions:
<- merge(hospital_age, code_region, by.x = "reg", by.y = "code")
hospital_age # On utilise le format date pour coder le jour:
$jour <- as.Date(hospital_age$jour)
hospital_age# on affecte la semaine
$semaine <- num_semaine(hospital_age$jour)
hospital_age
# on calcule les nouvelles hospitalisations/réanimations/décès
$new_hosp <- 0
hospital_age$new_rea <- 0
hospital_age$new_dc <- 0
hospital_age
for (k in nrow(hospital_age):1) {
<- hospital_age$cl_age90[k]
age_k <- hospital_age$jour[k]
jour_k <- hospital_age$reg[k]
reg_k <- hospital_age$rad[k]
rad_k <- hospital_age$dc[k]
dc_k
<- which(hospital_age$reg == reg_k & hospital_age$cl_age90 == age_k & hospital_age$jour == jour_k - 1)
ind_k if (length(ind_k) == 1) {
$new_hosp[k] <- max((hospital_age$hosp[k] - hospital_age$hosp[ind_k]) +
hospital_age$dc[k] - hospital_age$dc[ind_k]) +
(hospital_age$rad[k] - hospital_age$rad[ind_k]) +
(hospital_age$rea[k] - hospital_age$rea[ind_k]), 0)
(hospital_age$new_rea[k] <- max((hospital_age$dc[k] - hospital_age$dc[ind_k]) +
hospital_age$rea[k] - hospital_age$rea[ind_k]), 0)
(hospital_age$new_dc[k] <- max((hospital_age$dc[k] - hospital_age$dc[ind_k]), 0)
hospital_age
}
}# on aggrege par semaine
<- hospital_age %>%
my_basis_age group_by(region, semaine, cl_age90) %>%
::summarize(hosp = sum(new_hosp),
dplyrrea = sum(new_rea),
dc = sum(new_dc),
jour = max(jour),
region = unique(region))
# On met au format wide
<- tidyr::pivot_wider(my_basis_age,
my_basis_age_wide id_cols = c("semaine", "region", "jour", "hosp", "rea", "dc", "cl_age90"),
names_from = "cl_age90",
values_from = c("hosp", "rea", "dc"))
On va calculer quelques chiffres clés pour mesure la situation des régions sur les 7 derniers jours qui viennent de s’écouler : [08 mars 2021; 14 mars 2021].
# On aggrège les données par région sur la semaine `r paste0("[", format(to_day - 7, '%d %B %Y'), "; ", format(to_day - 1, '%d %B %Y'), "]")` :
<- my_basis %>%
vs_my_basis_t0 filter(semaine %in% "semaine_t00") %>%
group_by(region) %>%
summarise(hosp = sum(hosp),
rea = sum(rea),
dc = sum(dc))
# On aggrège les données par région sur la semaine `r paste0("[", format(to_day - 13, '%d %B %Y'), "; ", format(to_day - 7, '%d %B %Y'), "]")` :
<- my_basis %>%
vs_my_basis_t1 filter(semaine %in% "semaine_t01") %>%
group_by(region) %>%
summarise(hosp = sum(hosp),
rea = sum(rea),
dc = sum(dc))
On représente par région:
le nombre total de nouvelles hospitalisations (semaine [08 mars 2021; 14 mars 2021]).
le nombre moyen journalier de nouvelles hospitalisations (semaine [08 mars 2021; 14 mars 2021]).
l’évolution (en pourcentage) entre la semaine [01 mars 2021; 07 mars 2021] et la semaine [08 mars 2021; 14 mars 2021].
<- vs_my_basis_t0 %>%
hosp_region select(region, hosp) %>%
mutate(`moyenne jour` = hosp / 7,
`evolution en %` = (vs_my_basis_t0$hosp - vs_my_basis_t1$hosp) / vs_my_basis_t1$hosp * 100) %>%
rename(`total semaine` = hosp) %>%
arrange(-`total semaine`)
# On représente les données :
3] <- round(hosp_region[, 3])
hosp_region[, 4] <- round(hosp_region[, 4], 1)
hosp_region[, 2:4] <- lapply(hosp_region[2:4], function(x) {
hosp_region[cell_spec(x, bold = T, color = spec_color(x, end = 0.9),
font_size = spec_font_size(x))
})<- rbind(hosp_region, tibble(region = "France entière",
hosp_region `total semaine` = sum(vs_my_basis_t0$hosp),
`moyenne jour` = round(sum(vs_my_basis_t0$hosp) / 7, 0),
`evolution en %` = round((sum(vs_my_basis_t0$hosp) - sum(vs_my_basis_t1$hosp)) /
sum(vs_my_basis_t1$hosp) * 100, 1)))
kbl(hosp_region, escape = F, align = "c") %>% kable_classic("striped", full_width = F)
region | total semaine | moyenne jour | evolution en % |
---|---|---|---|
Ile-de-France | 2791 | 399 | 10.8 |
Hauts-de-France | 1275 | 182 | 7.8 |
Provence-Alpes-Côte d’Azur | 1196 | 171 | -9.2 |
Auvergne-Rhône-Alpes | 1017 | 145 | -2.9 |
Grand Est | 821 | 117 | 2.6 |
Normandie | 463 | 66 | 22.5 |
Occitanie | 451 | 64 | -5.1 |
Nouvelle-Aquitaine | 432 | 62 | 5.4 |
Bourgogne-Franche-Comté | 371 | 53 | -2.6 |
Centre-Val de Loire | 352 | 50 | 21.4 |
Pays de la Loire | 320 | 46 | 5.6 |
Bretagne | 229 | 33 | 15.7 |
DOM-TOM | 186 | 27 | 24 |
Corse | 29 | 4 | 38.1 |
France entière | 9933 | 1419 | 4.9 |
On représente par département la carte des nouvelles hospitalisations sur la dernière semaine observée ([08 mars 2021; 14 mars 2021])
# On importe les contours des départements
.2015 <- readOGR(dsn="./departements 2015/DEPARTEMENT", layer="DEPARTEMENT") dep
## OGR data source with driver: ESRI Shapefile
## Source: "/media/thibault/My Passport/confinement/covid/departements 2015/DEPARTEMENT", layer: "DEPARTEMENT"
## with 96 features
## It has 11 fields
.2015@data$CODE_DEPT <- as.character(dep.2015@data$CODE_DEPT)
dep
# data
.2015_00 <- merge(dep.2015, filter(my_basis, semaine == "semaine_t00"),
depby.x = "CODE_DEPT", by.y = "dep")
# On représente les nouvelles hospitalisations sur la dernière semaine observée (`r paste0("[", format(to_day - 7, '%d %B %Y'), "; ", format(to_day - 1, '%d %B %Y'), "]")`) (Source pour le code : https://rgeomatic.hypotheses.org/1361#more-1361)
# quantization breaks of the rate
<- c(0, getBreaks(v = dep.2015_00$hosp, method = "kmeans", nclass = 5))
bks # correct the breaks to use the global rate as limit of class
# get a color palette
<- carto.pal(pal1 = "green.pal", n1 = 3, pal2 = "wine.pal", n2 = 3)
cols ## Choropleth layer
# set figure margins and background color
par(mar = c(0, 0, 1.2, 0), bg = "lemonchiffon")
# Hospitalisations
choroLayer(spdf = dep.2015_00, var = "hosp", breaks = bks, col = cols,
border = "khaki", lwd = 0.5,
legend.title.txt = "Hospitalisations",
legend.pos = 'topleft', legend.values.rnd = 0)
# add a title and layout
layoutLayer(title = paste0("Nouvelles hospitalisations ",
paste0("[", format(to_day - 7, '%d %B %Y'), "; ", format(to_day - 1, '%d %B %Y'), "]")),
sources = "", north = TRUE, scale = 50, tabtitle = TRUE,
theme = "sand.pal", frame = FALSE,
author = "")
On représente par région:
le nombre total de nouvelles réanimations (semaine [08 mars 2021; 14 mars 2021]).
le nombre moyen journalier de nouvelles réanimations (semaine [08 mars 2021; 14 mars 2021]).
l’évolution (en pourcentage) entre la semaine [01 mars 2021; 07 mars 2021] et la semaine [08 mars 2021; 14 mars 2021].
<- vs_my_basis_t0 %>%
rea_region select(region, rea) %>%
mutate(`moyenne jour` = rea / 7,
`evolution en %` = (vs_my_basis_t0$rea - vs_my_basis_t1$rea) / vs_my_basis_t1$rea * 100) %>%
rename(`total semaine` = rea) %>%
arrange(-`total semaine`)
# On représente les données :
3] <- round(rea_region[, 3])
rea_region[, 4] <- round(rea_region[, 4], 1)
rea_region[, 2:4] <- lapply(rea_region[2:4], function(x) {
rea_region[cell_spec(x, bold = T, color = spec_color(x, end = 0.9),
font_size = spec_font_size(x))
})
<- rbind(rea_region, tibble(region = "France entière",
rea_region `total semaine` = sum(vs_my_basis_t0$rea),
`moyenne jour` = round(sum(vs_my_basis_t0$rea) / 7, 0),
`evolution en %` = round((sum(vs_my_basis_t0$rea) - sum(vs_my_basis_t1$rea)) /
sum(vs_my_basis_t1$rea) * 100, 1)))
kbl(rea_region, escape = F, align = "c") %>% kable_classic("striped", full_width = F)
region | total semaine | moyenne jour | evolution en % |
---|---|---|---|
Ile-de-France | 736 | 105 | 20.5 |
Hauts-de-France | 292 | 42 | 7.4 |
Provence-Alpes-Côte d’Azur | 259 | 37 | -3.7 |
Auvergne-Rhône-Alpes | 239 | 34 | 8.6 |
Grand Est | 178 | 25 | 24.5 |
Occitanie | 131 | 19 | 17 |
Nouvelle-Aquitaine | 86 | 12 | -12.2 |
Centre-Val de Loire | 79 | 11 | 12.9 |
Normandie | 77 | 11 | 5.5 |
Bourgogne-Franche-Comté | 69 | 10 | -4.2 |
DOM-TOM | 53 | 8 | 35.9 |
Pays de la Loire | 52 | 7 | 2 |
Bretagne | 30 | 4 | -11.8 |
Corse | 6 | 1 | -25 |
France entière | 2287 | 327 | 10.4 |
On représente par département la carte des nouvelles réanimations sur la dernière semaine observée ([08 mars 2021; 14 mars 2021])
# quantization breaks of the rate
<- c(0, getBreaks(v = dep.2015_00$rea, method = "kmeans", nclass = 5))
bks # correct the breaks to use the global rate as limit of class
# get a color palette
<- carto.pal(pal1 = "green.pal", n1 = 3, pal2 = "wine.pal", n2 = 3)
cols ## Choropleth layer
# set figure margins and background color
par(mar = c(0, 0, 1.2, 0), bg = "lemonchiffon")
# Hospitalisations
choroLayer(spdf = dep.2015_00, var = "rea", breaks = bks, col = cols,
border = "khaki", lwd = 0.5,
legend.title.txt = "Réanimations",
legend.pos = 'topleft', legend.values.rnd = 0)
# add a title and layout
layoutLayer(title = paste0("Nouvelles Réanimations ",
paste0("[", format(to_day - 7, '%d %B %Y'), "; ", format(to_day - 1, '%d %B %Y'), "]")),
sources = "", north = TRUE, scale = 50, tabtitle = TRUE,
theme = "sand.pal", frame = FALSE,
author = "")
On représente par région:
le nombre total de nouveaux décès (semaine [08 mars 2021; 14 mars 2021]).
le nombre moyen journalier de nouveaux décès (semaine [08 mars 2021; 14 mars 2021]).
l’évolution (en pourcentage) entre la semaine [01 mars 2021; 07 mars 2021] et la semaine [08 mars 2021; 14 mars 2021].
<- vs_my_basis_t0 %>%
dc_region select(region, dc) %>%
mutate(`moyenne jour` = dc / 7,
`evolution en %` = (vs_my_basis_t0$dc - vs_my_basis_t1$dc) / vs_my_basis_t1$dc * 100) %>%
rename(`total semaine` = dc) %>%
arrange(-`total semaine`)
# On représente les données :
3] <- round(dc_region[, 3])
dc_region[, 4] <- round(dc_region[, 4], 1)
dc_region[, 2:4] <- lapply(dc_region[2:4], function(x) {
dc_region[cell_spec(x, bold = T, color = spec_color(x, end = 0.9),
font_size = spec_font_size(x))
})
<- rbind(dc_region, tibble(region = "France entière",
dc_region `total semaine` = sum(vs_my_basis_t0$dc),
`moyenne jour` = round(sum(vs_my_basis_t0$dc) / 7, 0),
`evolution en %` = round((sum(vs_my_basis_t0$dc) - sum(vs_my_basis_t1$dc)) /
sum(vs_my_basis_t1$dc) * 100, 1)))
kbl(dc_region, escape = F, align = "c") %>% kable_classic("striped", full_width = F)
region | total semaine | moyenne jour | evolution en % |
---|---|---|---|
Ile-de-France | 405 | 58 | -4.5 |
Hauts-de-France | 243 | 35 | -4 |
Provence-Alpes-Côte d’Azur | 243 | 35 | 1.7 |
Auvergne-Rhône-Alpes | 204 | 29 | -0.5 |
Grand Est | 172 | 25 | -7 |
Nouvelle-Aquitaine | 95 | 14 | 3.3 |
Occitanie | 74 | 11 | -29.5 |
Normandie | 69 | 10 | 0 |
Bourgogne-Franche-Comté | 68 | 10 | -16 |
Centre-Val de Loire | 56 | 8 | 1.8 |
Pays de la Loire | 47 | 7 | -21.7 |
Bretagne | 37 | 5 | -24.5 |
DOM-TOM | 14 | 2 | -39.1 |
Corse | 6 | 1 | 100 |
France entière | 1733 | 248 | -6 |
On représente par département la carte des nouveaux décès sur la dernière semaine observée ([08 mars 2021; 14 mars 2021])
# quantization breaks of the rate
<- c(0, getBreaks(v = dep.2015_00$dc, method = "kmeans", nclass = 5))
bks # correct the breaks to use the global rate as limit of class
# get a color palette
<- carto.pal(pal1 = "green.pal", n1 = 3, pal2 = "wine.pal", n2 = 3)
cols ## Choropleth layer
# set figure margins and background color
par(mar = c(0, 0, 1.2, 0), bg = "lemonchiffon")
# Hospitalisations
choroLayer(spdf = dep.2015_00, var = "dc", breaks = bks, col = cols,
border = "khaki", lwd = 0.5,
legend.title.txt = "Décès",
legend.pos = 'topleft', legend.values.rnd = 0)
# add a title and layout
layoutLayer(title = paste0("Nouveaux décès ",
paste0("[", format(to_day - 7, '%d %B %Y'), "; ", format(to_day - 1, '%d %B %Y'), "]")),
sources = "", north = TRUE, scale = 50, tabtitle = TRUE,
theme = "sand.pal", frame = FALSE,
author = "")
On calcule la différence entre le nombre de nouveaux patients hospitalisés sur la période [08 mars 2021; 14 mars 2021] et sur la période [28 février 2021; 07 mars 2021]
<- merge(my_basis %>%
my_basis_evol filter(semaine == "semaine_t00") %>%
rename(hosp_t0 = hosp) %>%
select(dep, hosp_t0, region),
%>%
my_basis filter(semaine == "semaine_t01") %>%
select(dep, hosp) %>%
rename(hosp_t1 = hosp),
by = "dep") %>%
mutate(diff_abs = hosp_t0 - hosp_t1,
diff_rel = (hosp_t0 - hosp_t1) / hosp_t1) %>%
mutate(evol = factor(ifelse(diff_rel < 0, "<0",
ifelse(diff_rel >= 0 & diff_rel < 0.5, "[0,50%[",
ifelse(diff_rel >= 0.5 & diff_rel < 1, "[50,100%[",
ifelse(diff_rel >= 1 & diff_rel < 2, "[100,200%[",
">200%")))),
levels = c("<0", "[0,50%[", "[50,100%[", "[100,200%[", ">200%")))
<- tidyr::pivot_longer(data = my_basis_evol,
my_basis_evol_long col = c(2, 4),
names_to = "semaine",
values_to = "hospitalisations")
$semaine <- factor(my_basis_evol_long$semaine,
my_basis_evol_longlevels = c("hosp_t1", "hosp_t0"),
labels = c(paste0("[", format(to_day - 14, '%d %b'), "; ",
format(to_day - 8, '%d %b'), "]"),
paste0("[", format(to_day - 7, '%d %b'), "; ",
format(to_day - 1, '%d %b'), "]")))
On va représenter des couleurs différentes en fonction du taux d’évolution découpées en 5 classes
<- ggplot(my_basis_evol_long, aes(x = semaine, y = hospitalisations, colour = evol, group = dep))+
p geom_line() +
scale_colour_manual(values = c("blue", "#FC9272", "#FB6A4A", "#DE2D26", "#A50F15")) +
facet_wrap(~region)
::ggplotly(p) plotly
On met à jour les données chaque jour :
# On récupére directement l'url depuis le site du ministère:
<- "https://www.data.gouv.fr/fr/datasets/r/406c6a23-e283-4300-9484-54e78c8ae675"
url if (!file.exists(paste0(getwd(), "/data/test", to_day, ".csv"))) {
download.file(url, destfile = paste0(getwd(), "/data/test", to_day, ".csv"))
}<- read.csv(paste0(getwd(), "/data/test", to_day, ".csv"), sep = ";")
test # on enlève les départements qui ne sont pas présents dans la table hopital
<- test %>%
test filter(!(dep %in% c("975", "977", "978")))
# On utilise le format date pour coder le jour:
$jour <- as.Date(test$jour)
test$semaine <- num_semaine(test$jour, begin = max(hospital$jour) - 3, decallage = TRUE)
test<- merge(test, dep_region, by = "dep") test_region
On va calculer quelques chiffres clés pour mesurer la situation des régions sur une fenêtre de 7 jours [05 mars 2021; 11 mars 2021]. On ne peut pas représenter les 7 derniers jours car les données ne sont pas encore diffusées.
# On aggrège les données par région sur la semaine `r paste0("[", format(to_day - 7, '%d %B %Y'), "; ", format(to_day - 1, '%d %B %Y'), "]")` :
<- test_region %>%
vs_my_basis_t0 filter(semaine %in% "semaine_t0-1", cl_age90 == 0) %>%
group_by(region) %>%
summarise(P = sum(P))
# On aggrège les données par région sur la semaine `r paste0("[", format(to_day - 13, '%d %B %Y'), "; ", format(to_day - 7, '%d %B %Y'), "]")` :
<- test_region %>%
vs_my_basis_t1 filter(semaine %in% "semaine_t00", cl_age90 == 0) %>%
group_by(region) %>%
summarise(P = sum(P))
On représente par région:
le nombre total de testés positifs (semaine [05 mars 2021; 11 mars 2021]).
le nombre moyen journalier de testés positifs (semaine [05 mars 2021; 11 mars 2021]).
l’évolution (en pourcentage) entre la semaine [26 février 2021; 04 mars 2021] et la semaine [05 mars 2021; 11 mars 2021].
<- vs_my_basis_t0 %>%
P_region select(region, P) %>%
mutate(`moyenne jour` = P / 7,
`evolution en %` = (vs_my_basis_t0$P - vs_my_basis_t1$P) / vs_my_basis_t1$P * 100) %>%
rename(`total semaine` = P) %>%
arrange(-`total semaine`)
# On représente les données :
3] <- round(P_region[, 3])
P_region[, 4] <- round(P_region[, 4], 1)
P_region[, 2:4] <- lapply(P_region[2:4], function(x) {
P_region[cell_spec(x, bold = T, color = spec_color(x, end = 0.9),
font_size = spec_font_size(x))
})<- rbind(P_region, tibble(region = "France entière",
P_region `total semaine` = sum(vs_my_basis_t0$P),
`moyenne jour` = round(sum(vs_my_basis_t0$P) / 7, 0),
`evolution en %` = round((sum(vs_my_basis_t0$P) - sum(vs_my_basis_t1$P)) /
sum(vs_my_basis_t1$P) * 100, 1)))
kbl(P_region, escape = F, align = "c") %>% kable_classic("striped", full_width = F)
region | total semaine | moyenne jour | evolution en % |
---|---|---|---|
Ile-de-France | 48054 | 6865 | 12.5 |
Hauts-de-France | 21403 | 3058 | 8.3 |
Provence-Alpes-Côte d’Azur | 17199 | 2457 | 2.7 |
Auvergne-Rhône-Alpes | 15885 | 2269 | 9.7 |
Grand Est | 11454 | 1636 | 13.3 |
Occitanie | 9236 | 1319 | 0.9 |
Nouvelle-Aquitaine | 7223 | 1032 | 10.9 |
Normandie | 6716 | 959 | 13.5 |
Pays de la Loire | 5987 | 855 | 7.8 |
Bourgogne-Franche-Comté | 4736 | 677 | 11 |
Centre-Val de Loire | 4696 | 671 | 12.8 |
Bretagne | 4295 | 614 | 17.5 |
DOM-TOM | 1916 | 274 | -26.2 |
Corse | 540 | 77 | 9.5 |
France entière | 159340 | 22763 | 9 |
On représente les testés positifs par tranche d’age:
# On aggrège les données par tranche d'age et semaine:
<- test %>%
test_by_age filter(cl_age90 != 0) %>%
group_by(semaine, cl_age90) %>%
summarize(P = sum(P),
jour = max(jour)) %>%
group_by(semaine) %>%
mutate(percent_P = P / sum(P))
<- ggplot(test_by_age) +
p aes(x = jour, y = P, fill = factor(cl_age90)) +
geom_area(color = "black") +
labs(title = "Nombre de téstés positifs par classe d'âge ",
x = "Week",
y = "Effectifs",
fill = "Age") +
scale_fill_brewer(palette = "Set3") +
theme_minimal()
::ggplotly(p) plotly
On représente les testés positifs par région :
$region <- factor(test_region$region, levels = hosp_region$region)
test_region<- test_region %>%
test_by_region filter(cl_age90 == 0) %>%
group_by(semaine, region) %>%
summarize(P = sum(P),
jour = max(jour)) %>%
group_by(semaine) %>%
mutate(percent_P = P / sum(P))
<- ggplot(test_by_region) +
p aes(x = jour, y = P, fill = factor(region)) +
geom_area(color = "black") +
labs(title = "Nombre de testés positifs par région",
x = "Week",
y = "Effectifs",
fill = "Region") +
scale_fill_brewer(palette = "Set3") +
theme_minimal()
::ggplotly(p) plotly
<- test_region %>%
test_by_dep filter(cl_age90 == 0) %>%
group_by(semaine, region, dep) %>%
summarize(P = sum(P),
jour = max(jour)) %>%
group_by(semaine) %>%
mutate(percent_P = P / sum(P))
<- ggplot(data = test_by_dep,
p aes(x = jour, y = P, color = region, group = dep)) +
geom_line() +
coord_cartesian(ylim = c(0, 20000)) +
facet_wrap(~ region)
::ggplotly(p) plotly
Hypothèse: on suppose que le nombre d’admis en hospitalisations à la semaine t0 dépend du nombre de cas testés positifs sur une fenêtre de 7 jours qui aura commencé 10 jours avant la semaine t0. Exemple: la semaine t0 est [08 mars 2021; 14 mars 2021], on va l’expliquer par le nombre de personnes testées positive du [26 février 2021; 04 mars 2021].
On prépare ici les données pour l’étape de modélisation:
# On aggrège les données par département et semaine:
<- test %>%
test_by filter(cl_age90 != 0) %>%
group_by(dep, semaine, cl_age90) %>%
summarize(P = sum(P),
jour = max(jour)) %>%
group_by(dep, semaine) %>%
mutate(percent_P = P / sum(P))
# On passe d'un format long à un format wide les tranches d'âge pour les avoir comme des variables explicatives
$cl_age90 <- paste0("tranche_", test_by$cl_age90)
test_by<- tidyr::pivot_wider(test_by,
test_long id_cols = c("semaine", "dep", "jour", "P", "cl_age90"),
names_from = "cl_age90",
values_from = "P")
# On aggrège les données par département et semaine:
<- test_long %>%
test_by group_by(dep, semaine) %>%
summarize(tranche_9 = sum(tranche_9),
tranche_19 = sum(tranche_19),
tranche_29 = sum(tranche_29),
tranche_39 = sum(tranche_39),
tranche_49 = sum(tranche_49),
tranche_59 = sum(tranche_59),
tranche_69 = sum(tranche_69),
tranche_79 = sum(tranche_79),
tranche_89 = sum(tranche_89),
tranche_90 = sum(tranche_90)) %>%
mutate(tranche_0 = tranche_9 + tranche_19 + tranche_29 + tranche_39 +
+ tranche_59 + tranche_69 + tranche_79 + tranche_89 + tranche_90)
tranche_49
# On merge les jeux de données :
<- merge(my_basis, test_by, by = c("dep", "semaine"), all.y = T)
my_basis which(is.na(my_basis$jour)), "jour"] <- to_day + 6
my_basis[which(is.na(my_basis$region)), "region"] <- dep_region$region[match(my_basis[which(is.na(my_basis$region)), "dep"], dep_region$dep)] my_basis[
Dans un premier temps, on va rerésenter les départements par des cercles de taille proportionnelle aux nombres de testés positifs la semaine du [26 février 2021; 04 mars 2021]. La couleur dépend du nombre d’hospitalisations observés la semaine du [08 mars 2021; 14 mars 2021].
.2015_00 <- merge(dep.2015, filter(my_basis, semaine == "semaine_t00"),
depby.x = "CODE_DEPT", by.y = "dep")
<- 1 - (dep.2015_00$tranche_0 / max(dep.2015_00$tranche_0))
w .2015_dorling <- cartogram_dorling(dep.2015_00, "tranche_0", m_weight = w, k = 5)
dep# dep.2015$tranche_0 <- as.numeric(dep.2015$tranche_0)
# dep.2015_ncont <- cartogram_ncont(dep.2015, "tranche_0")
# set figure margins and background color
par(mar = c(0, 0, 1.2, 0), bg = "lemonchiffon")
# Hospitalisations
<- c(0, getBreaks(v = dep.2015_00$hosp, method = "kmeans", nclass = 5))
bks # correct the breaks to use the global rate as limit of class
# get a color palette
<- carto.pal(pal1 = "green.pal", n1 = 3, pal2 = "wine.pal", n2 = 3)
cols choroLayer(spdf = dep.2015_dorling, var = "hosp", breaks = bks, col = cols, lwd = 0.5,
legend.title.txt = "Hospitalisations",
legend.pos = 'topleft', legend.values.rnd = 0)
# plot(dep.2015, add = T, border = "khaki")
# add a title and layout
layoutLayer(title = paste0("Nouvelles hospitalisations ",
paste0("[", format(to_day - 7, '%d %B %Y'), "; ", format(to_day - 1, '%d %B %Y'), "]")),
sources = "", north = TRUE, scale = 50, tabtitle = TRUE,
theme = "sand.pal", frame = FALSE,
author = "")
On représente le nombre de nouvelles hospitalisations par semaine et par département en fonction du nombre de personnes testées positives quelques jours auparavant et on constate un lien très fort.
<- ggplot(my_basis) +
p aes(x = tranche_0, y = hosp) +
geom_point() +
geom_smooth(method = "loess") +
geom_smooth(method = "lm",
col = "red") +
facet_wrap(~ region)
::ggplotly(p) plotly
On rappelle que les données sur le nombre de testés positifs ne sont disponible que jusqu’au 11 mars 2021. Notre objectif est de prédire le nombre de testés positifs du 12 mars 2021 au 18 mars 2021 en utilisant des modèles de séries temporelles. En utilisant un modèle de série temporelle on suppose que ce qu’on observe à la date \(j\) dépend de ce qu’il s’est passé les dates antérieures. On va utiliser 3 modèles différents et en fonction de leur performence (sur les données passées), on va leur donner plus ou moins d’importance.
Ici, on considère les données journalières, et non hebdomadaires. On va expliquer \(y_{d, t}^a\), le nombre de testés positifs le jour \(t\) dans le département \(d\) et dans la tranche d’âge \(a\). La stratégie utilisée est la suivante :
on différencie chaque série pour les rendre stationnaire (on ne vérifiera pas l’hypothèse de stationarité après la différenciation car on modélise énormément de modèle, ici on a \(A\times D\) séries où \(A\) est le nombre de classe d’âge et \(D\) le nombre de département et notre but est d’avoir une procédure automatique)
on cherche le meilleur modèle \(ARIMA(p,d,q)\) selon le critère AIC, à l’aide de la fonction auto.arima() (package forecast)
on prédit sur les 7 prochains jours à venir et on cummule ces prédictions pour avoir une prédiction du nombre de cas positifs sur la semaine à venir.
On va appliquer deux modèles de lissage exponentiels:
un modèle journalier qui va permettre de modéliser \(y_{d, t}^a\), le nombre de testés positifs le jour \(t\) dans le département \(d\) et dans la tranche d’âge \(a\) afin de prédire le nombre de testés positifs dans les 7 jours.
un modèle hebdomadaire qui va permettre de modéliser \(y_{d, s}^a\), le nombre de testés positifs la semaine \(s\) dans le département \(d\) et dans la tranche d’âge \(a\) afin de prédire le nombre de testés positifs la semaine à venir.
On apprentit les modèles ci-dessus en enlevant la dernière semaine observée dans le but de donner des poids différents aux trois modèles de prédictions utilisés. Ainsi, on donnera davantage de poids aux modèles qui ont mieux prédit la dernière semaine observée.
# prediction par department
<- my_basis[my_basis$semaine == "semaine_t00", "dep"]
nom_dep <- numeric(length(nom_dep))
pred_cas <- data.frame(true_P = numeric(0), pred_1 = numeric(0), pred_2 = numeric(0), pred_3 = numeric(0))
my_tab
# apprentissage
for (k in length(nom_dep):1) {
if (nom_dep[k] %in% c("975", "977", "978")) {
<- rbind(data_k, my_basis)
my_basis else {
} for (age in c(0, 9, 19, 29, 39, 49, 59, 69, 79, 89, 90)) {
# apprentissage
<- test[test$dep == nom_dep[k] & test$cl_age90 == age & test$jour <= max(test$jour) - 7, ]
temp <- zoo(temp$P, temp$jour)
my_ts
# Methode 1 : ARIMA
<- diff(my_ts)
my_ts_diff # tseries::adf.test(my_ts)
# tseries::adf.test(my_ts_diff)
<- forecast::auto.arima(my_ts_diff)
my_mod <- as.numeric(forecast(my_mod)$mean)
forecast_my_mod <- round(sum((as.numeric(my_ts[length(my_ts)]) + cumsum(forecast_my_mod))[1:7]), 0)
pred_1 # Méthode 2 : lissage exponentiel
<- ets(my_ts)
my_mod_exp <- as.numeric(forecast(my_mod_exp)$mean)
forecast_my_mod_exp <- ifelse(forecast_my_mod_exp > 0, forecast_my_mod_exp, 0)
forecast_my_mod_exp <- round(sum(forecast_my_mod_exp[1:7]), 0)
pred_2 # Méthode 3 : lissage exponentiel sur données hebdomadaires
<- my_basis[my_basis$dep == nom_dep[k] & !(my_basis$semaine %in% c("semaine_t0-1", "semaine_t0-2")), ]
temp <- zoo(temp[ , paste0("tranche_", age)], temp$jour)
my_ts_exp <- ets(my_ts_exp)
my_mod_exp_2 <- as.numeric(forecast(my_mod_exp_2)$mean)
forecast_my_mod_exp <- ifelse(forecast_my_mod_exp > 0, forecast_my_mod_exp, 0)
forecast_my_mod_exp <- round(forecast_my_mod_exp[1], 0)
pred_3
<- sum(test[which(test$dep == nom_dep[k] & test$cl_age90 == age &
true_P $jour > (max(test$jour) - 7)), "P"])
test<- rbind(my_tab, data.frame(true_P = true_P, pred_1 = pred_1, pred_2 = pred_2, pred_3 = pred_3))
my_tab
}
}
}
<- lm(true_P ~ pred_1 + pred_2 + pred_3, data = my_tab)
res_lm_cas
for (k in length(nom_dep):1) {
<- data.frame(dep = nom_dep[k], semaine = "semaine_t0-2", hosp = NA, rea = NA, rad = NA, dc = NA,
data_k jour = to_day + 13, region = dep_region[match(nom_dep[k], dep_region$dep) , "region"],
tranche_9 = NA, tranche_19 = NA, tranche_29 = NA, tranche_39 = NA, tranche_49 = NA,
tranche_59 = NA, tranche_69 = NA, tranche_79 = NA, tranche_89 = NA, tranche_90 = NA,
tranche_0 = NA)
<- data.frame(dep = nom_dep[k], semaine = "semaine_t0-2", hosp = NA, rea = NA, rad = NA, dc = NA,
data_k_2 jour = to_day + 13, region = dep_region[match(nom_dep[k], dep_region$dep) , "region"],
tranche_9 = NA, tranche_19 = NA, tranche_29 = NA, tranche_39 = NA, tranche_49 = NA,
tranche_59 = NA, tranche_69 = NA, tranche_79 = NA, tranche_89 = NA, tranche_90 = NA,
tranche_0 = NA)
if (nom_dep[k] %in% c("975", "977", "978")) {
<- rbind(data_k, my_basis)
my_basis else {
} for (age in c(0, 9, 19, 29, 39, 49, 59, 69, 79, 89, 90)) {
# modèle journaliers
<- test[test$dep == nom_dep[k] & test$cl_age90 == age, ]
temp <- zoo(temp$P, temp$jour)
my_ts <- diff(my_ts)
my_ts_diff # tseries::adf.test(my_ts)
# tseries::adf.test(my_ts_diff)
<- forecast::auto.arima(my_ts_diff)
my_mod <- as.numeric(forecast(my_mod)$mean)
forecast_my_mod <- round(sum((as.numeric(my_ts[length(my_ts)]) + cumsum(forecast_my_mod))[1:7]), 0)
pred_1 # modèles exponentiels
# Méthode 2 : lissage exponentiel
<- ets(my_ts)
my_mod_exp <- as.numeric(forecast(my_mod_exp)$mean)
forecast_my_mod_exp <- ifelse(forecast_my_mod_exp > 0, forecast_my_mod_exp, 0)
forecast_my_mod_exp <- round(sum(forecast_my_mod_exp[1:7]), 0)
pred_2 # Méthode 3 : lissage exponentiel sur données hebdomadaires
<- my_basis[my_basis$dep == nom_dep[k] & !(my_basis$semaine %in% c("semaine_t0-2")), ]
temp <- zoo(temp[ , paste0("tranche_", age)], temp$jour)
my_ts_exp <- ets(my_ts_exp)
my_mod_exp_2 <- as.numeric(forecast(my_mod_exp_2)$mean)
forecast_my_mod_exp <- ifelse(forecast_my_mod_exp > 0, forecast_my_mod_exp, 0)
forecast_my_mod_exp <- round(forecast_my_mod_exp[1], 0)
pred_3 paste0("tranche_", age)] <- predict(res_lm_cas, newdata = data.frame(pred_1 = pred_1,
data_k[ , pred_2 = pred_2,
pred_3 = pred_3))
}<- rbind(data_k, my_basis)
my_basis
} }
On représente les testés positifs par région en ajoutant les valeurs de la semaine prédite:
<- my_basis %>%
test_by_region group_by(semaine, region) %>%
summarize(P = sum(tranche_0),
jour = max(jour))
$region <- factor(test_by_region$region, levels = hosp_region$region)
test_by_region<- ggplot(test_by_region) +
p aes(x = jour - 10, y = P, fill = factor(region)) +
geom_area(color = "black") +
labs(title = "Prédictions du nombre de testés positifs par région",
x = "Week",
y = "Effectifs",
fill = "Region") +
scale_fill_brewer(palette = "Set3") +
theme_minimal()
::ggplotly(p) plotly
On aggrège les données à la France entière:
<- my_basis %>%
my_basis_fr group_by(semaine, jour) %>%
summarise(P = sum(tranche_0))
<- ggplot(data = filter(my_basis_fr, semaine %in% c("semaine_t0-2", "semaine_t0-1", "semaine_t00")),
p aes(x = jour - 10, y = P)) +
geom_line(col = "red") +
geom_line(data = filter(my_basis_fr, !(semaine %in% c("semaine_t0-2"))),
aes(x = jour - 10, y = P)) +
labs(title = "Prédiction des nouveaux cas positifs dans les 7 jours",
x = "semaine",
y = "Cas positifs",
fill = "Age")
::ggplotly(p) plotly
Ici, pour chaque région \(r\), le modèle est de la forme
\[y_{i,t}^r=\beta_0^r+\beta_1^rx_{i,t'}^r+\epsilon_{i,t}^r\] avec:
En d’autres termes, on fait ici un modèle de régression par région. Cela suppose que le lien entre les tests virologiques et le nombre d’hospitalisation est homogène à l’intérieur d’une région et peut différer d’une région à une autre.
Apprentissage:
On modélise sur les observations des semaines précédentes:
<- lm(hosp ~ region + tranche_0:region - 1,
res_lm data = my_basis[!(my_basis$semaine %in% c("semaine_t0-2", "semaine_t0-1", "semaine_t00")), ])
::stargazer(res_lm, type = "html") stargazer
Dependent variable: | |
hosp | |
regionAuvergne-Rhône-Alpes | 12.869*** |
(1.659) | |
regionBourgogne-Franche-Comté | 9.762*** |
(2.195) | |
regionBretagne | 4.015 |
(3.237) | |
regionCentre-Val de Loire | 8.925*** |
(2.638) | |
regionCorse | 1.953 |
(4.479) | |
regionDOM-TOM | 3.049 |
(2.812) | |
regionGrand Est | 13.292*** |
(1.953) | |
regionHauts-de-France | 27.695*** |
(2.613) | |
regionIle-de-France | 30.271*** |
(2.539) | |
regionNormandie | 5.697** |
(2.782) | |
regionNouvelle-Aquitaine | 2.556 |
(1.752) | |
regionOccitanie | 3.084* |
(1.617) | |
regionPays de la Loire | 13.426*** |
(2.878) | |
regionProvence-Alpes-Côte d’Azur | 8.143*** |
(2.469) | |
regionAuvergne-Rhône-Alpes:tranche_0 | 0.064*** |
(0.001) | |
regionBourgogne-Franche-Comté:tranche_0 | 0.074*** |
(0.003) | |
regionBretagne:tranche_0 | 0.058*** |
(0.004) | |
regionCentre-Val de Loire:tranche_0 | 0.058*** |
(0.004) | |
regionCorse:tranche_0 | 0.044* |
(0.023) | |
regionDOM-TOM:tranche_0 | 0.087*** |
(0.006) | |
regionGrand Est:tranche_0 | 0.068*** |
(0.002) | |
regionHauts-de-France:tranche_0 | 0.056*** |
(0.001) | |
regionIle-de-France:tranche_0 | 0.058*** |
(0.001) | |
regionNormandie:tranche_0 | 0.071*** |
(0.003) | |
regionNouvelle-Aquitaine:tranche_0 | 0.062*** |
(0.002) | |
regionOccitanie:tranche_0 | 0.054*** |
(0.002) | |
regionPays de la Loire:tranche_0 | 0.049*** |
(0.003) | |
regionProvence-Alpes-Côte d’Azur:tranche_0 | 0.082*** |
(0.001) | |
Observations | 4,242 |
R2 | 0.929 |
Adjusted R2 | 0.928 |
Residual Std. Error | 32.506 (df = 4214) |
F Statistic | 1,968.067*** (df = 28; 4214) |
Note: | p<0.1; p<0.05; p<0.01 |
On représente comme si on on avait fait un modèle par région pour faciliter la lecture des coefficients :
::stargazer(res_lm_r1, res_lm_r2, res_lm_r3, res_lm_r4, res_lm_r5, res_lm_r6, res_lm_r7,
stargazer
res_lm_r8, res_lm_r9, res_lm_r10, res_lm_r11, res_lm_r12, res_lm_r13, res_lm_r14, type = "html", column.labels = nom_region)
Dependent variable: | ||||||||||||||
hosp | ||||||||||||||
Auvergne-Rhône-Alpes | Hauts-de-France | Provence-Alpes-Côte d’Azur | Grand Est | Occitanie | Normandie | Nouvelle-Aquitaine | Centre-Val de Loire | Bourgogne-Franche-Comté | Bretagne | Corse | Pays de la Loire | Ile-de-France | DOM-TOM | |
(1) | (2) | (3) | (4) | (5) | (6) | (7) | (8) | (9) | (10) | (11) | (12) | (13) | (14) | |
tranche_0 | 0.064*** | 0.056*** | 0.082*** | 0.068*** | 0.054*** | 0.071*** | 0.062*** | 0.058*** | 0.074*** | 0.058*** | 0.044*** | 0.049*** | 0.058*** | 0.087*** |
(0.001) | (0.001) | (0.002) | (0.002) | (0.001) | (0.002) | (0.001) | (0.002) | (0.002) | (0.002) | (0.005) | (0.002) | (0.001) | (0.004) | |
Constant | 12.869*** | 27.695*** | 8.143* | 13.292*** | 3.084*** | 5.697*** | 2.556*** | 8.925*** | 9.762*** | 4.015** | 1.953* | 13.426*** | 30.271*** | 3.049 |
(1.924) | (4.572) | (4.493) | (1.829) | (0.690) | (2.153) | (0.850) | (1.470) | (2.040) | (1.822) | (0.983) | (2.051) | (3.785) | (1.899) | |
Observations | 504 | 210 | 252 | 420 | 546 | 210 | 504 | 252 | 336 | 168 | 84 | 210 | 336 | 210 |
R2 | 0.925 | 0.892 | 0.900 | 0.807 | 0.917 | 0.854 | 0.844 | 0.741 | 0.729 | 0.786 | 0.480 | 0.752 | 0.875 | 0.701 |
Adjusted R2 | 0.925 | 0.891 | 0.900 | 0.807 | 0.917 | 0.854 | 0.844 | 0.740 | 0.729 | 0.785 | 0.474 | 0.750 | 0.874 | 0.700 |
Residual Std. Error | 37.716 (df = 502) | 56.870 (df = 208) | 59.149 (df = 250) | 30.445 (df = 418) | 13.866 (df = 544) | 25.149 (df = 208) | 15.766 (df = 502) | 18.114 (df = 250) | 30.207 (df = 334) | 18.295 (df = 166) | 7.132 (df = 82) | 23.165 (df = 208) | 48.460 (df = 334) | 21.954 (df = 208) |
F Statistic | 6,205.862*** (df = 1; 502) | 1,710.871*** (df = 1; 208) | 2,251.697*** (df = 1; 250) | 1,751.469*** (df = 1; 418) | 5,986.162*** (df = 1; 544) | 1,219.137*** (df = 1; 208) | 2,720.026*** (df = 1; 502) | 716.005*** (df = 1; 250) | 900.440*** (df = 1; 334) | 610.581*** (df = 1; 166) | 75.817*** (df = 1; 82) | 629.304*** (df = 1; 208) | 2,329.489*** (df = 1; 334) | 487.572*** (df = 1; 208) |
Note: | p<0.1; p<0.05; p<0.01 |
Test:
On teste le modèle sur les données de la semaine actuelle:
<- predict(res_lm, newdata = my_basis[my_basis$semaine == "semaine_t00", ]) pred_1
plot(pred_1, my_basis[my_basis$semaine == "semaine_t00", "hosp"],
xlab = "valeurs prédites", ylab = "valeurs observées")
abline(a = 0, b = 1)
text(pred_1, my_basis[my_basis$semaine == "semaine_t00", "hosp"],
$semaine == "semaine_t00", "dep"], pos = 2) my_basis[my_basis
L’écart quadratique moyen est égal ici à :
mean((pred_1 - my_basis[my_basis$semaine == "semaine_t00", "hosp"]) ^ 2, na.rm = T)
## [1] 1051.304
Ici, on va faire un modèle qui prend en compte les classes d’âges. Les données d’hospitalisation par classe d’âge ne sont disponibles que par région. Le modèle est de la forme
\[y_{i,t}^a=\beta_0^a+\beta_1^ax_{i,t'}^a+\epsilon_{i,t}^a\] avec:
\(y_{i,t}\) le nombre d’entrées de la classe d’âge \(a\) à l’hôpital dans la région \(i\) sur la période \(t\), où \(t\) est une fenêtre de 7 jours.
\(x_{i,t'}\) est le nombre de testés positifs de la classe d’âge \(a\) dans la région \(i\) sur la période \(t'\) où \(t'\) correspond à la fenêtre \(t\), décalé de 10 jours.
En d’autres termes, on fait ici un modèle de régression par classe d’âge, toute région confondue. Cela suppose que le lien entre les tests virologiques et le nombre d’hospitalisation est homogène dans une classe d’âge quelque soit les régions.
On merge avec le nombre de test positifs:
# débord on aggrège le nombre de testés positifs par région
<- merge(test_by, dep_region, by = "dep")
test_by <- aggregate(test_by[, c("tranche_9", "tranche_19", "tranche_29", "tranche_39",
test_reg "tranche_49", "tranche_59", "tranche_69", "tranche_79",
"tranche_89", "tranche_90", "tranche_0")],
by = list(
semaine = test_by$semaine,
region = test_by$region), FUN = sum)
# ensuite, on fait le merge
<- merge(my_basis_age_wide, test_reg, by = c("semaine", "region")) my_basis_age_wide
Apprentissage:
On modélise sur les observations des semaines précédentes et on représente les résultats tranche d’âge par tranche d’âge
<- my_basis_age_wide[!(my_basis_age_wide$semaine %in%
apprentissage_sample c("semaine_t0-2", "semaine_t0-1", "semaine_t00")), ]
<- lm(hosp_9 ~ tranche_9, data = apprentissage_sample)
res_lm_9 <- lm(hosp_19 ~ tranche_19, data = apprentissage_sample)
res_lm_19 <- lm(hosp_29 ~ tranche_29, data = apprentissage_sample)
res_lm_29 <- lm(hosp_39 ~ tranche_39, data = apprentissage_sample)
res_lm_39 <- lm(hosp_49 ~ tranche_49, data = apprentissage_sample)
res_lm_49 <- lm(hosp_59 ~ tranche_59, data = apprentissage_sample)
res_lm_59 <- lm(hosp_69 ~ tranche_69, data = apprentissage_sample)
res_lm_69 <- lm(hosp_79 ~ tranche_79, data = apprentissage_sample)
res_lm_79 <- lm(hosp_89 ~ tranche_89, data = apprentissage_sample)
res_lm_89 <- lm(hosp_90 ~ tranche_90, data = apprentissage_sample) res_lm_90
::stargazer(res_lm_9, res_lm_19, res_lm_29, res_lm_39, res_lm_49, res_lm_59,
stargazertype = "html") res_lm_69, res_lm_79, res_lm_89, res_lm_90,
Dependent variable: | ||||||||||
hosp_9 | hosp_19 | hosp_29 | hosp_39 | hosp_49 | hosp_59 | hosp_69 | hosp_79 | hosp_89 | hosp_90 | |
(1) | (2) | (3) | (4) | (5) | (6) | (7) | (8) | (9) | (10) | |
tranche_9 | 0.013*** | |||||||||
(0.001) | ||||||||||
tranche_19 | 0.004*** | |||||||||
(0.0001) | ||||||||||
tranche_29 | 0.008*** | |||||||||
(0.0002) | ||||||||||
tranche_39 | 0.015*** | |||||||||
(0.0003) | ||||||||||
tranche_49 | 0.023*** | |||||||||
(0.0003) | ||||||||||
tranche_59 | 0.048*** | |||||||||
(0.001) | ||||||||||
tranche_69 | 0.109*** | |||||||||
(0.001) | ||||||||||
tranche_79 | 0.226*** | |||||||||
(0.003) | ||||||||||
tranche_89 | 0.347*** | |||||||||
(0.005) | ||||||||||
tranche_90 | 0.288*** | |||||||||
(0.005) | ||||||||||
Constant | 0.754*** | 0.947*** | 2.680*** | 3.307*** | 3.933*** | 4.632*** | 7.255*** | 10.498*** | 13.986*** | 9.906*** |
(0.234) | (0.192) | (0.364) | (0.470) | (0.576) | (1.006) | (1.346) | (2.181) | (2.612) | (1.656) | |
Observations | 588 | 588 | 588 | 588 | 588 | 588 | 588 | 588 | 588 | 588 |
R2 | 0.380 | 0.538 | 0.763 | 0.839 | 0.885 | 0.905 | 0.926 | 0.892 | 0.895 | 0.835 |
Adjusted R2 | 0.379 | 0.537 | 0.763 | 0.839 | 0.885 | 0.905 | 0.925 | 0.892 | 0.895 | 0.834 |
Residual Std. Error (df = 586) | 4.656 | 3.857 | 7.447 | 9.746 | 11.911 | 20.735 | 27.628 | 44.374 | 52.418 | 33.257 |
F Statistic (df = 1; 586) | 359.798*** | 681.827*** | 1,886.195*** | 3,063.586*** | 4,499.760*** | 5,604.026*** | 7,289.877*** | 4,850.190*** | 5,001.858*** | 2,960.571*** |
Note: | p<0.1; p<0.05; p<0.01 |
Test:
On teste le modèle sur les données de la semaine actuelle. On revient sur les données départementales, on suppose donc que les modèles estimés pour chaque tranche d’âge sur les régions est valable aussi pour les départements.
<- my_basis[my_basis$semaine == "semaine_t00", ]
test_sample <- predict(res_lm_9, newdata = test_sample)
pred_9 <- predict(res_lm_19, newdata = test_sample)
pred_19 <- predict(res_lm_29, newdata = test_sample)
pred_29 <- predict(res_lm_39, newdata = test_sample)
pred_39 <- predict(res_lm_49, newdata = test_sample)
pred_49 <- predict(res_lm_59, newdata = test_sample)
pred_59 <- predict(res_lm_69, newdata = test_sample)
pred_69 <- predict(res_lm_79, newdata = test_sample)
pred_79 <- predict(res_lm_89, newdata = test_sample)
pred_89 <- predict(res_lm_90, newdata = test_sample) pred_90
On a donc une prédiction par tranche d’âge et pour obtenir la prédiction finale, il faut donc faire la somme sur les différentes prédictions :
<- pred_9 + pred_19 + pred_29 + pred_39 + pred_49 + pred_59 + pred_69 +
pred_2 + pred_89 + pred_90 pred_79
plot(pred_2, my_basis[my_basis$semaine == "semaine_t00", "hosp"],
xlab = "valeurs prédites", ylab = "valeurs observées")
abline(a = 0, b = 1)
text(pred_2, my_basis[my_basis$semaine == "semaine_t00", "hosp"],
$semaine == "semaine_t00", "dep"], pos = 2) my_basis[my_basis
L’écart quadratique moyen est égal ici à :
mean((pred_2 - my_basis[my_basis$semaine == "semaine_t00", "hosp"]) ^ 2, na.rm = T)
## [1] 3328.613
On utilise la même stratégie que celle présentée pour prédire le nombre de cas positifs.
Etape d’apprentissage : on entraîne l’agorithme sur les données passées en enlevant la dernière semaine observée et on prédit sur cette semaine afin de calculer les écarts quadratiques avec les valeurs observées.
<- my_basis[my_basis$semaine == "semaine_t00", "dep"]
nom_dep <- numeric(length(nom_dep))
pred_3a <- numeric(length(nom_dep))
pred_3b <- numeric(length(nom_dep))
pred_3c for (k in 1:length(nom_dep)) {
<- hospital[!(hospital$semaine %in% c("semaine_t0-2", "semaine_t0-1", "semaine_t00")) &
temp $dep == nom_dep[k], ]
hospital<- zoo(temp$incid_hosp, temp$jour)
my_ts <- diff(my_ts)
my_ts_diff # tseries::adf.test(my_ts)
# tseries::adf.test(my_ts_diff)
if (nom_dep[k] %in% c("975", "977", "978")) {
<- NA
pred_3[k] else {
} <- forecast::auto.arima(my_ts_diff)
my_mod <- as.numeric(forecast(my_mod)$mean)
forecast_my_mod <- sum((as.numeric(my_ts[length(my_ts)]) + cumsum(forecast_my_mod))[1:7])
pred_3a[k] # modèles exponentiels
# Méthode 2 : lissage exponentiel
<- ets(my_ts)
my_mod_exp <- as.numeric(forecast(my_mod_exp)$mean)
forecast_my_mod_exp <- ifelse(forecast_my_mod_exp > 0, forecast_my_mod_exp, 0)
forecast_my_mod_exp <- round(sum(forecast_my_mod_exp[1:7]), 0)
pred_3b[k] # Méthode 3 : lissage exponentiel sur données hebdomadaires
<- my_basis[my_basis$dep == nom_dep[k] & !(my_basis$semaine %in%
temp c("semaine_t0-2", "semaine_t0-1", "semaine_t00")), ]
<- zoo(temp$hosp, temp$jour)
my_ts_exp <- ets(my_ts_exp)
my_mod_exp_2 <- as.numeric(forecast(my_mod_exp_2)$mean)
forecast_my_mod_exp <- ifelse(forecast_my_mod_exp > 0, forecast_my_mod_exp, 0)
forecast_my_mod_exp <- round(forecast_my_mod_exp[1], 0)
pred_3c[k]
} }
On obtient le graphique suivant de valeurs prédites/valeurs observées :
<- par(mfrow = c(1, 3), oma = c(0, 0, 0, 0))
op plot(pred_3a, my_basis[my_basis$semaine == "semaine_t00", "hosp"],
xlab = "valeurs prédites", ylab = "valeurs observées", main = "Box-Jenkins")
abline(a = 0, b = 1)
text(pred_3a, my_basis[my_basis$semaine == "semaine_t00", "hosp"],
$semaine == "semaine_t00", "dep"], pos = 2)
my_basis[my_basisplot(pred_3b, my_basis[my_basis$semaine == "semaine_t00", "hosp"],
xlab = "valeurs prédites", ylab = "valeurs observées", main = "Lissage exponentiel journalier")
abline(a = 0, b = 1)
text(pred_3b, my_basis[my_basis$semaine == "semaine_t00", "hosp"],
$semaine == "semaine_t00", "dep"], pos = 2)
my_basis[my_basisplot(pred_3c, my_basis[my_basis$semaine == "semaine_t00", "hosp"],
xlab = "valeurs prédites", ylab = "valeurs observées", main = "Lissage exponentiel hebdomadaire")
abline(a = 0, b = 1)
text(pred_3c, my_basis[my_basis$semaine == "semaine_t00", "hosp"],
$semaine == "semaine_t00", "dep"], pos = 2) my_basis[my_basis
par(op)
L’écart quadratique moyen est égal ici à :
c(mean((pred_3a - my_basis[my_basis$semaine == "semaine_t00", "hosp"]) ^ 2, na.rm = T),
mean((pred_3b - my_basis[my_basis$semaine == "semaine_t00", "hosp"]) ^ 2, na.rm = T),
mean((pred_3c - my_basis[my_basis$semaine == "semaine_t00", "hosp"]) ^ 2, na.rm = T)
)
## [1] 969.8112 969.6832 547.8317
Les 3 prédictions sont très proches et on va choisir un algorithme de type stepwise sur les prédictions pour choisir la meilleure combinaison des modèles de séries temporelles.
<- step(lm(my_basis[my_basis$semaine == "semaine_t00", "hosp"] ~ pred_3a + pred_3b + pred_3c - 1)) lm_3_ts
## Start: AIC=632.21
## my_basis[my_basis$semaine == "semaine_t00", "hosp"] ~ pred_3a +
## pred_3b + pred_3c - 1
##
## Df Sum of Sq RSS AIC
## <none> 49772 632.21
## - pred_3a 1 2146.6 51919 634.47
## - pred_3b 1 4251.2 54024 638.49
## - pred_3c 1 6447.6 56220 642.51
<- predict(lm_3_ts)
pred_3 mean((pred_3 - na.omit(my_basis[my_basis$semaine == "semaine_t00", "hosp"])) ^ 2)
## [1] 492.7954
On a donc 3 prédictions obtenues selon :
Combinaison des prédictions:
<- lm(my_basis[my_basis$semaine == "semaine_t00", "hosp"] ~ pred_1 + pred_2 + pred_3 - 1)
lm_3 mean((predict(lm_3) - na.omit(my_basis[my_basis$semaine == "semaine_t00", "hosp"])) ^ 2)
## [1] 430.5989
## Start: AIC=1355.43
## y_true ~ pred_3a_s2 + pred_3b_s2 + pred_3c_s2 - 1
##
## Df Sum of Sq RSS AIC
## - pred_3a_s2 1 230 161140 1353.7
## <none> 160910 1355.4
## - pred_3b_s2 1 1743 162653 1355.6
## - pred_3c_s2 1 42003 202913 1400.3
##
## Step: AIC=1353.72
## y_true ~ pred_3b_s2 + pred_3c_s2 - 1
##
## Df Sum of Sq RSS AIC
## <none> 161140 1353.7
## - pred_3b_s2 1 1783 162924 1353.9
## - pred_3c_s2 1 46562 207702 1403.0
On prédit le nombre d’hospitalisations :
du [15 mars 2021; 21 mars 2021] en utilisant les vrais valeurs du nombre de testé positifs la semaine du [05 mars 2021; 11 mars 2021].
du [22 mars 2021; 28 mars 2021] en utilisant les valeurs prédites du nombre de testé positifs la semaine du [12 mars 2021; 18 mars 2021].
Avant de faire cela, on actualise en incluant dans l’étape d’apprentissage les données de la dernière semaine observée:
# modèle 1
<- lm(hosp ~ tranche_0, data = my_basis[!(my_basis$semaine %in% "semaine_t0-1"), ])
res_lm # modèle 2
<- my_basis_age_wide[!(my_basis_age_wide$semaine %in%
apprentissage_sample c("semaine_t0-1")), ]
<- lm(hosp_9 ~ tranche_9, data = apprentissage_sample)
res_lm_9 <- lm(hosp_19 ~ tranche_19, data = apprentissage_sample)
res_lm_19 <- lm(hosp_29 ~ tranche_29, data = apprentissage_sample)
res_lm_29 <- lm(hosp_39 ~ tranche_39, data = apprentissage_sample)
res_lm_39 <- lm(hosp_49 ~ tranche_49, data = apprentissage_sample)
res_lm_49 <- lm(hosp_59 ~ tranche_59, data = apprentissage_sample)
res_lm_59 <- lm(hosp_69 ~ tranche_69, data = apprentissage_sample)
res_lm_69 <- lm(hosp_79 ~ tranche_79, data = apprentissage_sample)
res_lm_79 <- lm(hosp_89 ~ tranche_89, data = apprentissage_sample)
res_lm_89 <- lm(hosp_90 ~ tranche_90, data = apprentissage_sample)
res_lm_90
# On prédit avec la méthode 1
<- my_basis[my_basis$semaine %in% c("semaine_t0-1", "semaine_t0-2"), ]
new_data <- predict(res_lm, newdata = new_data)
pred_1 # On prédit avec la méthode 2
<- my_basis[my_basis$semaine %in% c("semaine_t0-1", "semaine_t0-2"), ]
test_sample <- predict(res_lm_9, newdata = test_sample)
pred_9 <- predict(res_lm_19, newdata = test_sample)
pred_19 <- predict(res_lm_29, newdata = test_sample)
pred_29 <- predict(res_lm_39, newdata = test_sample)
pred_39 <- predict(res_lm_49, newdata = test_sample)
pred_49 <- predict(res_lm_59, newdata = test_sample)
pred_59 <- predict(res_lm_69, newdata = test_sample)
pred_69 <- predict(res_lm_79, newdata = test_sample)
pred_79 <- predict(res_lm_89, newdata = test_sample)
pred_89 <- predict(res_lm_90, newdata = test_sample)
pred_90 <- pred_9 + pred_19 + pred_29 + pred_39 + pred_49 + pred_59 + pred_69 +
pred_2 + pred_89 + pred_90
pred_79
# on prédit avec le modèle 3, mais on actualise les prédictions semaine par semaine
<- matrix(0, length(nom_dep), 2)
pred_3 for (k in 1:length(nom_dep)) {
if (nom_dep[k] %in% c("975", "977", "978")) {
<- NA
pred_3[k, ] else {
} <- hospital[!(hospital$semaine %in% c("semaine_t0-2", "semaine_t0-1")) &
temp $dep == nom_dep[k], ]
hospital<- zoo(temp$incid_hosp, temp$jour)
my_ts <- diff(my_ts)
my_ts_diff # tseries::adf.test(my_ts)
# tseries::adf.test(my_ts_diff)
# predictions à 7 jours
<- forecast::auto.arima(my_ts_diff)
my_mod <- as.numeric(forecast(my_mod, h = 14)$mean)
forecast_my_mod <- sum((as.numeric(my_ts[length(my_ts)]) + cumsum(forecast_my_mod))[1:7])
pred_3a_s1 # prediction à 14 jours
<- sum((as.numeric(my_ts[length(my_ts)]) + cumsum(forecast_my_mod))[1:14]) - pred_3a_s1
pred_3a_s2 # Lissage exponentiel
<- ets(my_ts)
my_mod_exp <- as.numeric(forecast(my_mod_exp, h = 14)$mean)
forecast_my_mod_exp <- ifelse(forecast_my_mod_exp > 0, forecast_my_mod_exp, 0)
forecast_my_mod_exp <- round(sum(forecast_my_mod_exp[1:7]), 0)
pred_3b_s1 <- round(sum(forecast_my_mod_exp[1:14]), 0) - pred_3b_s1
pred_3b_s2 # Méthode 3 : lissage exponentiel sur données hebdomadaires
<- my_basis[my_basis$dep == nom_dep[k] & !(my_basis$semaine %in%
temp c("semaine_t0-2", "semaine_t0-1")), ]
<- zoo(temp$hosp, temp$jour)
my_ts_exp <- ets(my_ts_exp)
my_mod_exp_2 <- as.numeric(forecast(my_mod_exp_2)$mean)
forecast_my_mod_exp <- ifelse(forecast_my_mod_exp > 0, forecast_my_mod_exp, 0)
forecast_my_mod_exp <- round(forecast_my_mod_exp[1], 0)
pred_3c_s1 <- round(forecast_my_mod_exp[2], 0)
pred_3c_s2
# prédictions des time series
1] <- predict(lm_3_ts, newdata = data.frame(pred_3a = pred_3a_s1,
pred_3[k, pred_3b = pred_3b_s1,
pred_3c = pred_3c_s1))
# prediction à 14 jours
2] <- predict(lm_3b_ts, newdata = data.frame(pred_3a_s2 = pred_3a_s2,
pred_3[k, pred_3b_s2 = pred_3b_s2,
pred_3c_s2 = pred_3c_s2))
}
}<- as.vector(pred_3)
pred_3 # On fait le mélande des deux prédictions
<- predict(lm_3, newdata = data.frame(pred_1 = pred_1[new_data$semaine == "semaine_t0-1"],
res_pred_a pred_2 = pred_2[test_sample$semaine == "semaine_t0-1"],
pred_3 = pred_3[1:(length(pred_3) / 2)]))
<- predict(lm_3b, newdata = data.frame(
res_pred_b pred_1_s2 = pred_1[new_data$semaine == "semaine_t0-2"],
pred_2_s2 = pred_2[test_sample$semaine == "semaine_t0-2"],
pred_3_s2 = pred_3[((length(pred_3) / 2) + 1):length(pred_3)]))
<- my_basis[my_basis$semaine %in% "semaine_t0-1", ]
new_data $semaine %in% "semaine_t0-1", "hosp"] <- res_pred_a
my_basis[my_basis$semaine %in% "semaine_t0-2", "hosp"] <- res_pred_b
my_basis[my_basis$next_week <- res_pred_a
new_data$next_two_week <- res_pred_b new_data
On va représenter l’évolution du nombre de nouveaux patients hospitalisés dans un intervalle de temps de 4 semaines :
"last_week"] <- my_basis[my_basis$semaine == "semaine_t01", "hosp"]
new_data[, "this_week"] <- my_basis[my_basis$semaine == "semaine_t00", "hosp"]
new_data[, <- tidyr::pivot_longer(data = select(new_data, dep, region, last_week, this_week, next_week, next_two_week),
new_data_long col = 3:6,
names_to = "semaine",
values_to = "hospitalisations")
$semaine <- factor(new_data_long$semaine,
new_data_longlevels = c("last_week", "this_week", "next_week", "next_two_week"),
labels = c(paste0("[", format(to_day - 14, '%d %b'), "; ",
format(to_day - 8, '%d %b'), "]"),
paste0("[", format(to_day - 7, '%d %b'), "; ",
format(to_day - 1, '%d %b'), "]"),
paste0("[", format(to_day, '%d %b'), "; ",
format(to_day + 6, '%d %b'), "]"),
paste0("[", format(to_day + 7, '%d %b'), "; ",
format(to_day + 13, '%d %b'), "]"))
)# On ajoute aux données de la semaine dernière :
$region <- factor(new_data_long$region, levels = hosp_region$region)
new_data_long<- ggplot(new_data_long, aes(x = semaine, y = hospitalisations, group = dep))+
p geom_line() +
facet_wrap(~region)
::ggplotly(p) plotly
On aggrège les données à la France entière:
<- my_basis %>%
my_basis_fr group_by(semaine, jour) %>%
summarise(hosp = sum(hosp),
rea = sum(rea),
dc = sum(dc))
<- ggplot(data = filter(my_basis_fr, semaine %in% c("semaine_t0-2", "semaine_t0-1", "semaine_t00")),
p aes(x = jour, y = hosp)) +
geom_line(col = "red") +
geom_line(data = filter(my_basis_fr, !(semaine %in% c("semaine_t0-2", "semaine_t0-1"))),
aes(x = jour, y = hosp)) +
labs(title = "Prédiction des nouvelles hospitalisations dans les 14 jours",
x = "semaine",
y = "hospitalisations",
fill = "Age")
::ggplotly(p) plotly
L’idée est d’expliquer le nombre de nouvelles réanimations la semaine \(t\) par le nombre de nouvelles hospitalisations la semaine \(t-1\).
Ainsi on sera en mesure de prédire le nombre de nouvelles réanimations d’une part la semaine à venir, mais aussi la semaine d’après si on utilise les prédictions du nombre d’hospitalisation la semaine à venir.
On prépare les données et on représente le nombre de nouvelles réanimations par semaine et par département en fonction du nombre de nouvelles hospitalisations la semaine d’avant et on constate un lien très fort.
<- my_basis %>%
my_basis_temp filter(semaine == "semaine_t0-2")
$hosp <- NA
my_basis_temp$semaine <- "semaine_t0-3"
my_basis_temp$jour <- my_basis_temp$jour + 7
my_basis_temppaste0("tranche_", c(9, 19, 29, 39, 49, 59, 69, 79, 89, 90, 0))] <- NA
my_basis_temp[, <- rbind(my_basis_temp, my_basis)
my_basis <- my_basis %>%
my_basis_rea select(dep, semaine, jour, region, rea)
<- my_basis %>%
temp_hosp select(dep, jour, hosp) %>%
mutate(jour = jour + 7)
<- merge(my_basis_rea, temp_hosp, by = c("jour", "dep"), all.x = T)
my_basis_rea <- my_basis_rea %>%
my_basis_rea
as.data.frame<- my_basis_rea[order(my_basis_rea$jour, decreasing = T), ] my_basis_rea
<- ggplot(my_basis_rea) +
p aes(x = hosp, y = rea) +
geom_point() +
geom_smooth(method = "loess") +
geom_smooth(method = "lm",
col = "red") +
facet_wrap(~ region)
::ggplotly(p) plotly
On ne va faire que deux modèles :
un modèle régional où on explique les nouvelles réanimations des départements au sein d’une même région.
un modèle de série temporelles où on explique dans un département les réanimations à l’instant \(t\) par les valeurs du passé.
On n’utilise pas le modèle qui utilise les classes d’âges car c’est difficile d’avoir le nombre de nouvelles réanimations par jour/département par classe d’âge. Il se peut donc que les prédictions soient sous-estimées dans le cas où la distribution des patients hospitalisés agés évolue positivement au cours du temps.
Apprentissage:
On modélise sur les observations des semaines précédentes:
<- lm(rea ~ region + hosp:region - 1,
res_lm_rea_1 data = my_basis_rea[!(my_basis_rea$semaine %in% c("semaine_t0-2", "semaine_t0-1", "semaine_t00")), ])
::stargazer(res_lm_rea_1, type = "html") stargazer
Dependent variable: | |
rea | |
regionAuvergne-Rhône-Alpes | -0.449 |
(0.400) | |
regionBourgogne-Franche-Comté | 0.921* |
(0.527) | |
regionBretagne | 0.835 |
(0.757) | |
regionCentre-Val de Loire | -0.078 |
(0.657) | |
regionCorse | 0.856 |
(1.023) | |
regionDOM-TOM | 1.498** |
(0.642) | |
regionGrand Est | -0.250 |
(0.482) | |
regionHauts-de-France | -0.371 |
(0.645) | |
regionIle-de-France | -1.306** |
(0.638) | |
regionNormandie | 0.564 |
(0.657) | |
regionNouvelle-Aquitaine | -0.071 |
(0.411) | |
regionOccitanie | -0.189 |
(0.384) | |
regionPays de la Loire | 0.471 |
(0.733) | |
regionProvence-Alpes-Côte d’Azur | -0.984* |
(0.578) | |
regionAuvergne-Rhône-Alpes:hosp | 0.157*** |
(0.002) | |
regionBourgogne-Franche-Comté:hosp | 0.116*** |
(0.007) | |
regionBretagne:hosp | 0.108*** |
(0.015) | |
regionCentre-Val de Loire:hosp | 0.169*** |
(0.013) | |
regionCorse:hosp | 0.127 |
(0.084) | |
regionDOM-TOM:hosp | 0.125*** |
(0.013) | |
regionGrand Est:hosp | 0.149*** |
(0.005) | |
regionHauts-de-France:hosp | 0.180*** |
(0.003) | |
regionIle-de-France:hosp | 0.201*** |
(0.003) | |
regionNormandie:hosp | 0.125*** |
(0.008) | |
regionNouvelle-Aquitaine:hosp | 0.156*** |
(0.008) | |
regionOccitanie:hosp | 0.208*** |
(0.007) | |
regionPays de la Loire:hosp | 0.128*** |
(0.011) | |
regionProvence-Alpes-Côte d’Azur:hosp | 0.165*** |
(0.003) | |
Observations | 4,141 |
R2 | 0.883 |
Adjusted R2 | 0.882 |
Residual Std. Error | 7.520 (df = 4113) |
F Statistic | 1,104.828*** (df = 28; 4113) |
Note: | p<0.1; p<0.05; p<0.01 |
Test:
On teste le modèle sur les données de la semaine actuelle:
<- predict(res_lm_rea_1, newdata = my_basis_rea[my_basis_rea$semaine == "semaine_t00", ]) pred_rea_1
plot(pred_rea_1, my_basis_rea[my_basis_rea$semaine == "semaine_t00", "rea"],
xlab = "valeurs prédites", ylab = "valeurs observées")
abline(a = 0, b = 1)
text(pred_rea_1, my_basis_rea[my_basis_rea$semaine == "semaine_t00", "rea"],
$semaine == "semaine_t00", "dep"], pos = 2) my_basis_rea[my_basis_rea
L’écart quadratique moyen est égal ici à :
mean((pred_rea_1 - my_basis_rea[my_basis_rea$semaine == "semaine_t00", "rea"]) ^ 2, na.rm = T)
## [1] 268.4507
On utilise la même stratégie que celle présentée pour prédire le nombre de nouveaux cas positifs et de nouvelles réanimations.
Etape d’apprentissage : on entraîne l’agorithme sur les données passées en enlevant la dernière semaine observée et on prédit sur cette semaine afin de calculer les écarts quadratiques avec les valeurs observées.
<- my_basis_rea[my_basis_rea$semaine == "semaine_t00", "dep"]
nom_dep <- numeric(length(nom_dep))
pred_rea_2a <- numeric(length(nom_dep))
pred_rea_2b <- numeric(length(nom_dep))
pred_rea_2c for (k in 1:length(nom_dep)) {
<- hospital[!(hospital$semaine %in% c("semaine_t0-2", "semaine_t0-1", "semaine_t00")) &
temp $dep == nom_dep[k], ]
hospital<- zoo(temp$incid_rea, temp$jour)
my_ts <- diff(my_ts)
my_ts_diff # tseries::adf.test(my_ts)
# tseries::adf.test(my_ts_diff)
if (nom_dep[k] %in% c("975", "977", "978")) {
<- NA
pred_rea_2[k] else {
} # box jenkins
<- forecast::auto.arima(my_ts_diff)
my_mod <- as.numeric(forecast(my_mod)$mean)
forecast_my_mod <- sum((as.numeric(my_ts[length(my_ts)]) + cumsum(forecast_my_mod))[1:7])
pred_rea_2a[k] # modèles exponentiels
# Méthode 2 : lissage exponentiel
<- ets(my_ts)
my_mod_exp <- as.numeric(forecast(my_mod_exp)$mean)
forecast_my_mod_exp <- ifelse(forecast_my_mod_exp > 0, forecast_my_mod_exp, 0)
forecast_my_mod_exp <- round(sum(forecast_my_mod_exp[1:7]), 0)
pred_rea_2b[k] # Méthode 3 : lissage exponentiel sur données hebdomadaires
<- my_basis[my_basis$dep == nom_dep[k] & !(my_basis$semaine %in%
temp c("semaine_t0-3", "semaine_t0-2", "semaine_t0-1", "semaine_t00")), ]
<- zoo(temp$rea, temp$jour)
my_ts_exp <- ets(my_ts_exp)
my_mod_exp_2 <- as.numeric(forecast(my_mod_exp_2)$mean)
forecast_my_mod_exp <- ifelse(forecast_my_mod_exp > 0, forecast_my_mod_exp, 0)
forecast_my_mod_exp <- round(forecast_my_mod_exp[1], 0)
pred_rea_2c[k]
} }
On observe le graphique des valeurs prédites/valeurs observées :
<- par(mfrow = c(1, 3), oma = c(0, 0, 0, 0))
op plot(pred_rea_2a, my_basis_rea[my_basis_rea$semaine == "semaine_t00", "rea"],
xlab = "valeurs prédites", ylab = "valeurs observées", main = "Box-Jenkins")
abline(a = 0, b = 1)
text(pred_rea_2a, my_basis_rea[my_basis_rea$semaine == "semaine_t00", "rea"],
$semaine == "semaine_t00", "dep"], pos = 2)
my_basis_rea[my_basis_reaplot(pred_rea_2b, my_basis_rea[my_basis_rea$semaine == "semaine_t00", "rea"],
xlab = "valeurs prédites", ylab = "valeurs observées", main = "Lissage exponentiel journalier")
abline(a = 0, b = 1)
text(pred_rea_2b, my_basis_rea[my_basis_rea$semaine == "semaine_t00", "rea"],
$semaine == "semaine_t00", "dep"], pos = 2)
my_basis_rea[my_basis_reaplot(pred_rea_2c, my_basis_rea[my_basis_rea$semaine == "semaine_t00", "rea"],
xlab = "valeurs prédites", ylab = "valeurs observées", main = "Lissage exponentiel hebdomadaire")
abline(a = 0, b = 1)
text(pred_rea_2c, my_basis_rea[my_basis_rea$semaine == "semaine_t00", "rea"],
$semaine == "semaine_t00", "dep"], pos = 2) my_basis_rea[my_basis_rea
L’écart quadratique moyen est égal ici à :
c(mean((pred_rea_2a - my_basis_rea[my_basis_rea$semaine == "semaine_t00", "rea"]) ^ 2, na.rm = T),
mean((pred_rea_2b - my_basis_rea[my_basis_rea$semaine == "semaine_t00", "rea"]) ^ 2, na.rm = T),
mean((pred_rea_2c - my_basis_rea[my_basis_rea$semaine == "semaine_t00", "rea"]) ^ 2, na.rm = T)
)
## [1] 92.58207 92.70297 64.36634
Les 3 prédictions sont très proches et on va choisir un algorithme de type stepwise sur les prédictions pour choisir la meilleure combinaison et ne conserver qu’une seule prédiction basée sur les séries temporelles:
<- step(lm(my_basis[my_basis$semaine == "semaine_t00", "rea"] ~
lm_2_rea_ts + pred_rea_2b + pred_rea_2c - 1)) pred_rea_2a
## Start: AIC=389.98
## my_basis[my_basis$semaine == "semaine_t00", "rea"] ~ pred_rea_2a +
## pred_rea_2b + pred_rea_2c - 1
##
## Df Sum of Sq RSS AIC
## - pred_rea_2b 1 20.06 4543.0 388.43
## - pred_rea_2a 1 53.51 4576.4 389.17
## <none> 4522.9 389.98
## - pred_rea_2c 1 2741.32 7264.2 435.84
##
## Step: AIC=388.43
## my_basis[my_basis$semaine == "semaine_t00", "rea"] ~ pred_rea_2a +
## pred_rea_2c - 1
##
## Df Sum of Sq RSS AIC
## - pred_rea_2a 1 83.8 4626.8 388.27
## <none> 4543.0 388.43
## - pred_rea_2c 1 3300.4 7843.4 441.58
##
## Step: AIC=388.27
## my_basis[my_basis$semaine == "semaine_t00", "rea"] ~ pred_rea_2c -
## 1
##
## Df Sum of Sq RSS AIC
## <none> 4627 388.27
## - pred_rea_2c 1 167312 171939 751.42
<- predict(lm_2_rea_ts)
pred_rea_2 mean((pred_rea_2 - na.omit(my_basis[my_basis$semaine == "semaine_t00", "rea"])) ^ 2)
## [1] 45.80962
Combinaison des prédictions: on peut envisager de faire un panaché des deux prédictions. Autrement dit, on fait un modèle linéaire (avec une procédure stepwise) du nombre de réanimations observée la semaine t0 en fonction des 2 méthodes de prédictions. On obtient l’écart-quadratique moyen suivant:
<- lm(my_basis_rea[my_basis_rea$semaine == "semaine_t00", "rea"] ~
lm_rea_3 + pred_rea_2 - 1)
pred_rea_1 mean((predict(lm_rea_3) - na.omit(my_basis_rea[my_basis_rea$semaine == "semaine_t00", "rea"])) ^ 2)
## [1] 38.79501
On adapte le poids des prédictions en fonction de la semaine à prédire
<- c("semaine_t0-3", "semaine_t0-2", "semaine_t0-1", "semaine_t00")
semaine_to_drop <- pred_rea_1
pred_rea_1_s2 <- pred_rea_2a
pred_rea_2a_s2 <- pred_rea_2b
pred_rea_2b_s2 <- pred_rea_2c
pred_rea_2c_s2
<- my_basis_rea[my_basis_rea$semaine == "semaine_t00", "rea"]
y_true
for (j in 0:0) {
<- paste0("semaine_t0", j)
semaine_to_estim <- c(y_true, my_basis[my_basis$semaine == semaine_to_estim, "rea"])
y_true <- c(semaine_to_drop, paste0("semaine_t0", j + 1))
semaine_to_drop <- lm(rea ~ region + hosp:region - 1,
res_lm_rea_1 data = my_basis_rea[!(my_basis_rea$semaine %in% semaine_to_drop), ])
<- c(pred_rea_1_s2,
pred_rea_1_s2 round(predict(res_lm_rea_1, newdata = my_basis_rea[my_basis_rea$semaine == semaine_to_estim, ])))
<- numeric(length(nom_dep))
pred_rea_2a_temp <- numeric(length(nom_dep))
pred_rea_2b_temp <- numeric(length(nom_dep))
pred_rea_2c_temp
for (k in 1:length(nom_dep)) {
<- hospital[!(hospital$semaine %in% semaine_to_drop) &
temp $dep == nom_dep[k], ]
hospital<- zoo(temp$incid_rea, temp$jour)
my_ts <- diff(my_ts)
my_ts_diff # tseries::adf.test(my_ts)
# tseries::adf.test(my_ts_diff)
if (nom_dep[k] %in% c("975", "977", "978")) {
<- NA
pred_rea_2[k] else {
} <- forecast::auto.arima(my_ts_diff)
my_mod <- as.numeric(forecast(my_mod, h = 14)$mean)
forecast_my_mod <- sum((as.numeric(my_ts[length(my_ts)]) + cumsum(forecast_my_mod))[1:7])
temp <- sum((as.numeric(my_ts[length(my_ts)]) + cumsum(forecast_my_mod))[1:14]) - temp
pred_rea_2a_temp[k] # modèles exponentiels
# Méthode 2 : lissage exponentiel
<- ets(my_ts)
my_mod_exp <- as.numeric(forecast(my_mod_exp, h = 14)$mean)
forecast_my_mod_exp <- ifelse(forecast_my_mod_exp > 0, forecast_my_mod_exp, 0)
forecast_my_mod_exp <- round(sum(forecast_my_mod_exp[1:7]), 0)
temp <- round(sum(forecast_my_mod_exp[1:14]), 0) - temp
pred_rea_2b_temp[k] # Méthode 3 : lissage exponentiel sur données hebdomadaires
<- my_basis[my_basis$dep == nom_dep[k] & !(my_basis$semaine %in% semaine_to_drop), ]
temp <- zoo(temp$rea, temp$jour)
my_ts_exp if (all(my_ts_exp == 0)) {
<- 0
pred_rea_2c_temp[k] else {
} <- ets(my_ts_exp)
my_mod_exp_2 <- as.numeric(forecast(my_mod_exp_2)$mean)
forecast_my_mod_exp <- ifelse(forecast_my_mod_exp > 0, forecast_my_mod_exp, 0)
forecast_my_mod_exp <- round(forecast_my_mod_exp[2], 0)
pred_rea_2c_temp[k]
}
}
}<- c(pred_rea_2a_s2, pred_rea_2a_temp)
pred_rea_2a_s2 <- c(pred_rea_2b_s2, pred_rea_2b_temp)
pred_rea_2b_s2 <- c(pred_rea_2c_s2, pred_rea_2c_temp)
pred_rea_2c_s2
}
<- step(lm(y_true ~ pred_rea_2a_s2 + pred_rea_2b_s2 + pred_rea_2c_s2 - 1)) lm_2_rea_ts_s1
## Start: AIC=881.57
## y_true ~ pred_rea_2a_s2 + pred_rea_2b_s2 + pred_rea_2c_s2 - 1
##
## Df Sum of Sq RSS AIC
## - pred_rea_2b_s2 1 7.0 15417 879.66
## - pred_rea_2a_s2 1 56.9 15467 880.31
## <none> 15410 881.57
## - pred_rea_2c_s2 1 9136.4 24546 973.61
##
## Step: AIC=879.66
## y_true ~ pred_rea_2a_s2 + pred_rea_2c_s2 - 1
##
## Df Sum of Sq RSS AIC
## <none> 15417 879.66
## - pred_rea_2a_s2 1 228.6 15645 880.63
## - pred_rea_2c_s2 1 14358.5 29775 1010.62
<- predict(lm_2_rea_ts_s1)
pred_rea_2_s2
<- lm(y_true ~ pred_rea_1_s2 + pred_rea_2_s2 - 1)
lm_rea_3b
#######
<- c("semaine_t0-3", "semaine_t0-2", "semaine_t0-1", "semaine_t00", "semaine_t01")
semaine_to_drop <- pred_rea_1
pred_rea_1_s3 <- pred_rea_2a
pred_rea_2a_s3 <- pred_rea_2b
pred_rea_2b_s3 <- pred_rea_2c
pred_rea_2c_s3
<- my_basis_rea[my_basis_rea$semaine == "semaine_t00", "rea"]
y_true
for (j in 0:0) {
<- paste0("semaine_t0", j)
semaine_to_estim <- c(y_true, my_basis[my_basis$semaine == semaine_to_estim, "rea"])
y_true <- c(semaine_to_drop, paste0("semaine_t0", j + 2))
semaine_to_drop
<- lm(rea ~ region + hosp:region - 1,
res_lm_rea_1 data = my_basis_rea[!(my_basis_rea$semaine %in% semaine_to_drop), ])
<- c(pred_rea_1_s3, round(predict(res_lm_rea_1, newdata = my_basis_rea[my_basis_rea$semaine == semaine_to_estim, ])))
pred_rea_1_s3
<- numeric(length(nom_dep))
pred_rea_2a_temp <- numeric(length(nom_dep))
pred_rea_2b_temp <- numeric(length(nom_dep))
pred_rea_2c_temp
for (k in 1:length(nom_dep)) {
<- hospital[!(hospital$semaine %in% semaine_to_drop) & hospital$dep == nom_dep[k], ]
temp <- zoo(temp$incid_rea, temp$jour)
my_ts <- diff(my_ts)
my_ts_diff # tseries::adf.test(my_ts)
# tseries::adf.test(my_ts_diff)
if (nom_dep[k] %in% c("975", "977", "978")) {
<- NA
pred_rea_2[k] else {
} <- forecast::auto.arima(my_ts_diff)
my_mod <- as.numeric(forecast(my_mod, h = 21)$mean)
forecast_my_mod <- sum((as.numeric(my_ts[length(my_ts)]) + cumsum(forecast_my_mod))[1:7])
temp1 <- sum((as.numeric(my_ts[length(my_ts)]) + cumsum(forecast_my_mod))[1:14]) - temp1
temp2 <- sum((as.numeric(my_ts[length(my_ts)]) + cumsum(forecast_my_mod))[1:21]) - temp1 - temp2
pred_rea_2a_temp[k] # modèles exponentiels
# Méthode 2 : lissage exponentiel
<- ets(my_ts)
my_mod_exp <- as.numeric(forecast(my_mod_exp, h = 21)$mean)
forecast_my_mod_exp <- ifelse(forecast_my_mod_exp > 0, forecast_my_mod_exp, 0)
forecast_my_mod_exp <- round(sum(forecast_my_mod_exp[1:7]), 0)
temp1 <- round(sum(forecast_my_mod_exp[1:14]), 0) - temp1
temp2 <- round(sum(forecast_my_mod_exp[1:21]), 0) - temp2 - temp1
pred_rea_2b_temp[k] # Méthode 3 : lissage exponentiel sur données hebdomadaires
<- my_basis[my_basis$dep == nom_dep[k] & !(my_basis$semaine %in% semaine_to_drop), ]
temp <- zoo(temp$rea, temp$jour)
my_ts_exp if (all(my_ts_exp == 0)) {
<- 0
pred_rea_2c_temp[k] else {
} <- ets(my_ts_exp)
my_mod_exp_2 <- as.numeric(forecast(my_mod_exp_2)$mean)
forecast_my_mod_exp <- ifelse(forecast_my_mod_exp > 0, forecast_my_mod_exp, 0)
forecast_my_mod_exp <- round(forecast_my_mod_exp[3], 0)
pred_rea_2c_temp[k]
}
}
}
<- c(pred_rea_2a_s3, pred_rea_2a_temp)
pred_rea_2a_s3 <- c(pred_rea_2b_s3, pred_rea_2b_temp)
pred_rea_2b_s3 <- c(pred_rea_2c_s3, pred_rea_2c_temp)
pred_rea_2c_s3
}
<- step(lm(y_true ~ pred_rea_2a_s3 + pred_rea_2b_s3 + pred_rea_2c_s3 - 1)) lm_2_rea_ts_s2
## Start: AIC=896.87
## y_true ~ pred_rea_2a_s3 + pred_rea_2b_s3 + pred_rea_2c_s3 - 1
##
## Df Sum of Sq RSS AIC
## <none> 16622 896.87
## - pred_rea_2c_s3 1 5961.0 22583 956.77
## - pred_rea_2b_s3 1 6946.1 23568 965.40
## - pred_rea_2a_s3 1 15874.7 32497 1030.29
<- predict(lm_2_rea_ts_s2)
pred_rea_2_s3
<- lm(y_true ~ pred_rea_1_s3 + pred_rea_2_s3 - 1) lm_rea_3c
On prédit:
le nombre de réanimations à venir du [15 mars 2021; 21 mars 2021] en utilisant les nouvelles hospitalisations du [08 mars 2021; 14 mars 2021]
le nombre de réanimations à venir du [22 mars 2021; 28 mars 2021] en utilisant la prédiction des hospitalisations à venir du [15 mars 2021; 21 mars 2021]
le nombre de réanimations à venir du [29 mars 2021; 04 avril 2021] en utilisant la prédiction des hospitalisations à venir du [22 mars 2021; 28 mars 2021]
Pour cela, on actualise le modèle, c’est-à-dire qu’on inclut la dernière semaine observée:
<- lm(rea ~ region + hosp:region - 1,
res_lm data = my_basis_rea[!(my_basis_rea$semaine %in% c("semaine_t0-2", "semaine_t0-1")), ])
# semaine t+1
<- my_basis_rea[my_basis_rea$semaine %in% c("semaine_t0-1", "semaine_t0-2", "semaine_t0-3"), ]
new_data_rea_1 <- predict(res_lm, newdata = new_data_rea_1)
pred_rea_1
<- matrix(0, length(nom_dep), 3)
pred_rea_2 <- matrix(0, length(nom_dep), 3)
pred_rea_2a <- matrix(0, length(nom_dep), 3)
pred_rea_2b <- matrix(0, length(nom_dep), 3)
pred_rea_2c for (k in 1:length(nom_dep)) {
<- hospital[!(hospital$semaine %in% c("semaine_t0-3", "semaine_t0-2", "semaine_t0-1")) &
temp $dep == nom_dep[k], ]
hospital<- zoo(temp$incid_rea, temp$jour)
my_ts <- diff(my_ts)
my_ts_diff # tseries::adf.test(my_ts)
# tseries::adf.test(my_ts_diff)
if (nom_dep[k] %in% c("975", "977", "978")) {
<- NA
pred_rea_2[k] else {
} <- forecast::auto.arima(my_ts_diff)
my_mod <- as.numeric(forecast(my_mod, h = 21)$mean)
forecast_my_mod <- sum((as.numeric(my_ts[length(my_ts)]) + cumsum(forecast_my_mod))[1:7])
pred_3a_s1 <- sum((as.numeric(my_ts[length(my_ts)]) + cumsum(forecast_my_mod))[1:14]) - pred_3a_s1
pred_3a_s2 <- sum((as.numeric(my_ts[length(my_ts)]) + cumsum(forecast_my_mod))[1:21]) -
pred_3a_s3 - pred_3a_s2
pred_3a_s1 # Lissage exponentiel
<- ets(my_ts)
my_mod_exp <- as.numeric(forecast(my_mod_exp, h = 21)$mean)
forecast_my_mod_exp <- ifelse(forecast_my_mod_exp > 0, forecast_my_mod_exp, 0)
forecast_my_mod_exp <- round(sum(forecast_my_mod_exp[1:7]), 0)
pred_3b_s1 <- round(sum(forecast_my_mod_exp[1:14]), 0) - pred_3b_s1
pred_3b_s2 <- round(sum(forecast_my_mod_exp[1:21]), 0) - pred_3b_s2 - pred_3b_s1
pred_3b_s3 # Méthode 3 : lissage exponentiel sur données hebdomadaires
<- my_basis[my_basis$dep == nom_dep[k] & !(my_basis$semaine %in%
temp c("semaine_t0-3", "semaine_t0-2", "semaine_t0-1")), ]
<- zoo(temp$rea, temp$jour)
my_ts_exp <- ets(my_ts_exp)
my_mod_exp_2 <- as.numeric(forecast(my_mod_exp_2)$mean)
forecast_my_mod_exp <- ifelse(forecast_my_mod_exp > 0, forecast_my_mod_exp, 0)
forecast_my_mod_exp <- round(forecast_my_mod_exp[1], 0)
pred_3c_s1 <- round(forecast_my_mod_exp[2], 0)
pred_3c_s2 <- round(forecast_my_mod_exp[3], 0)
pred_3c_s3
1] <- predict(lm_2_rea_ts, newdata = data.frame(pred_rea_2a = pred_3a_s1,
pred_rea_2[k, pred_rea_2b = pred_3b_s1,
pred_rea_2c = pred_3c_s1))
2] <- predict(lm_2_rea_ts_s1, newdata = data.frame(pred_rea_2a_s2 = pred_3a_s2,
pred_rea_2[k, pred_rea_2b_s2 = pred_3b_s2,
pred_rea_2c_s2 = pred_3c_s2))
3] <- predict(lm_2_rea_ts_s2, newdata = data.frame(pred_rea_2a_s3 = pred_3a_s3,
pred_rea_2[k, pred_rea_2b_s3 = pred_3b_s3,
pred_rea_2c_s3 = pred_3c_s3))
}
}
<- predict(lm_rea_3, newdata = data.frame(pred_rea_1 =
pred_rea_a $semaine == "semaine_t0-1"],
pred_rea_1[new_data_rea_1pred_rea_2 = as.vector(pred_rea_2)[1:(length(pred_rea_1) / 3)]))
<- predict(lm_rea_3b, newdata = data.frame(
pred_rea_b pred_rea_1_s2 = pred_rea_1[new_data_rea_1$semaine == "semaine_t0-2"],
pred_rea_2_s2 = as.vector(pred_rea_2)[((length(pred_rea_1) / 3) + 1):(2 * length(pred_rea_1) / 3)]))
<- predict(lm_rea_3c, newdata = data.frame(
pred_rea_c pred_rea_1_s3 = pred_rea_1[new_data_rea_1$semaine == "semaine_t0-3"],
pred_rea_2_s3 = as.vector(pred_rea_2)[(2 * length(pred_rea_1) / 3 + 1):length(pred_rea_1)]))
# on synthétise les résultats
<- my_basis[my_basis$semaine %in% "semaine_t0-1", ]
new_data $this_week <- my_basis_rea[my_basis_rea$semaine == "semaine_t00", "rea"]
new_data$next_week <- pred_rea_a
new_data$next_two_week <- pred_rea_b
new_data$next_three_week <- pred_rea_c
new_data$semaine %in% "semaine_t0-1", "rea"] <- pred_rea_a
my_basis[my_basis$semaine %in% "semaine_t0-2", "rea"] <- pred_rea_b
my_basis[my_basis$semaine %in% "semaine_t0-3", "rea"] <- pred_rea_c my_basis[my_basis
On va représenter l’évolution du nombre de patients en réanimations dans un intervalle de temps de 4 semaines :
<- tidyr::pivot_longer(data = select(new_data, dep, region,
new_data_long
this_week, next_week, next_two_week, next_three_week),col = 3:6,
names_to = "semaine",
values_to = "rea")
$semaine <- factor(new_data_long$semaine,
new_data_longlevels = c("this_week", "next_week", "next_two_week", "next_three_week"),
labels = c(paste0("[", format(to_day - 7, '%d %b'), "; ",
format(to_day - 1, '%d %b'), "]"),
paste0("[", format(to_day, '%d %b'), "; ",
format(to_day + 6, '%d %b'), "]"),
paste0("[", format(to_day+7, '%d %b'), "; ",
format(to_day + 13, '%d %b'), "]"),
paste0("[", format(to_day + 14, '%d %b'), "; ",
format(to_day + 20, '%d %b'), "]")
) )
$region <- factor(new_data_long$region, levels = hosp_region$region)
new_data_long<- ggplot(new_data_long, aes(x = semaine, y = rea, group = dep))+
p geom_line() +
facet_wrap(~region)
::ggplotly(p) plotly
On aggrège les données à la France entière:
<- my_basis %>%
my_basis_fr group_by(semaine, jour) %>%
summarise(rea = sum(rea))
<- ggplot(data = filter(my_basis_fr, semaine %in%
p c("semaine_t0-3", "semaine_t0-2", "semaine_t0-1", "semaine_t00")),
aes(x = jour, y = rea)) +
geom_line(col = "red") +
geom_line(data = filter(my_basis_fr, !(semaine %in%
c("semaine_t0-3", "semaine_t0-2", "semaine_t0-1"))),
aes(x = jour, y = rea)) +
labs(title = "Prédiction des nouvelles réanimations dans les 21 jours",
x = "semaine",
y = "réanimations",
fill = "Age")
::ggplotly(p) plotly
L’idée est d’expliquer le nombre de nouveaux décès la semaine \(t\) par les nouvelles réanimations la semaine \(t-1\).
Ainsi on sera en mesure de prédire le nombre de nouveaux décès la semaine à venir, mais aussi les trois semaines suivantes en utilisant les prédictions des hospitalisations, des réanimations et cas positifs.
On prépare les données et on représente le nombre de nouveaux décès par semaine et par département en fonction du nombre de nouvelles réanimations la semaine d’avant et on constate un lien très fort.
<- my_basis %>%
my_basis_temp filter(semaine == "semaine_t0-3")
$rea <- NA
my_basis_temp$semaine <- "semaine_t0-4"
my_basis_temp$jour <- my_basis_temp$jour + 7
my_basis_temp<- rbind(my_basis_temp, my_basis)
my_basis <- my_basis %>%
my_basis_dc select(dep, semaine, jour, region, dc)
<- my_basis %>%
temp_rea select(dep, jour, rea) %>%
mutate(jour = jour + 7)
<- merge(my_basis_dc, temp_rea, by = c("jour", "dep"), all.x = T)
my_basis_dc <- my_basis_dc %>%
my_basis_dc
as.data.frame<- my_basis_dc[order(my_basis_dc$jour, decreasing = T), ]
my_basis_dc
<- ggplot(my_basis_dc) +
p aes(x = rea, y = dc) +
geom_point() +
geom_smooth(method = "loess") +
geom_smooth(method = "lm",
col = "red") +
facet_wrap(~ region)
::ggplotly(p) plotly
On va faire deux modèles : un modèle régional où on explique les nouvelles réanimations des départements au sein d’une même région ainsi qu’un modèle de série temporelle département par département.
Apprentissage:
On modélise sur les observations des semaines précédentes:
<- lm(dc ~ region + rea:region - 1,
res_lm_dc_1 data = my_basis_dc[!(my_basis_dc$semaine %in%
c("semaine_t0-3", "semaine_t0-2", "semaine_t0-1", "semaine_t00")), ])
::stargazer(res_lm_dc_1, type = "html") stargazer
Dependent variable: | |
dc | |
regionAuvergne-Rhône-Alpes | 4.048*** |
(0.412) | |
regionBourgogne-Franche-Comté | 2.879*** |
(0.537) | |
regionBretagne | 1.609** |
(0.789) | |
regionCentre-Val de Loire | 3.426*** |
(0.617) | |
regionCorse | 0.245 |
(1.078) | |
regionDOM-TOM | -0.021 |
(0.692) | |
regionGrand Est | 2.410*** |
(0.487) | |
regionHauts-de-France | 5.935*** |
(0.662) | |
regionIle-de-France | 8.473*** |
(0.615) | |
regionNormandie | 1.389** |
(0.682) | |
regionNouvelle-Aquitaine | 1.997*** |
(0.411) | |
regionOccitanie | 1.607*** |
(0.392) | |
regionPays de la Loire | 2.278*** |
(0.719) | |
regionProvence-Alpes-Côte d’Azur | 4.184*** |
(0.591) | |
regionAuvergne-Rhône-Alpes:rea | 0.929*** |
(0.016) | |
regionBourgogne-Franche-Comté:rea | 0.975*** |
(0.050) | |
regionBretagne:rea | 1.025*** |
(0.117) | |
regionCentre-Val de Loire:rea | 0.543*** |
(0.066) | |
regionCorse:rea | 0.529 |
(0.373) | |
regionDOM-TOM:rea | 0.445*** |
(0.084) | |
regionGrand Est:rea | 1.182*** |
(0.035) | |
regionHauts-de-France:rea | 0.850*** |
(0.017) | |
regionIle-de-France:rea | 0.597*** |
(0.015) | |
regionNormandie:rea | 1.237*** |
(0.061) | |
regionNouvelle-Aquitaine:rea | 0.789*** |
(0.049) | |
regionOccitanie:rea | 0.631*** |
(0.031) | |
regionPays de la Loire:rea | 0.957*** |
(0.075) | |
regionProvence-Alpes-Côte d’Azur:rea | 0.889*** |
(0.016) | |
Observations | 4,141 |
R2 | 0.857 |
Adjusted R2 | 0.856 |
Residual Std. Error | 7.993 (df = 4113) |
F Statistic | 881.671*** (df = 28; 4113) |
Note: | p<0.1; p<0.05; p<0.01 |
Test:
On teste le modèle sur les données de la semaine actuelle:
<- predict(res_lm_dc_1, newdata = my_basis_dc[my_basis_dc$semaine == "semaine_t00", ]) pred_dc_1
plot(pred_dc_1, my_basis_dc[my_basis_dc$semaine == "semaine_t00", "dc"],
xlab = "valeurs prédites", ylab = "valeurs observées")
abline(a = 0, b = 1)
text(pred_dc_1, my_basis_dc[my_basis_dc$semaine == "semaine_t00", "dc"],
$semaine == "semaine_t00", "dep"], pos = 2) my_basis_dc[my_basis_dc
L’écart quadratique moyen est égal ici à :
mean((pred_dc_1 - my_basis_dc[my_basis_dc$semaine == "semaine_t00", "dc"]) ^ 2, na.rm = T)
## [1] 93.06892
On utilise la même stratégie que celle présentée pour prédire le nombre de nouveaux cas, de nouvelles hospitalisations et de nouvelles réanimations.
Etape d’apprentissage : on entraîne l’agorithme sur les données passées en enlevant la dernière semaine observée et on prédit sur cette semaine afin de calculer les écarts quadratiques avec les valeurs observées.
<- numeric(length(nom_dep))
pred_dc_2a <- numeric(length(nom_dep))
pred_dc_2b <- numeric(length(nom_dep))
pred_dc_2c for (k in 1:length(nom_dep)) {
<- hospital[!(hospital$semaine %in% c("semaine_t0-1", "semaine_t00")) &
temp $dep == nom_dep[k], ]
hospital<- zoo(temp$incid_dc, temp$jour)
my_ts <- diff(my_ts)
my_ts_diff # tseries::adf.test(my_ts)
# tseries::adf.test(my_ts_diff)
if (nom_dep[k] %in% c("975", "977", "978")) {
<- NA
pred_dc_2[k] else {
} <- forecast::auto.arima(my_ts_diff)
my_mod <- as.numeric(forecast(my_mod)$mean)
forecast_my_mod <- sum((as.numeric(my_ts[length(my_ts)]) + cumsum(forecast_my_mod))[1:7])
pred_dc_2a[k] # modèles exponentiels
# Méthode 2 : lissage exponentiel
<- ets(my_ts)
my_mod_exp <- as.numeric(forecast(my_mod_exp)$mean)
forecast_my_mod_exp <- ifelse(forecast_my_mod_exp > 0, forecast_my_mod_exp, 0)
forecast_my_mod_exp <- round(sum(forecast_my_mod_exp[1:7]), 0)
pred_dc_2b[k] # Méthode 3 : lissage exponentiel sur données hebdomadaires
<- my_basis[my_basis$dep == nom_dep[k] & !(my_basis$semaine %in%
temp c("semaine_t0-4", "semaine_t0-3",
"semaine_t0-2", "semaine_t0-1", "semaine_t00")), ]
<- zoo(temp$dc, temp$jour)
my_ts_exp <- ets(my_ts_exp)
my_mod_exp_2 <- as.numeric(forecast(my_mod_exp_2)$mean)
forecast_my_mod_exp <- ifelse(forecast_my_mod_exp > 0, forecast_my_mod_exp, 0)
forecast_my_mod_exp <- round(forecast_my_mod_exp[1], 0)
pred_dc_2c[k]
} }
On représente le graphique des valeurs prédites / valeurs observées :
par(mfrow = c(1, 3))
plot(pred_dc_2a, my_basis_dc[my_basis_dc$semaine == "semaine_t00", "dc"],
xlab = "valeurs prédites", ylab = "valeurs observées", main = "Box-Jenkins")
abline(a = 0, b = 1)
text(pred_dc_2a, my_basis_dc[my_basis_dc$semaine == "semaine_t00", "dc"],
$semaine == "semaine_t00", "dep"], pos = 2)
my_basis_dc[my_basis_dcplot(pred_dc_2b, my_basis_dc[my_basis_dc$semaine == "semaine_t00", "dc"],
xlab = "valeurs prédites", ylab = "valeurs observées", main = "Lissage exponentiel journalier")
abline(a = 0, b = 1)
text(pred_dc_2b, my_basis_dc[my_basis_dc$semaine == "semaine_t00", "dc"],
$semaine == "semaine_t00", "dep"], pos = 2)
my_basis_dc[my_basis_dcplot(pred_dc_2c, my_basis_dc[my_basis_dc$semaine == "semaine_t00", "dc"],
xlab = "valeurs prédites", ylab = "valeurs observées", main = "Lissage exponentiel hebdomadaire")
abline(a = 0, b = 1)
text(pred_dc_2c, my_basis_dc[my_basis_dc$semaine == "semaine_t00", "dc"],
$semaine == "semaine_t00", "dep"], pos = 2) my_basis_dc[my_basis_dc
L’écart quadratique moyen est égal ici à :
c(
mean((pred_dc_2a - my_basis_dc[my_basis_dc$semaine == "semaine_t00", "dc"]) ^ 2, na.rm = T),
mean((pred_dc_2b - my_basis_dc[my_basis_dc$semaine == "semaine_t00", "dc"]) ^ 2, na.rm = T),
mean((pred_dc_2c - my_basis_dc[my_basis_dc$semaine == "semaine_t00", "dc"]) ^ 2, na.rm = T)
)
## [1] 66.76575 67.40594 48.37624
Les 3 prédictions sont très proches et on va choisir un algorithme de type stepwise sur les prédictions pour choisir la meilleure combinaison et ne garder qu’une prédiction de type série temporelle:
<- step(lm(my_basis[my_basis$semaine == "semaine_t00", "dc"] ~
lm_2_dc_ts + pred_dc_2b + pred_dc_2c - 1)) pred_dc_2a
## Start: AIC=393.77
## my_basis[my_basis$semaine == "semaine_t00", "dc"] ~ pred_dc_2a +
## pred_dc_2b + pred_dc_2c - 1
##
## Df Sum of Sq RSS AIC
## - pred_dc_2a 1 2.27 4698.3 391.82
## - pred_dc_2b 1 56.72 4752.7 392.99
## <none> 4696.0 393.77
## - pred_dc_2c 1 1827.46 6523.5 424.97
##
## Step: AIC=391.82
## my_basis[my_basis$semaine == "semaine_t00", "dc"] ~ pred_dc_2b +
## pred_dc_2c - 1
##
## Df Sum of Sq RSS AIC
## <none> 4698.3 391.82
## - pred_dc_2b 1 117.58 4815.9 392.32
## - pred_dc_2c 1 1897.32 6595.6 424.08
<- predict(lm_2_dc_ts)
pred_dc_2 mean((pred_dc_2 - na.omit(my_basis[my_basis$semaine == "semaine_t00", "dc"])) ^ 2)
## [1] 46.51775
Combinaison des prédictions: on peut envisager de faire un panaché des deux prédictions en régressant (avec un algorithme de type stepwise) le nombre de décés observé la semaine t0 en fonction des deux méthodes de régression. On obtient l’écart moyen quadratique suivant :
<- lm(my_basis_dc[my_basis_dc$semaine == "semaine_t00", "dc"] ~
lm_dc_3 + pred_dc_2 - 1)
pred_dc_1 mean((predict(lm_dc_3) - na.omit(my_basis_dc[my_basis_dc$semaine == "semaine_t00", "dc"])) ^ 2)
## [1] 42.08645
On adapte le poids des prédictions en fonction de la semaine à prédire
<- c("semaine_t0-4", "semaine_t0-3", "semaine_t0-2", "semaine_t0-1", "semaine_t00")
semaine_to_drop <- pred_dc_1
pred_dc_1_s2 <- pred_dc_2a
pred_dc_2a_s2 <- pred_dc_2b
pred_dc_2b_s2 <- pred_dc_2c
pred_dc_2c_s2
<- my_basis[my_basis$semaine == "semaine_t00", "dc"]
y_true
for (j in 0:0) {
<- paste0("semaine_t0", j)
semaine_to_estim <- c(y_true, my_basis[my_basis$semaine == semaine_to_estim, "dc"])
y_true <- c(semaine_to_drop, paste0("semaine_t0", j + 1))
semaine_to_drop <- lm(dc ~ region + rea:region - 1,
res_lm_dc_1 data = my_basis_dc[!(my_basis_dc$semaine %in% semaine_to_drop), ])
<- c(pred_dc_1_s2,
pred_dc_1_s2 round(predict(res_lm_dc_1, newdata = my_basis_dc[my_basis_dc$semaine == semaine_to_estim, ])))
<- numeric(length(nom_dep))
pred_dc_2a_temp <- numeric(length(nom_dep))
pred_dc_2b_temp <- numeric(length(nom_dep))
pred_dc_2c_temp
for (k in 1:length(nom_dep)) {
<- hospital[!(hospital$semaine %in% semaine_to_drop) &
temp $dep == nom_dep[k], ]
hospital<- zoo(temp$incid_dc, temp$jour)
my_ts <- diff(my_ts)
my_ts_diff # tseries::adf.test(my_ts)
# tseries::adf.test(my_ts_diff)
if (nom_dep[k] %in% c("975", "977", "978")) {
<- NA
pred_dc_2[k] else {
} <- forecast::auto.arima(my_ts_diff)
my_mod <- as.numeric(forecast(my_mod, h = 14)$mean)
forecast_my_mod <- sum((as.numeric(my_ts[length(my_ts)]) + cumsum(forecast_my_mod))[1:7])
temp <- sum((as.numeric(my_ts[length(my_ts)]) + cumsum(forecast_my_mod))[1:14]) - temp
pred_dc_2a_temp[k] # modèles exponentiels
# Méthode 2 : lissage exponentiel
<- ets(my_ts)
my_mod_exp <- as.numeric(forecast(my_mod_exp, h = 14)$mean)
forecast_my_mod_exp <- ifelse(forecast_my_mod_exp > 0, forecast_my_mod_exp, 0)
forecast_my_mod_exp <- round(sum(forecast_my_mod_exp[1:7]), 0)
temp <- round(sum(forecast_my_mod_exp[1:14]), 0) - temp
pred_dc_2b_temp[k] # Méthode 3 : lissage exponentiel sur données hebdomadaires
<- my_basis[my_basis$dep == nom_dep[k] & !(my_basis$semaine %in% semaine_to_drop), ]
temp <- zoo(temp$dc, temp$jour)
my_ts_exp if (all(my_ts_exp == 0)) {
<- 0
pred_dc_2c_temp[k] else {
} <- ets(my_ts_exp)
my_mod_exp_2 <- as.numeric(forecast(my_mod_exp_2)$mean)
forecast_my_mod_exp <- ifelse(forecast_my_mod_exp > 0, forecast_my_mod_exp, 0)
forecast_my_mod_exp <- round(forecast_my_mod_exp[2], 0)
pred_dc_2c_temp[k]
}
}
}<- c(pred_dc_2a_s2, pred_dc_2a_temp)
pred_dc_2a_s2 <- c(pred_dc_2b_s2, pred_dc_2b_temp)
pred_dc_2b_s2 <- c(pred_dc_2c_s2, pred_dc_2c_temp)
pred_dc_2c_s2
}
<- step(lm(y_true ~ pred_dc_2a_s2 + pred_dc_2b_s2 + pred_dc_2c_s2 - 1)) lm_2_dc_ts_s1
## Start: AIC=808.73
## y_true ~ pred_dc_2a_s2 + pred_dc_2b_s2 + pred_dc_2c_s2 - 1
##
## Df Sum of Sq RSS AIC
## - pred_dc_2a_s2 1 12.0 10757 806.96
## - pred_dc_2b_s2 1 78.7 10824 808.20
## <none> 10745 808.73
## - pred_dc_2c_s2 1 4665.3 15410 879.57
##
## Step: AIC=806.96
## y_true ~ pred_dc_2b_s2 + pred_dc_2c_s2 - 1
##
## Df Sum of Sq RSS AIC
## <none> 10757 806.96
## - pred_dc_2b_s2 1 269.0 11026 809.95
## - pred_dc_2c_s2 1 5391.1 16148 887.02
<- predict(lm_2_dc_ts_s1)
pred_dc_2_s2
<- lm(y_true ~ pred_dc_1_s2 + pred_dc_2_s2 - 1)
lm_dc_3b
#######
# Semaine + 2
#######
<- c("semaine_t0-4", "semaine_t0-3", "semaine_t0-2", "semaine_t0-1", "semaine_t00", "semaine_t01")
semaine_to_drop <- pred_dc_1_s2
pred_dc_1_s3 <- pred_dc_2a_s2
pred_dc_2a_s3 <- pred_dc_2b_s2
pred_dc_2b_s3 <- pred_dc_2c_s2
pred_dc_2c_s3
for (j in 0:0) {
<- paste0("semaine_t0", j)
semaine_to_estim <- c(y_true, my_basis[my_basis$semaine == semaine_to_estim, "dc"])
y_true <- c(semaine_to_drop, paste0("semaine_t0", j + 2))
semaine_to_drop
<- lm(dc ~ region + rea:region - 1,
res_lm_dc_1 data = my_basis_dc[!(my_basis_dc$semaine %in% semaine_to_drop), ])
<- c(pred_dc_1_s3, round(predict(res_lm_dc_1,
pred_dc_1_s3 newdata = my_basis_dc[my_basis_dc$semaine == semaine_to_estim, ])))
<- numeric(length(nom_dep))
pred_dc_2a_temp <- numeric(length(nom_dep))
pred_dc_2b_temp <- numeric(length(nom_dep))
pred_dc_2c_temp
for (k in 1:length(nom_dep)) {
<- hospital[!(hospital$semaine %in% semaine_to_drop) & hospital$dep == nom_dep[k], ]
temp <- zoo(temp$incid_dc, temp$jour)
my_ts <- diff(my_ts)
my_ts_diff # tseries::adf.test(my_ts)
# tseries::adf.test(my_ts_diff)
if (nom_dep[k] %in% c("975", "977", "978")) {
<- NA
pred_dc_2[k] else {
} <- forecast::auto.arima(my_ts_diff)
my_mod <- as.numeric(forecast(my_mod, h = 21)$mean)
forecast_my_mod <- sum((as.numeric(my_ts[length(my_ts)]) + cumsum(forecast_my_mod))[1:7])
temp1 <- sum((as.numeric(my_ts[length(my_ts)]) + cumsum(forecast_my_mod))[1:14]) - temp1
temp2 <- sum((as.numeric(my_ts[length(my_ts)]) + cumsum(forecast_my_mod))[1:21]) - temp1 - temp2
temp3 <- ifelse(temp3 > 0, round(temp3), 0)
pred_dc_2a_temp[k] # modèles exponentiels
# Méthode 2 : lissage exponentiel
<- ets(my_ts)
my_mod_exp <- as.numeric(forecast(my_mod_exp, h = 21)$mean)
forecast_my_mod_exp <- ifelse(forecast_my_mod_exp > 0, forecast_my_mod_exp, 0)
forecast_my_mod_exp <- round(sum(forecast_my_mod_exp[1:7]), 0)
temp1 <- round(sum(forecast_my_mod_exp[1:14]), 0) - temp1
temp2 <- round(sum(forecast_my_mod_exp[1:21]), 0) - temp2 - temp1
pred_dc_2b_temp[k] # Méthode 3 : lissage exponentiel sur données hebdomadaires
<- my_basis[my_basis$dep == nom_dep[k] & !(my_basis$semaine %in% semaine_to_drop), ]
temp <- zoo(temp$dc, temp$jour)
my_ts_exp if (all(my_ts_exp == 0)) {
<- 0
pred_dc_2c_temp[k] else {
} <- ets(my_ts_exp)
my_mod_exp_2 <- as.numeric(forecast(my_mod_exp_2)$mean)
forecast_my_mod_exp <- ifelse(forecast_my_mod_exp > 0, forecast_my_mod_exp, 0)
forecast_my_mod_exp <- round(forecast_my_mod_exp[3], 0)
pred_dc_2c_temp[k]
}
}
}
<- c(pred_dc_2a_s3, pred_dc_2a_temp)
pred_dc_2a_s3 <- c(pred_dc_2b_s3, pred_dc_2b_temp)
pred_dc_2b_s3 <- c(pred_dc_2c_s3, pred_dc_2c_temp)
pred_dc_2c_s3
}
<- step(lm(y_true ~ pred_dc_2a_s3 + pred_dc_2b_s3 + pred_dc_2c_s3 - 1)) lm_2_dc_ts_s2
## Start: AIC=1269.6
## y_true ~ pred_dc_2a_s3 + pred_dc_2b_s3 + pred_dc_2c_s3 - 1
##
## Df Sum of Sq RSS AIC
## - pred_dc_2b_s3 1 13.4 19628 1267.8
## <none> 19615 1269.6
## - pred_dc_2a_s3 1 153.3 19768 1270.0
## - pred_dc_2c_s3 1 5967.2 25582 1348.1
##
## Step: AIC=1267.81
## y_true ~ pred_dc_2a_s3 + pred_dc_2c_s3 - 1
##
## Df Sum of Sq RSS AIC
## <none> 19628 1267.8
## - pred_dc_2a_s3 1 204.5 19833 1269.0
## - pred_dc_2c_s3 1 6125.2 25753 1348.1
<- predict(lm_2_dc_ts_s2)
pred_dc_2_s3
<- lm(y_true ~ pred_dc_1_s3 + pred_dc_2_s3 - 1)
lm_dc_3c
#######
# Semaine T + 3
#######
<- c("semaine_t0-4", "semaine_t0-3", "semaine_t0-2", "semaine_t0-1",
semaine_to_drop "semaine_t00", "semaine_t01", "semaine_t02")
<- pred_dc_1_s3
pred_dc_1_s4 <- pred_dc_2a_s3
pred_dc_2a_s4 <- pred_dc_2b_s3
pred_dc_2b_s4 <- pred_dc_2c_s3
pred_dc_2c_s4
for (j in 0:0) {
<- paste0("semaine_t0", j)
semaine_to_estim <- c(y_true, my_basis[my_basis$semaine == semaine_to_estim, "dc"])
y_true <- c(semaine_to_drop, paste0("semaine_t0", j + 3))
semaine_to_drop
<- lm(dc ~ region + rea:region - 1,
res_lm_dc_1 data = my_basis_dc[!(my_basis_dc$semaine %in% semaine_to_drop), ])
<- c(pred_dc_1_s4, round(predict(res_lm_dc_1,
pred_dc_1_s4 newdata = my_basis_dc[my_basis_dc$semaine == semaine_to_estim, ])))
<- numeric(length(nom_dep))
pred_dc_2a_temp <- numeric(length(nom_dep))
pred_dc_2b_temp <- numeric(length(nom_dep))
pred_dc_2c_temp
for (k in 1:length(nom_dep)) {
<- hospital[!(hospital$semaine %in% semaine_to_drop) & hospital$dep == nom_dep[k], ]
temp <- zoo(temp$incid_dc, temp$jour)
my_ts <- diff(my_ts)
my_ts_diff # tseries::adf.test(my_ts)
# tseries::adf.test(my_ts_diff)
if (nom_dep[k] %in% c("975", "977", "978")) {
<- NA
pred_dc_2[k] else {
} <- forecast::auto.arima(my_ts_diff)
my_mod <- as.numeric(forecast(my_mod, h = 28)$mean)
forecast_my_mod <- sum((as.numeric(my_ts[length(my_ts)]) + cumsum(forecast_my_mod))[1:7])
temp1 <- sum((as.numeric(my_ts[length(my_ts)]) + cumsum(forecast_my_mod))[1:14]) - temp1
temp2 <- sum((as.numeric(my_ts[length(my_ts)]) + cumsum(forecast_my_mod))[1:21]) - temp1 - temp2
temp3 <- sum((as.numeric(my_ts[length(my_ts)]) + cumsum(forecast_my_mod))[1:28]) - temp1 - temp2 - temp3
temp4 <- ifelse(temp4 > 0, round(temp4), 0)
pred_dc_2a_temp[k] # modèles exponentiels
# Méthode 2 : lissage exponentiel
<- ets(my_ts)
my_mod_exp <- as.numeric(forecast(my_mod_exp, h = 28)$mean)
forecast_my_mod_exp <- ifelse(forecast_my_mod_exp > 0, forecast_my_mod_exp, 0)
forecast_my_mod_exp <- round(sum(forecast_my_mod_exp[1:7]), 0)
temp1 <- round(sum(forecast_my_mod_exp[1:14]), 0) - temp1
temp2 <- round(sum(forecast_my_mod_exp[1:21]), 0) - temp1 - temp2
temp3 <- round(sum(forecast_my_mod_exp[1:28]), 0) - temp1 - temp2 - temp3
pred_dc_2b_temp[k] # Méthode 3 : lissage exponentiel sur données hebdomadaires
<- my_basis[my_basis$dep == nom_dep[k] & !(my_basis$semaine %in% semaine_to_drop), ]
temp <- zoo(temp$dc, temp$jour)
my_ts_exp if (all(my_ts_exp == 0)) {
<- 0
pred_dc_2c_temp[k] else {
} <- ets(my_ts_exp)
my_mod_exp_2 <- as.numeric(forecast(my_mod_exp_2)$mean)
forecast_my_mod_exp <- ifelse(forecast_my_mod_exp > 0, forecast_my_mod_exp, 0)
forecast_my_mod_exp <- round(forecast_my_mod_exp[4], 0)
pred_dc_2c_temp[k]
}
}
}
<- c(pred_dc_2a_s4, pred_dc_2a_temp)
pred_dc_2a_s4 <- c(pred_dc_2b_s4, pred_dc_2b_temp)
pred_dc_2b_s4 <- c(pred_dc_2c_s4, pred_dc_2c_temp)
pred_dc_2c_s4
}
<- step(lm(y_true ~ pred_dc_2a_s4 + pred_dc_2b_s4 + pred_dc_2c_s4 - 1)) lm_2_dc_ts_s3
## Start: AIC=1801.8
## y_true ~ pred_dc_2a_s4 + pred_dc_2b_s4 + pred_dc_2c_s4 - 1
##
## Df Sum of Sq RSS AIC
## - pred_dc_2b_s4 1 2.7 34425 1799.8
## - pred_dc_2a_s4 1 6.7 34429 1799.9
## <none> 34423 1801.8
## - pred_dc_2c_s4 1 6686.7 41109 1871.5
##
## Step: AIC=1799.83
## y_true ~ pred_dc_2a_s4 + pred_dc_2c_s4 - 1
##
## Df Sum of Sq RSS AIC
## - pred_dc_2a_s4 1 4.1 34429 1797.9
## <none> 34425 1799.8
## - pred_dc_2c_s4 1 6684.3 41110 1869.5
##
## Step: AIC=1797.88
## y_true ~ pred_dc_2c_s4 - 1
##
## Df Sum of Sq RSS AIC
## <none> 34429 1797.9
## - pred_dc_2c_s4 1 264391 298820 2668.9
<- predict(lm_2_dc_ts_s3)
pred_dc_2_s4
<- lm(y_true ~ pred_dc_1_s4 + pred_dc_2_s4 - 1) lm_dc_4c
On prédit:
le nombre de décès à venir du [15 mars 2021; 21 mars 2021] en utilisant les nouvelles réanimations du [08 mars 2021; 14 mars 2021]
le nombre de décès à venir du [22 mars 2021; 28 mars 2021] en utilisant la prédiction des réanimations à venir du [15 mars 2021; 21 mars 2021]
le nombre de décès à venir du [29 mars 2021; 04 avril 2021] en utilisant la prédiction des réanimations à venir du [22 mars 2021; 28 mars 2021]
le nombre de décès à venir du [05 avril 2021; 11 avril 2021] en utilisant la prédiction des réanimations à venir du [22 mars 2021; 28 mars 2021]
Pour cela, on actualise le modèle, c’est-à-dire qu’on inclut la dernière semaine observée:
<- lm(dc ~ region + rea:region - 1,
res_lm data = my_basis_dc[!(my_basis_dc$semaine %in% c("semaine_t0-2", "semaine_t0-1")), ])
# semaine t+1
<- my_basis_dc[my_basis_dc$semaine %in% c("semaine_t0-1", "semaine_t0-2", "semaine_t0-3", "semaine_t0-4"), ]
new_data_dc_1 <- predict(res_lm, newdata = new_data_dc_1)
pred_dc_1
<- matrix(0, length(nom_dep), 4)
pred_dc_2 <- matrix(0, length(nom_dep), 4)
pred_dc_2a <- matrix(0, length(nom_dep), 4)
pred_dc_2b <- matrix(0, length(nom_dep), 4)
pred_dc_2c for (k in 1:length(nom_dep)) {
<- hospital[!(hospital$semaine %in% c("semaine_t0-4", "semaine_t0-3", "semaine_t0-2", "semaine_t0-1")) &
temp $dep == nom_dep[k], ]
hospital<- zoo(temp$incid_dc, temp$jour)
my_ts <- diff(my_ts)
my_ts_diff # tseries::adf.test(my_ts)
# tseries::adf.test(my_ts_diff)
if (nom_dep[k] %in% c("975", "977", "978")) {
<- NA
pred_rea_2[k] else {
} <- forecast::auto.arima(my_ts_diff)
my_mod <- as.numeric(forecast(my_mod, h = 28)$mean)
forecast_my_mod <- sum((as.numeric(my_ts[length(my_ts)]) + cumsum(forecast_my_mod))[1:7])
pred_3a_s1 <- sum((as.numeric(my_ts[length(my_ts)]) + cumsum(forecast_my_mod))[1:14]) - pred_3a_s1
pred_3a_s2 <- sum((as.numeric(my_ts[length(my_ts)]) + cumsum(forecast_my_mod))[1:21]) -
pred_3a_s3 - pred_3a_s2
pred_3a_s1 <- sum((as.numeric(my_ts[length(my_ts)]) + cumsum(forecast_my_mod))[1:28]) -
pred_3a_s4 - pred_3a_s2 - pred_3a_s3
pred_3a_s1 # Lissage exponentiel
<- ets(my_ts)
my_mod_exp <- as.numeric(forecast(my_mod_exp, h = 28)$mean)
forecast_my_mod_exp <- ifelse(forecast_my_mod_exp > 0, forecast_my_mod_exp, 0)
forecast_my_mod_exp <- round(sum(forecast_my_mod_exp[1:7]), 0)
pred_3b_s1 <- round(sum(forecast_my_mod_exp[1:14]), 0) - pred_3b_s1
pred_3b_s2 <- round(sum(forecast_my_mod_exp[1:21]), 0) - pred_3b_s2 - pred_3b_s1
pred_3b_s3 <- round(sum(forecast_my_mod_exp[1:28]), 0) - pred_3b_s3 - pred_3b_s2 - pred_3b_s1
pred_3b_s4 # Méthode 3 : lissage exponentiel sur données hebdomadaires
<- my_basis[my_basis$dep == nom_dep[k] & !(my_basis$semaine %in%
temp c("semaine_t0-4", "semaine_t0-3", "semaine_t0-2", "semaine_t0-1")), ]
<- zoo(temp$dc, temp$jour)
my_ts_exp <- ets(my_ts_exp)
my_mod_exp_2 <- as.numeric(forecast(my_mod_exp_2)$mean)
forecast_my_mod_exp <- ifelse(forecast_my_mod_exp > 0, forecast_my_mod_exp, 0)
forecast_my_mod_exp <- round(forecast_my_mod_exp[1], 0)
pred_3c_s1 <- round(forecast_my_mod_exp[2], 0)
pred_3c_s2 <- round(forecast_my_mod_exp[3], 0)
pred_3c_s3 <- round(forecast_my_mod_exp[4], 0)
pred_3c_s4
1] <- predict(lm_2_dc_ts, newdata = data.frame(pred_dc_2a = pred_3a_s1,
pred_dc_2[k, pred_dc_2b = pred_3b_s1,
pred_dc_2c = pred_3c_s1))
2] <- predict(lm_2_dc_ts_s1, newdata = data.frame(pred_dc_2a_s2 = pred_3a_s2,
pred_dc_2[k, pred_dc_2b_s2 = pred_3b_s2,
pred_dc_2c_s2 = pred_3c_s2))
3] <- predict(lm_2_dc_ts_s2, newdata = data.frame(pred_dc_2a_s3 = pred_3a_s3,
pred_dc_2[k, pred_dc_2b_s3 = pred_3b_s3,
pred_dc_2c_s3 = pred_3c_s3))
4] <- predict(lm_2_dc_ts_s3, newdata = data.frame(pred_dc_2a_s4 = pred_3a_s4,
pred_dc_2[k, pred_dc_2b_s4 = pred_3b_s4,
pred_dc_2c_s4 = pred_3c_s4))
}
}
<- 4 * length(nom_dep)
n_4
<- predict(lm_dc_3, newdata = data.frame(pred_dc_1 =
pred_dc_a $semaine == "semaine_t0-1"],
pred_dc_1[new_data_dc_1pred_dc_2 = as.vector(pred_dc_2)[1:(n_4 / 4)]))
<- predict(lm_dc_3b, newdata = data.frame(
pred_dc_b pred_dc_1_s2 = pred_dc_1[new_data_dc_1$semaine == "semaine_t0-2"],
pred_dc_2_s2 = as.vector(pred_dc_2)[((n_4 / 4) + 1):(2 * n_4 / 4)]))
<- predict(lm_dc_3c, newdata = data.frame(
pred_dc_c pred_dc_1_s3 = pred_dc_1[new_data_dc_1$semaine == "semaine_t0-3"],
pred_dc_2_s3 = as.vector(pred_dc_2)[(2 * n_4 / 4 + 1):(3 * n_4 / 4)]))
<- predict(lm_dc_4c, newdata = data.frame(
pred_dc_d pred_dc_1_s4 = pred_dc_1[new_data_dc_1$semaine == "semaine_t0-4"],
pred_dc_2_s4 = as.vector(pred_dc_2)[(3 * n_4 / 4 + 1):n_4]))
# on synthétise les résultats
<- my_basis[my_basis$semaine %in% "semaine_t0-1", ]
new_data $this_week <- my_basis_dc[my_basis_dc$semaine == "semaine_t00", "dc"]
new_data$next_week <- pred_dc_a
new_data$next_two_week <- pred_dc_b
new_data$next_three_week <- pred_dc_c
new_data$next_four_week <- pred_dc_d
new_data$semaine %in% "semaine_t0-1", "dc"] <- pred_dc_a
my_basis[my_basis$semaine %in% "semaine_t0-2", "dc"] <- pred_dc_b
my_basis[my_basis$semaine %in% "semaine_t0-3", "dc"] <- pred_dc_c
my_basis[my_basis$semaine %in% "semaine_t0-4", "dc"] <- pred_dc_d my_basis[my_basis
On va représenter l’évolution du nombre de décès dans un intervalle de temps de 5 semaines :
<- tidyr::pivot_longer(data = select(new_data, dep, region,
new_data_long
this_week, next_week, next_two_week, next_three_week, next_four_week),col = 3:7,
names_to = "semaine",
values_to = "dc")
$semaine <- factor(new_data_long$semaine,
new_data_longlevels = c("this_week", "next_week", "next_two_week", "next_three_week", "next_four_week"),
labels = c(paste0("[", format(to_day - 7, '%d %b'), "; ",
format(to_day - 1, '%d %b'), "]"),
paste0("[", format(to_day, '%d %b'), "; ",
format(to_day + 6, '%d %b'), "]"),
paste0("[", format(to_day + 7, '%d %b'), "; ",
format(to_day + 13, '%d %b'), "]"),
paste0("[", format(to_day + 14, '%d %b'), "; ",
format(to_day + 20, '%d %b'), "]"),
paste0("[", format(to_day + 21, '%d %b'), "; ",
format(to_day + 27, '%d %b'), "]")
)
)
$region <- factor(new_data_long$region, levels = hosp_region$region)
new_data_long<- ggplot(new_data_long, aes(x = semaine, y = dc, group = dep))+
p geom_line() +
facet_wrap(~region)
::ggplotly(p) plotly
On aggrège les données à la France entière:
<- my_basis %>%
my_basis_fr group_by(semaine, jour) %>%
summarise(dc = sum(dc))
<- ggplot(data = filter(my_basis_fr, semaine %in%
p c("semaine_t0-4", "semaine_t0-3", "semaine_t0-2", "semaine_t0-1", "semaine_t00")),
aes(x = jour, y = dc)) +
geom_line(col = "red") +
geom_line(data = filter(my_basis_fr, !(semaine %in%
c("semaine_t0-4", "semaine_t0-3", "semaine_t0-2", "semaine_t0-1"))),
aes(x = jour, y = dc)) +
labs(title = "Prédiction des nouveaux décès dans les 28 jours",
x = "semaine",
y = "décès",
fill = "Age")
::ggplotly(p) plotly
Soit un nombre de décès par jour de :
%>%
new_data_long group_by(semaine) %>%
summarize(dc = sum(dc, na.rm = T) / 7)
## # A tibble: 5 x 2
## semaine dc
## <fct> <dbl>
## 1 [08 mars; 14 mars] 248.
## 2 [15 mars; 21 mars] 253.
## 3 [22 mars; 28 mars] 266.
## 4 [29 mars; 04 avril] 273.
## 5 [05 avril; 11 avril] 272.
1.3 Comment a évolué la situation depuis le début de l’épidémie ?
1.3.1 Graphique d’évolution
1.3.1.1 Hospitalisations
Ici, on représente le nombre d’entrée en hospitalisations par semaine en fonction du temps sur la France entière.
On représente la même figure mais en mettant en relief la répartition des valeurs par région :
On représente la même figure mais en mettant en relief la répartition des valeurs par classe d’âge :
On met les valeurs en pourcentages pour que le graphique soit plus visible
1.3.1.2 Réanimations
On représente le nombre cummulé d’entrée en réanimations par semaine en fonction du temps sur la France entière.
On représente la même figure mais en mettant en relief la répartition des valeurs par région :
On représente la même figure mais en mettant en relief la répartition des valeurs par classe d’âge :
On met les valeurs en pourcentages pour que le graphique soit plus visibles
Enfin, on représente le ratio réanimations / hospitalisations :
1.3.1.3 Décès
On représente le nombre cummulé de nouveaux décès par semaine en fonction du temps sur la France entière.
On représente la même figure mais en mettant en relief la répartition des valeurs par région :
On représente la même figure mais en mettant en relief la répartition des valeurs par classe d’âge :
On met les valeurs en pourcentages pour que le graphique soit plus visibles
Enfin, on représente le ratio décès / réanimations :
1.3.2 Graphique d’évolution du nombre d’hospitalisations par départements groupés par région
On va s’intéresser au nombre d’hospitalisations. On peut représenter cette information département par département. Ici, on représente le nombre cummulé d’entrée par semaine en fonction du temps.
On représente d’abord les 4 régions actuellement les plus touchées et pour lesquelles l’axe des ordonnées va de 0 à 1200.
On représente ensuite les 8 régions suivantes les plus touchées mais avec une échelle différente sur l’axe des ordonnées (0 à 400):
Enfin, on représente les 2 régions les moins touchées et avec une échelle différente sur l’axe des ordonnées (0 à 200):
1.3.3 Cartes d’évolution sur les 6 dernières semaines
On représente l’évolution des hospitalisations sur les 6 dernières semaines:
On représente l’évolution des réanimations sur les 6 dernières semaines:
On représente l’évolution des décès sur les 6 dernières semaines: