[1] "2023-11-14" "2024-11-14" "2025-11-14"
[1] "2023-01-01" "2024-01-01" "2025-01-01"
[1] "2023-01-01" "2024-02-01" "2025-03-01"
vignettes/temporelles.qmd
Règle 1 : On utilise
theme_ofce()
pour les graphiques !
Règle 2 : Les dates sont au format
<date>
même lorsque la fréquence est annuelle.
Règle 3 : On utilise
scale_x_date(date_breaks = "5 years", date_minor_breaks = "1 year", guide = "minor_ticks")
en définissantdate_breaks
à la fréquence souhaitée (en évitant trop de dates) etdate_minor_breaks
à une année ("1 year"
).
Règle 4 : Si les y sont en %, alors mettre “%” dans le format de l’axe des y.
Règle 5 : On choisit un
line_width
entre 0.5 et 1 pour legeom_line()
, on ajoute ungeom_point(shape=21, stroke=0.25, col="white")
pour marquer les points auxquels on a des données. Si on peut mettre la légende sous forme de labels, c’est mieux car cela allège le graphique.
Pour les séries temporelles, il y a deux recommandations pour les données :
utilisez le format long pour les données du graphique. Il peut être plus simple pour calculer des taux de croissance ou des ratios de passer en format large, mais c’est mieux de passer en format long pour la partie graphique, avec une ou plusieurs colonnes pour différencier les lignes. Cela permettra d’associer une couleur à chaque série et une facette à chaque pays par exemple.
le champ décrivant les dates doit être en type date
. ce n’est pas toujours évident quand les séries sont à fréquence annuelle, mais c’est très utile pour mélanger des séries de fréquence irrégulière, pour homogénéiser l’aspect des axes de dates et mieux maîtriser le formatage des dates. Pour convertir une date en date, soit elle est au format <character>
sous la forme "2022-12-01"
et la fonction base::as.Date()
fonctionne très bien. Sinon, pour les autres cas, le package lubridate (formation R niv. 1) est très pratique et propose de nombreuses fonctions permettant d’absorber beaucoup de cas (les fonctions sont par exemple lubridate::ymd()
lubridate::dmy()
lubridate::my()
etc…).
[1] "2023-11-14" "2024-11-14" "2025-11-14"
[1] "2023-01-01" "2024-01-01" "2025-01-01"
[1] "2023-01-01" "2024-02-01" "2025-03-01"
Note
Dans le cas où les données proviennent d’Excel et sont en format numérique on peut utiliser
as.Date(df$date, origin = "1899-12-30")
pour les convertir en<date>
.
Prenons l’exemple du graphiques sur les spreads (legislatives2024, Blot Geerolf Plane). Les données sont générées par un scrapping sur investing.com (en attendant une solution API sur une banque de données bien faite). Les données se présentent sous la forme.
# A tibble: 10,117 × 3
date pays taux
<date> <chr> <dbl>
1 2007-01-02 spreadfra 0.0130
2 2007-01-03 spreadfra 0.0360
3 2007-01-04 spreadfra 0.0280
4 2007-01-05 spreadfra 0.0190
5 2007-01-08 spreadfra 0.0440
6 2007-01-09 spreadfra 0.0430
7 2007-01-10 spreadfra 0.0290
8 2007-01-11 spreadfra 0.0370
9 2007-01-12 spreadfra 0.0340
10 2007-01-15 spreadfra 0.0380
# ℹ 10,107 more rows
Les données sont au format long (avec deux modalités pour pays
et donc 3 colonnes), les dates sont au format <date>
, donc tout va presque bien. La colonne pays
est un peu brute. On la transforme pour avoir un label plus propre et en facteur, pour contrôler l’ordre (on met France en premier, Italie en second). Il y a plusieurs méthodes pour arriver à ce résultat. Ici, on reste très simple parce qu’il n’y a que deux modalités. Si il y en avait plus de deux (et surtout un grand nombre, possiblement évolutif), on aurait fait quelques manipulations de chaînes et on aurait utilisé le package countrycode pour transformer les code pays en texte lisible, possiblement traduit dans différentes langues.
# A tibble: 10,117 × 3
date pays taux
<date> <chr> <dbl>
1 2007-01-02 spreadfra 0.0130
2 2007-01-03 spreadfra 0.0360
3 2007-01-04 spreadfra 0.0280
4 2007-01-05 spreadfra 0.0190
5 2007-01-08 spreadfra 0.0440
6 2007-01-09 spreadfra 0.0430
7 2007-01-10 spreadfra 0.0290
8 2007-01-11 spreadfra 0.0370
9 2007-01-12 spreadfra 0.0340
10 2007-01-15 spreadfra 0.0380
# ℹ 10,107 more rows
Le graphique de base est alors simple à construire. On utilise une couche geom_line()
et geom_point()
, une couche aes()
avec comme x
les dates, y
les taux et couleurs les pays. Pour geom_line()
, il faut préciser le groupe (cela peut paraître redondant, mais cela peut servir si on veut colorer en fonction d’une autre variable). L’ordre est important et le geom_line()
est en premier et donc en dessous du geom_point()
.
On utilise la palette summer de PrettyCols (affaire de goût). On utilise la fonction theme_ofce()
pour homogénéiser la présentation des graphiques. On précise les labels des axes inutile pour x
, explicite pour y
. Et la source, en notant que l’on peut utiliser markdown
dans le texte de la source, ce qui permet de mettre Source en italique.
Le recours à scale_x_date()
permet de spécifier facilement le format des dates (avec la syntaxe de base::strptime()
) et la fonction scale::label_date_short()
permet un formatage élégant des dates (voir plus bas la partie insert).
On ajoute au graphique des annotations. C’est ici faid de façon laborieuse, on peut construire des fonctions (formation R niv. 2) ou utiliser esquisse ou {gganotate}
mais ces deux solutions ont des défauts.
Pour les annotations on peut utiliser différentes méthodes. La plus laborieuse est la fonction ggplot2::annotate()
. La plus élégante est ggforce::geom_mark_circle()
ou ggrepel::geom_repel_text()
.
Le résultat est intéressant, mais le graphique a cependant un défaut, il y a trop de points, ce qui est du à la fréquence quotidienne et donc il perd en clarté. On va donc faire deux choses : réduire la fréquence en agrégeant les données par mois, puis on va ajouter un insert.
Pour construire les données à la fréquence mensuelle, on va créer un champ de date, mais retenant une seule date par mois (au milieu du mois). En agrégeant par mois (summarise
) on construit la série en mensuel.
# A tibble: 422 × 5
# Groups: date [211]
date pays taux_max taux_min taux
<date> <fct> <dbl> <dbl> <dbl>
1 2007-01-15 France 0.0580 0.0130 0.0409
2 2007-01-15 Italie 0.278 0.154 0.229
3 2007-02-15 France 0.0560 0.0380 0.0440
4 2007-02-15 Italie 0.284 0.17 0.211
5 2007-03-15 France 0.0630 0.0350 0.0466
6 2007-03-15 Italie 0.318 0.192 0.239
7 2007-04-15 France 0.0690 0.0410 0.0496
8 2007-04-15 Italie 0.285 0.153 0.225
9 2007-05-15 France 0.0980 0.0330 0.0464
10 2007-05-15 Italie 0.291 0.175 0.222
# ℹ 412 more rows
On peut alors facilement modifier le graphique main
en utilisant %+%
(cette instruction modifie les données en entrée du graphique par le nouveau jeu de données qu’on vient de construire qui a exactement la même structure, comme on a utilisé les dates le passage du quotidien au mensuel se fait automatiquement, les axes sont parfaitement construits) :
L’insert est le même graphique, en enlevant les annotations, en simplifiant les axes et en zoomant sur les deux derniers mois.
On l’insère dans le graphique principal en utilisant patchwork, ce qui donne le graphique, plus lisible et plus élégant. Les paramètres de inset
sont choisis après quelques essais et erreurs. On a réduit la taille de la police de caractère pour accentuer l’effet visuel.
Tip 1: Une alternative avec {ggmagnify}
Le package ggmagnify simplifie la tâche et offre quelques améliorations esthétiques. Il faut cependant que les dataset principal et inset soit les mêmes [pas sûr en fait]. On reprend l’agrégation temporelle en l’arrêtant aux deux derniers mois. On complexifie l’insert pour intégrer plus d’éléments en utilisant l’argument
plot
deggmagnify::geom_magnify()
.
La dernière étape est l’interactivité. On utilise le package ggiraph qui va permettre d’intégrer des tooltips très simplement et très efficacement. On peut aussi avec des sélections dynamiques ou encore des zooms.
Pour ajouter l’interactivité, la première étape est de générer le texte des tooltips dans le tableau de données. Notez l’utilisation de lubridate::stamp_date()
pour formater les dates simplement.
L’interactivité est alors ajoutée par des instructions spécifiques qui se substituent aux geom_*
en ajoutant un suffix, geom_*_interactive
. Ces geom_*_interactive
acceptent un aes
avec deux paramètres supplémentaire, le premier définissant le tooltip
et le second, data_id
, une variable qui relie les éléments graphiques entre eux pour qu’ils soient modifiés lors du survol avec la souris. La fonction girafy
qui est définie par source("rinit.r")
et finalise le rendu. ggiraph conserve tous les éléments du graphique et il est possible de l’appliquer avec patchwork pour combiner les interactivités.
La clef pour l’interactivité est d’apporter de l’information à l’utilisateur par le texte du tooltip. Il est possible d’avoir des interactivités plus avancées, en déclenchant une action sur un click par exemple. L’approche par ggiraph est applicable simplement à de nombreux graphiques avec un rendu satisfaisant. Cela marche également pour des facet
et donc ça ouvre beaucoup de possibilités.
On transforme les données en fréquence trimestrielle en utilisant la fonction lubridate::floor_date()
. En calculant les variables année (y
) et trimestre (q
), on peut avec le package ggh4x produire facilement un joli graphique trimestriel. Les clefs sont de mettre en x l’interaction entre ces deux éléments discrets (attention à l’ordre, attention à trier les données avec arrange
). La magie opère ensuite avec guide = "axis_nested"
. Cete fonction est généralisable à bien des cas.
Non mais ca va pas ?
Une bonne pratique est de mettre à disposition les données et le code ayant servi à produire le graphique. Une façon est d’utiliser les boutons code présents dans ce document pour publier le code. La seconde est de mettre tous les codes sur un dépôt github 😸 public.
A minima, on ajoute un bouton pour télécharger les données. C’est simple à faire avec downloadthis et ce bout de code qui peut être mis juste après un graphique. On reprend le fichier de données, tel quel, modifié éventuellement pour enlever ou renommer une colonne, et qui sera disponible en csv, UTF8, avec des virgules comme sépérateurs et des points comme marque décimale (i.e. pas ce qu’Excel attend ☠️).
Pour que les boutons soient sur la même ligne on utilise la syntaxe inline 'r une_expression_R'
:
On peut aussi les mettre dans la marge en entourant le chunk R de ::: column-margin ⏎ un_code_r ⏎ :::
(visuellement c’est mieux quand il y a le graphique juste avant le div).