Graphiques animés en R avec gganimate

Transformez un graphique ggplot2 en une animation fluide avec quelques couches supplémentaires

Data Visualization

Apprenez à créer des graphiques animés en R avec gganimate — enrichissez un graphique ggplot2 de couches de transition et d’easing pour l’animer dans le temps ou entre groupes, puis effectuez son rendu en GIF. Idéal pour montrer un changement au fil du temps et raconter une data story que votre audience regarde vraiment.

Auteur·rice
Date de publication

8 juillet 2026

Modifié

17 juillet 2026

AstuceCe que vous apprendrez
  • L’idée d’une seule couche derrière gganimate : gardez votre ggplot tel quel, puis ajoutez une couche transition_*() pour le mettre en mouvement.
  • transition_reveal() pour tracer une courbe au fil du temps, transition_time() pour déplacer des points à travers une date réelle, et transition_states() pour passer d’un groupe à l’autre par morphing.
  • Comment lisser le mouvement avec ease_aes() et ajouter un titre dynamique qui affiche l’image courante.
  • Comment effectuer le rendu en GIF avec gifski et le sauvegarder avec anim_save() — chaque graphique ci-dessous repose sur du R réel, à copier-coller.

Un graphique statique montre l’état final ; une animation montre le changement. Lorsque votre histoire est « regardez ceci évoluer au fil du temps » — une tendance qui grimpe, une distribution qui se décale, une course entre groupes — un court GIF en boucle retient l’attention bien mieux qu’un mur de petits multiples. Le package gganimate rend cela presque gratuit : vous construisez un graphique ggplot2 ordinaire, ajoutez une seule couche de transition, et gganimate calcule les images intermédiaires (le tween) pour vous.

Cet article utilise le jeu de données intégré airquality (relevés quotidiens de qualité de l’air à New York, de mai à septembre 1973), de sorte que tout s’exécute sans téléchargement de données. Vous n’avez besoin que de deux packages : gganimate (les couches d’animation) et gifski (le moteur de rendu GIF).

# One-time install: the animation layers + a fast GIF renderer
install.packages(c("gganimate", "gifski"))

La recette : un ggplot, plus une couche de transition

Toute l’idée en une phrase : créez un ggplot normal, puis ajoutez une couche transition_*(). Voici un graphique en courbes ordinaire de la température quotidienne, une courbe par mois, coloré avec la palette viridis adaptée au daltonisme. Rien n’y est encore spécifique à l’animation :

library(ggplot2)

p <- ggplot(
  airquality,
  aes(x = Day, y = Temp, group = Month, color = factor(Month))
) +
  geom_line(linewidth = 0.9) +
  scale_color_viridis_d(name = "Month") +
  labs(x = "Day of month", y = "Temperature (°F)") +
  theme_minimal(base_size = 13)

p

A static ggplot2 line chart of daily temperature for five months, May through September 1973, one viridis-colored line per month.

A ggplot2 line chart of daily air temperature across five months, May through September 1973, with one viridis-colored line per month.

Pour l’animer, ajoutez transition_reveal(Day). Cela indique à gganimate de tracer les courbes progressivement le long de l’axe Day, de sorte que chaque image en révèle un peu plus de chaque mois. Assignez le résultat et effectuez son rendu avec animate(), en choisissant le gifski_renderer() et un nombre d’images modéré pour que le GIF reste léger :

library(gganimate)

anim <- p + transition_reveal(Day)

animate(anim, renderer = gifski_renderer(), device = "ragg_png",
        width = 440, height = 320, units = "px", res = 100, nframes = 24, fps = 8)

An animated ggplot2 line chart where five monthly temperature lines are drawn progressively day by day, May through September 1973.

C’est tout le schéma. Les courbes que vous aviez déjà grandissent maintenant de gauche à droite, un jour à la fois, et les cinq mois avancent ensemble. Vous avez changé une seule chose : vous avez ajouté une couche de transition. Tout le reste — les attributs esthétiques, la palette, le thème — a été repris tel quel.

transition_time() : se déplacer dans le temps réel

transition_reveal() conserve l’historique à l’écran (la courbe reste tracée). Souvent, vous voulez l’inverse : un unique marqueur qui se déplace dans le temps, en ne montrant que l’instant courant. C’est transition_time(), et il excelle pour une bulle en mouvement.

Ci-dessous, chaque ligne d’airquality devient le relevé d’un jour — l’ozone en fonction de la température, avec le point dimensionné selon le vent. Nous construisons une véritable colonne Date à partir du mois et du jour (base R, sans package supplémentaire), écartons les jours dont l’ozone est manquant, et animons selon cette date. Deux touches la rendent lisible : un titre dynamique qui affiche la date courante grâce à la variable d’étiquette {frame_time}, et shadow_wake() pour laisser une courte traînée en fondu derrière la bulle :

library(ggplot2)
library(gganimate)

# Self-contained: build a date and keep days with a measured ozone value
aq <- airquality[!is.na(airquality$Ozone), ]
aq$date <- as.Date(paste(1973, aq$Month, aq$Day, sep = "-"))

b <- ggplot(aq, aes(x = Temp, y = Ozone, size = Wind)) +
  geom_point(color = "#3a86d4", alpha = 0.8) +
  scale_size(range = c(2, 10), name = "Wind (mph)") +
  labs(title = "Date: {frame_time}",
       x = "Temperature (°F)", y = "Ozone (ppb)") +
  theme_minimal(base_size = 13)

anim <- b +
  transition_time(date) +
  shadow_wake(wake_length = 0.1, alpha = FALSE)

animate(anim, renderer = gifski_renderer(), device = "ragg_png",
        width = 440, height = 320, units = "px", res = 100, nframes = 24, fps = 8)

An animated bubble tracing daily ozone against temperature over the summer of 1973, sized by wind, with a short fading trail and a live date title.

La bulle saute d’un point à l’autre du plan température–ozone jour après jour, et la traînée rend le chemin lisible. Le titre se met à jour automatiquement car gganimate expose des variables d’image à l’intérieur de { } : transition_time() vous donne frame_time (la valeur temporelle courante). Si vous préférez garder les points bruts visibles en arrière-plan plutôt qu’un sillage, remplacez shadow_wake() par shadow_mark().

transition_states() : passer d’un groupe à l’autre par morphing

Le troisième cas courant n’a aucun axe temporel — vous voulez parcourir des catégories, en passant en douceur de l’une à la suivante par morphing. C’est transition_states(). Ici, nous résumons d’abord la température moyenne par mois avec la fonction aggregate() de base R, puis animons un diagramme en barres qui grandit et se fond d’un mois à l’autre.

mean_temp <- aggregate(Temp ~ Month, data = airquality, FUN = mean)
mean_temp$month <- factor(month.name[mean_temp$Month], levels = month.name)
mean_temp
  Month     Temp     month
1     5 65.54839       May
2     6 79.10000      June
3     7 83.90323      July
4     8 83.96774    August
5     9 76.90000 September

Le tableau affiché montre la température qui grimpe vers un pic de milieu d’été puis redescend d’ici septembre. Animons-le maintenant. Nous ajoutons enter_grow() + enter_fade() pour que chaque barre apparaisse en grandissant, ease_aes("cubic-in-out") pour que le mouvement accélère puis se stabilise au lieu d’avancer à vitesse constante, et la variable d’étiquette {closest_state} pour afficher le mois à l’écran :

library(ggplot2)
library(gganimate)

mean_temp <- aggregate(Temp ~ Month, data = airquality, FUN = mean)
mean_temp$month <- factor(month.name[mean_temp$Month], levels = month.name)

s <- ggplot(mean_temp, aes(x = month, y = Temp, fill = Temp)) +
  geom_col(show.legend = FALSE) +
  scale_fill_viridis_c() +
  labs(title = "Month: {closest_state}",
       x = NULL, y = "Mean temperature (°F)") +
  theme_minimal(base_size = 13)

anim <- s +
  transition_states(month, wrap = FALSE) +
  enter_grow() +
  enter_fade() +
  ease_aes("cubic-in-out")

animate(anim, renderer = gifski_renderer(), device = "ragg_png",
        width = 440, height = 320, units = "px", res = 100, nframes = 24, fps = 8)

Animated bars of mean monthly temperature morphing between May and September, each bar growing and fading in, filled by a viridis color scale.

Chaque barre apparaît en grandissant à mesure que son mois devient l’état actif, et ease_aes() donne à cette croissance un rendu naturel. transition_states() fonctionne aussi avec des facettes — ajoutez facet_wrap() à votre graphique de base exactement comme d’habitude, et chaque panneau s’anime en cadence.

Sauvegarder votre animation

animate() renvoie l’animation, et anim_save() l’écrit sur le disque. Comme ggsave(), elle récupère la dernière animation rendue si vous ne lui en passez pas une explicitement :

anim <- s + transition_states(month, wrap = FALSE) + ease_aes("cubic-in-out")

# Render, then save the last animation as a GIF
animate(anim, renderer = gifski_renderer(), nframes = 50, fps = 10)
anim_save("temperature-by-month.gif")

Deux réglages contrôlent la durée et la fluidité : nframes (plus d’images = plus fluide et plus lourd) et fps (images par seconde = vitesse de lecture) ; ensemble, ils fixent la durée (nframes / fps secondes). Gardez les deux modérés pour un GIF léger. Pour un MP4 plutôt qu’un GIF, installez le package av et passez renderer = av_renderer("out.mp4").

Questions fréquentes

Effectuez le rendu avec animate(), puis appelez anim_save("file.gif") — elle sauvegarde par défaut la dernière animation rendue, ou passez-en une explicitement avec anim_save("file.gif", animation = my_anim). Pour un GIF, utilisez renderer = gifski_renderer() ; pour un MP4, installez le package av et utilisez renderer = av_renderer("file.mp4").

Un objet gganimate ne devient une animation qu’une fois qu’une couche transition_*() a été ajoutée et que l’objet est rendu. Assurez-vous d’avoir ajouté une transition (par exemple + transition_time(date)), d’imprimer ou d’animate() l’objet, et qu’un moteur de rendu tel que gifski est installé. Dans un bloc Quarto ou R Markdown, assigner l’objet puis le laisser s’imprimer (ou appeler animate()) produit le GIF.

transition_time() parcourt une variable continue (une date ou un nombre) et ne montre que l’instant courant — idéal pour une bulle en mouvement. transition_reveal() suit lui aussi une dimension continue mais conserve ce qui a déjà été tracé, révélant ainsi une courbe progressivement. transition_states() parcourt une variable catégorielle, en passant d’un groupe discret à l’autre par morphing.

Passez nframes (nombre total d’images — plus il est élevé, plus c’est fluide mais lourd) et fps (images par seconde — plus il est élevé, plus c’est rapide) à animate(). La durée de lecture est de nframes / fps secondes. Pour un GIF web compact, des valeurs comme nframes = 50 et fps = 10 constituent un bon point de départ.

gganimate expose des variables d’image que vous pouvez référencer dans { } au sein de n’importe quelle étiquette. transition_time() fournit {frame_time}, transition_states() fournit {closest_state}, et transition_reveal() fournit {frame_along} — par exemple labs(title = "Date: {frame_time}") met à jour le titre à chaque image.

Pour aller plus loin dans /learn

Cet article est la recette ciblée. gganimate est une couche d’extension par-dessus ggplot2 : plus votre graphique de base est solide, meilleure sera votre animation. Pour les leçons pas à pas, à reproductibilité garantie, sur les graphiques que vous animerez, voir :

Voir aussi

🟢 Avec un agent IA

Demandez à Prova « anime mon graphique en courbes ggplot2 au fil du temps avec gganimate et sauvegarde-le en GIF » — elle répond avec du code que vous pouvez exécuter sur vos propres données. The runtime is the judge. Demander à Prova →

Cette page vous a-t-elle été utile ?

Recevez les nouvelles leçons R & Python par e-mail

Pratique, reproductible, sans spam. Désinscription à tout moment.

Double opt-in. Nous ne partageons jamais votre e-mail.

Partager cette pageXLinkedInRedditHN

Citation

BibTeX
@online{kassambara2026,
  author = {Kassambara, Alboukadel},
  title = {Graphiques animés en R avec gganimate},
  date = {2026-07-08},
  url = {https://www.datanovia.com/blog/animated-plots-in-r-gganimate},
  langid = {fr}
}
Veuillez citer ce travail comme suit :
Kassambara, Alboukadel. 2026. “Graphiques animés en R avec gganimate.” July 8. https://www.datanovia.com/blog/animated-plots-in-r-gganimate.