Construire un diagramme circulaire et un anneau avec coord_polar() — en direct dans votre navigateur
Apprenez à créer un diagramme circulaire et un graphique en anneau en R avec ggplot2 — une barre empilée en coordonnées polaires via coord_polar(). Ajoutez des étiquettes de parts centrées et des pourcentages, construisez un anneau, et sachez quand un diagramme en barres se lit mieux. Modifiez et exécutez le code en direct, sans aucune installation.
Date de publication
8 juillet 2026
Modifié
11 juillet 2026
AstucePoints clés
Un diagramme circulaire est une barre empilée en coordonnées polaires — construisez la barre, puis courbez-la avec coord_polar().
Tracez une seule barre de valeurs avec geom_col(), associez la catégorie à fill, puis enveloppez le tout avec coord_polar(theta = "y").
Retirez les axes et la grille avec theme_void() pour ne garder que les parts.
Placez une étiquette au milieu de chaque part en calculant sa position avec cumsum() en base R.
Un anneau est le même graphique avec un trou — fixez x = 2 et ajoutez xlim(0.5, 2.5).
Les diagrammes circulaires sont difficiles à lire au-delà de quelques parts : pour une comparaison précise, un diagramme en barres l’emporte généralement.
Chaque graphique ci-dessous est déjà rendu pour vous — modifiez ensuite n’importe quel exemple en direct dans le bac à sable.
Un diagramme circulaire montre comment un tout se répartit en parties. Dans ggplot2, il n’existe pas de geom_pie() ; à la place, vous construisez une seule barre empilée que vous courbez en cercle avec coord_polar(). Une fois que vous voyez un diagramme circulaire comme une barre en coordonnées polaires, chaque étape de la recette se met en place.
Cette leçon construit un diagramme circulaire étape par étape — parts de base, étiquettes centrées, pourcentages et un anneau — à partir d’un petit data frame autonome pour que chaque bloc s’exécute seul. Nous signalerons aussi la limite honnête : l’œil humain compare bien mieux les longueurs que les angles, donc lorsque les lecteurs doivent classer ou comparer des valeurs avec précision, un diagramme en barres est le choix le plus clair. Les diagrammes circulaires trouvent leur place pour donner une impression rapide de répartition d’un tout avec seulement une poignée de catégories.
Un diagramme circulaire de base
Commencez par les données : la part des portions quotidiennes pour quatre groupes alimentaires. Tracez une seule barre empilée avec geom_col() (associez la catégorie à fill), puis coord_polar(theta = "y") courbe cette barre en diagramme circulaire. theme_void() retire les axes et le fond gris pour ne montrer que les parts.
library(ggplot2)diet <-data.frame(group =c("Grains", "Vegetables", "Fruits", "Dairy"),value =c(40, 30, 20, 10))ggplot(diet, aes(x ="", y = value, fill = group)) +geom_col(width =1, color ="white") +coord_polar(theta ="y") +scale_fill_viridis_d() +theme_void()
Associer x = "" donne à chaque part la même base, si bien que la barre s’empile en un cercle complet. Le color = "white" ajoute une fine bordure entre les parts.
Compter les catégories directement à partir des données brutes
Le diagramme circulaire de base partait d’un tableau récapitulatif — vous aviez déjà les effectifs (value = c(40, 30, 20, 10)). Souvent, ce n’est pas le cas : vous avez des lignes brutes, une par observation, et vous voulez que ggplot2 les dénombre pour vous. Associez x = factor(1) pour que chaque ligne partage une même barre, puis utilisez geom_bar() — qui compte les lignes de chaque groupe fill — au lieu de geom_col(), qui a besoin de valeurs déjà calculées. Aucune étape table() ni récapitulatif intermédiaire.
library(ggplot2)ggplot(iris, aes(x =factor(1), fill = Species)) +geom_bar(width =1) +# geom_bar COUNTS rows per Species — no pre-summary neededcoord_polar(theta ="y") +scale_fill_viridis_d() +theme_void()
Les données intégrées iris contiennent 150 fleurs — 50 de chaque espèce — donc chaque part est l’effectif de cette catégorie, et les trois ressortent en tiers égaux. Le seul changement par rapport au diagramme circulaire de base est le geom : geom_col() trace les parts aux hauteurs que vous fournissez, tandis que geom_bar() dénombre d’abord les lignes de chaque groupe fill, vous menant directement des observations brutes à un diagramme circulaire. (Remplacez iris par votre propre data frame de lignes brutes — geom_bar() dénombre quelles que soient les catégories qu’il trouve.)
Ajouter une étiquette à chaque part
Un diagramme circulaire est bien plus facile à lire quand la valeur figure sur sa part. L’astuce, c’est la position de l’étiquette : le long de l’axe des y (désormais circulaire), le centre de chaque part correspond au cumul des valeurs jusqu’ici moins la moitié de la valeur courante. En base R, cumsum() donne le total cumulé — aucun package supplémentaire nécessaire.
ggplot2 empile les parts dans l’ordre inverse des niveaux de fill, on ordonne donc les données de la même façon avant de calculer les positions, et l’étiquette tombe pile au centre de chaque part.
library(ggplot2)diet <-data.frame(group =c("Grains", "Vegetables", "Fruits", "Dairy"),value =c(40, 30, 20, 10))# order to match ggplot2's stacking (reverse of the fill levels)diet <- diet[order(diet$group, decreasing =TRUE), ]# label position = centre of each slice, along the y (value) axisdiet$pos <-cumsum(diet$value) -0.5* diet$value# readable label colour per slice: dark on the light (yellow/green) slices, white on the dark onesdiet$lab_col <-ifelse(diet$group %in%c("Vegetables", "Grains"), "grey15", "white")ggplot(diet, aes(x ="", y = value, fill = group)) +geom_col(width =1, color ="white") +coord_polar(theta ="y") +geom_text(aes(y = pos, label = value, colour = lab_col), fontface ="bold") +scale_fill_viridis_d() +scale_colour_identity() +theme_void()
Afficher des pourcentages plutôt que des valeurs brutes
La répartition d’un tout se lit généralement mieux en pourcentages. Calculez la part de chaque groupe dans le total, puis étiquetez avec un signe %. paste0() construit le texte de l’étiquette en base R.
Jusqu’ici, chaque diagramme circulaire a utilisé scale_fill_viridis_d() — adaptée au daltonisme par défaut. Pour respecter une charte graphique ou une palette d’impression, remplacez-la par une autre échelle de remplissage. Deux choix courants :
scale_fill_brewer() — palettes ColorBrewer élaborées. Un nom séquentiel comme "Blues" nuance une seule teinte du clair au foncé ; un nom qualitatif comme "Set2" ou "Dark2" donne des teintes distinctes et adaptées au daltonisme pour des catégories non ordonnées (vous pouvez vérifier l’adaptation au daltonisme de n’importe quelle palette sur colorbrewer2.org).
scale_fill_grey() — niveaux de gris, pour l’impression ou quand la couleur n’est pas disponible.
Conservez le même diagramme circulaire diet et changez seulement l’échelle de remplissage. D’abord, une palette ColorBrewer :
library(ggplot2)diet <-data.frame(group =c("Grains", "Vegetables", "Fruits", "Dairy"),value =c(40, 30, 20, 10))ggplot(diet, aes(x ="", y = value, fill = group)) +geom_col(width =1, color ="white") +coord_polar(theta ="y") +scale_fill_brewer(palette ="Blues") +theme_void()
"Blues" est séquentielle — elle nuance une seule teinte, ce qui convient aux catégories ayant un ordre naturel (faible → élevé). Ces groupes alimentaires ne sont pas ordonnés, donc une palette qualitative ("Set2", "Dark2") garderait les parts distinctes tout en restant adaptée au daltonisme ; remplacez simplement palette = "Blues" par palette = "Set2".
Pour l’impression ou la photocopie, supprimez entièrement la couleur avec scale_fill_grey() :
library(ggplot2)diet <-data.frame(group =c("Grains", "Vegetables", "Fruits", "Dairy"),value =c(40, 30, 20, 10))ggplot(diet, aes(x ="", y = value, fill = group)) +geom_col(width =1, color ="white") +coord_polar(theta ="y") +scale_fill_grey(start =0.3, end =0.8) +theme_void()
start et end fixent le gris le plus foncé et le plus clair (0 = noir, 1 = blanc) ; 0.3–0.8 garde chaque part lisible face aux bordures blanches. Les niveaux de gris sont le choix sûr quand une figure peut être imprimée en noir et blanc.
Quand vous avez besoin de couleurs exactes — une palette de marque, la charte graphique d’un client — nommez-les vous-même avec scale_fill_manual(), une valeur hexadécimale par groupe dans l’ordre où la légende les affiche :
Nommer le vecteur (Grains = "#3a86d4", …) lie chaque couleur à son groupe, de sorte que l’association ne peut pas se décaler quand les données sont réordonnées. Choisissez vous-même des teintes adaptées au daltonisme, ou appuyez-vous sur scale_fill_brewer()/viridis pour le faire à votre place.
Graphique en anneau
Un anneau est un diagramme circulaire avec un trou au milieu — souvent plus reposant pour l’œil car il atténue le centre. Deux changements à la recette du diagramme circulaire : associez x = 2 (pousse l’anneau vers l’extérieur) et ajoutez xlim(0.5, 2.5) (la bande vide 0.5–2 devient le trou). Supprimez l’argument width.
Les angles et les aires sont réellement difficiles à comparer — deux parts de 22 % et 25 % paraissent presque identiques dans un diagramme circulaire. Quand votre lecteur doit classer des catégories ou lire des valeurs avec précision, un diagramme en barres fait mieux le travail : les mêmes données en barres triées se lisent d’un coup d’œil.
library(ggplot2)diet <-data.frame(group =c("Grains", "Vegetables", "Fruits", "Dairy"),value =c(40, 30, 20, 10))# sort bars by value for an instantly readable rankingdiet$group <-reorder(diet$group, diet$value)ggplot(diet, aes(x = group, y = value)) +geom_col(fill ="#3a86d4") +coord_flip() +labs(x =NULL, y ="Servings") +theme_minimal()
Gardez le diagramme circulaire pour un rapide « voici les parties du tout » avec quelques catégories ; passez aux barres dès que la comparaison précise compte.
Essayez en direct
Les graphiques ci-dessus ont été rendus au moment de la construction. Envie d’expérimenter ? Modifiez le code et appuyez sur Run — il s’exécute dans votre navigateur via webR (sans serveur, sans installation).
🟢 Avec un agent IA
Demandez à Prova« transformez mon data frame en un diagramme circulaire ggplot2 étiqueté » — elle répond avec du code que vous pouvez exécuter sur vos propres données, pour que la recette soit reproductible. The runtime is the judge.Demander à Prova →
Questions fréquentes
NoteComment créer un diagramme circulaire dans ggplot2 ?
Il n’existe pas de geom_pie(). Tracez une seule barre empilée de vos valeurs avec geom_col(), associez la catégorie à fill, puis ajoutez coord_polar(theta = "y") pour courber la barre en cercle. Ajoutez theme_void() pour retirer les axes et le fond gris afin de ne garder que les parts.
NotePourquoi mon diagramme circulaire s’affiche-t-il comme une seule barre ou une cible ?
coord_polar() a besoin d’une barre empilée à courber. Assurez-vous d’associer x = "" (une base commune) et y à votre valeur, et que fill est votre catégorie. Si vous associez la catégorie à x au lieu de fill, vous obtenez des barres séparées (une cible) plutôt qu’un seul diagramme circulaire.
NoteComment placer les étiquettes au centre de chaque part ?
Calculez la position de l’étiquette le long de l’axe des y avec cumsum(value) - 0.5 * valueaprès avoir ordonné les données pour correspondre à l’empilement de ggplot2 (inverse des niveaux de fill). Passez cette position à geom_text(aes(y = pos, ...)). Cela centre chaque étiquette dans sa part.
NoteComment transformer un diagramme circulaire en graphique en anneau ?
Reprenez la même recette de diagramme circulaire mais associez x = 2 et ajoutez xlim(0.5, 2.5). La bande vide entre 0.5 et 2 devient le trou au milieu. Vous pouvez supprimer l’argument width de geom_col().
NoteComment changer les couleurs d’un diagramme circulaire ggplot2 ?
Ajoutez une échelle de remplissage. Utilisez scale_fill_brewer(palette = "Set2") pour une palette ColorBrewer élaborée (choisissez-en une qualitative comme "Set2" ou "Dark2" pour des catégories non ordonnées), scale_fill_grey() pour l’impression, ou scale_fill_manual(values = c(...)) pour fixer des couleurs exactes. Le scale_fill_viridis_d() par défaut est déjà adapté au daltonisme.
NoteFaut-il utiliser un diagramme circulaire ou un diagramme en barres ?
N’utilisez un diagramme circulaire que pour une impression rapide de répartition d’un tout avec une poignée de catégories. Quand les lecteurs doivent classer des catégories ou comparer des valeurs avec précision, un diagramme en barres est plus clair — l’œil lit les longueurs bien plus précisément que les angles.
Testez vos connaissances
ImportantExercice : transformer la barre en diagramme circulaire
Le code ci-dessous trace une seule barre empilée. Ajoutez la seule couche coord_*() qui la courbe en diagramme circulaire.
# The layer that bends a bar into a circle takes theta = "y":# coord_polar(theta = "y")
library(ggplot2)
diet <- data.frame(
group = c("Grains", "Vegetables", "Fruits", "Dairy"),
value = c(40, 30, 20, 10)
)
ggplot(diet, aes(x = "", y = value, fill = group)) +
geom_col(width = 1, color = "white") +
coord_polar(theta = "y") +
scale_fill_viridis_d() +
theme_void()
library(ggplot2)diet <-data.frame(group =c("Grains", "Vegetables", "Fruits", "Dairy"),value =c(40, 30, 20, 10))ggplot(diet, aes(x ="", y = value, fill = group)) +geom_col(width =1, color ="white") +coord_polar(theta ="y") +scale_fill_viridis_d() +theme_void()
Vérification rapide : quel argument de coord_polar() associe la hauteur de la barre à l’angle du diagramme circulaire ?
AstuceAfficher la réponse
theta = "y". Il indique à coord_polar() d’enrouler l’attribut esthétique y (vos valeurs empilées) autour du cercle comme angle, transformant chaque valeur en une part proportionnelle.
Conclusion
Vous avez construit un diagramme circulaire ggplot2 en traçant une barre empilée avec geom_col() puis en la courbant avec coord_polar(theta = "y"), centré des étiquettes et des pourcentages avec un cumsum() en base R, et transformé le diagramme circulaire en anneau avec x = 2 + xlim(). Rappelez-vous le compromis : les diagrammes circulaires donnent une impression rapide de répartition d’un tout, mais pour une comparaison précise, tournez-vous vers le diagramme en barres.
Cette leçon est reproductible : les figures sont exécutées au moment de la construction (si elles s’affichent, le code fonctionne), et le bac à sable et le quiz se réexécutent en direct dans votre navigateur. The runtime is the judge.