
Introduction
Il existe de nombreuses astuces ggplot2 permettant d’améliorer assez simplement la lisibilité et l’apparence de ses graphiques avec R. J’ai récemment consulté une présentation de Cara Thompson, consultante spécialisée en visualisation de données, réalisée dans le cadre des Rencontres R 2026.
Intitulée Bien plus qu’un beau graphique : Créativité et accessibilité avec ggplot2, elle rassemble une quinzaine d’astuces.
J’ai trouvé plusieurs de ces idées intéressantes et j’ai eu envie de les tester sur mes propres graphiques. Certaines m’étaient déjà familières, mais je ne les utilisais pas toujours, ou pas forcément de la meilleure façon. D’autres m’ont permis de découvrir des possibilités de ggplot2 que je connaissais moins.
Je n’ai pas cherché à reprendre systématiquement toutes les astuces proposées par Cara Thompson. J’ai plutôt retenu celles qui m’ont paru les plus intéressantes ou les plus utiles dans ma pratique.
Dans cet article, je vous propose donc de partager les essais que j’ai réalisé. Nous verrons notamment comment jouer sur les couleurs, la typographie, les espacements, les fonds, les annotations ou encore l’orientation de certains textes. Et nous terminerons en regroupant plusieurs de ces choix dans un thème ggplot2 personnalisé et réutilisable.
1.Créer des palettes de couleurs franches et douces
Le choix des couleurs joue un rôle important dans le rendu d’un graphique. Une même représentation peut donner une impression très différente selon que l’on utilise des couleurs franches et contrastées ou, au contraire, des teintes plus douces et moins saturées.
Pour comparer ces deux possibilités, nous allons créer deux palettes à partir des mêmes couleurs de base : une première palette avec des couleurs relativement franches et une seconde avec des nuances plus douces.
Dans ggplot2, une palette personnalisée peut simplement être définie sous la forme d’un vecteur contenant les codes hexadécimaux des couleurs à utiliser :
mes_couleurs <- c(
setosa = "#4E79A7",
versicolor = "#F28E2B",
virginica = "#59A14F"
)
mes_couleurs_douces <- c(
setosa = "#AFCBE3",
versicolor = "#F6C08A",
virginica = "#B7D7A8"
)Nous pouvons maintenant appliquer successivement ces deux palettes au même graphique, afin que seule la couleur varie d’une représentation à l’autre. Ici, nous utiliserons un boxplot auquel sont ajoutées les observations individuelles.
Une fois la palette définie, elle peut être facilement appliquée à un graphique ggplot2. La fonction à utiliser dépend de l’élément auquel la couleur est associée : scale_fill_manual() permet de définir les couleurs de remplissage, par exemple pour des boxplots ou des barres, tandis que scale_color_manual() permet de définir la couleur des points ou des lignes.
Dans notre exemple, les couleurs sont utilisées pour remplir les boxplots. Nous utiliserons donc scale_fill_manual()en lui indiquant la palette souhaitée :
scale_fill_manual(values = mes_couleurs)
Il suffit ensuite de remplacer mes_couleurs par mes_couleurs_douces pour obtenir exactement le même graphique avec la seconde palette.
library(ggplot2)
library(patchwork)
p1 <- ggplot(
iris,
aes(
x = Species,
y = Sepal.Length,
fill = Species
)
) +
geom_boxplot(
alpha = 1,
outlier.shape = NA
) +
geom_jitter(
width = 0.15,
size = 1.8,
alpha = 0.7
) +
scale_fill_manual(values = mes_couleurs) +
labs(
title = "Couleurs classiques",
x = NULL,
y = "Longueur du sépale"
) +
theme_bw() +
theme(legend.position = "none")
p2 <- ggplot(
iris,
aes(
x = Species,
y = Sepal.Length,
fill = Species
)
) +
geom_boxplot(
alpha = 1,
outlier.shape = NA
) +
geom_jitter(
width = 0.15,
size = 1.8,
alpha = 0.7
) +
scale_fill_manual(values = mes_couleurs_douces) +
labs(
title = "Couleurs douces",
x = NULL,
y = "Longueur du sépale"
) +
theme_bw() +
theme(legend.position = "none")
p1 + p2
Comment choisir des couleurs douces dans R ?
Les couleurs classiques comme les couleurs douces peuvent être sélectionnées facilement à l’aide de l’add-in Colour Picker disponible dans RStudio.
Pour l’utiliser, il faut tout d’abord installer le package colourpicker. Dans RStudio, allez dans le menu Packages > Install, puis recherchez et installez le package colourpicker.
Une fois le package installé, ouvrez le menu Addins, situé dans la barre de menus de RStudio, puis sélectionnez ggplot2 Colour Picker.
Dans la partie inférieure de la fenêtre, l’outil Find a Colour permet de partir d’une couleur principale et d’en afficher différentes nuances. Vous pouvez par exemple demander l’affichage de 40 couleurs, puis sélectionner la couleur qui servira de point de départ. L’outil propose alors une gamme de nuances autour de cette couleur, ce qui permet de choisir assez facilement une teinte plus ou moins intense selon le rendu recherché.

Il suffit de répéter l’opération pour chacune des couleurs de la palette.
Une fois les couleurs sélectionnées, cliquez sur Done. Les couleurs choisies peuvent être retournées sous différentes formes, notamment sous la forme de codes hexadécimaux, particulièrement pratiques pour les utiliser ensuite dans ggplot2 :
mes_couleurs_douces <- c(
setosa = "#AFCBE3",
versicolor = "#F6C08A",
virginica = "#B7D7A8"
)Comme expliqué précédemment, la palette peut ensuite être appliquée au graphique avec scale_fill_manual() pour les couleurs de remplissage ou scale_color_manual() pour les lignes et les points.
Vous trouverez plus d’information sur l’outil colourpicker dans l’article Choisissez et modifiez très facilement les couleurs de vos graphs R avec Colour Picker
2. Renforcer la lisibilité avec des formes de points qui ont un contour
Lorsque les couleurs utilisées sont très douces, les points peuvent parfois manquer de contraste, en particulier sur un fond clair. Une possibilité consiste alors à utiliser des formes de points possédant à la fois une couleur de remplissage et une couleur de contour.
Dans ggplot2, l’argument shape permet de choisir la forme utilisée pour représenter les points. Certaines formes, notamment les formes 21 à 25, ont la particularité de posséder deux éléments dont la couleur peut être définie séparément :
fillcontrôle la couleur de remplissage du point ;colourcontrôle la couleur de son contour.
Par exemple, shape = 21 correspond à un cercle qui peut être rempli. Nous pouvons donc utiliser nos couleurs douces pour son remplissage et ajouter un contour gris afin de mieux délimiter chaque point. Comparons les deux représentations :
# Sans contour
p1 <-ggplot(iris, aes(Petal.Length, Petal.Width, colour = Species)) +
geom_point()+
scale_colour_manual(values = mes_couleurs_douces) +
labs(
title = "Sans contour",
x = "Longueur des pétales (cm)",
y = "Largeur des pétales (cm)",
colour = "Espèce"
) +
theme_bw()
# Avec contour
p2 <- ggplot(iris, aes(Petal.Length, Petal.Width, fill = Species)) +
geom_point(shape=21, colour="grey50")+
scale_fill_manual(values = mes_couleurs_douces) +
labs(
title = "Avec contour",
x = "Longueur des pétales (cm)",
y = "Largeur des pétales (cm)",
fill = "Espèce"
) +
theme_bw()
p1 + p2
Dans le premier graphique, la couleur des points est directement associée à l’espèce avec colour = Species. La palette est donc appliquée avec scale_colour_manual(). Dans le second graphique, nous utilisons shape = 21. Comme cette forme peut être remplie, nous associons cette fois l’espèce à fill :aes(fill = Species) et nous appliquons notre palette avec : scale_fill_manual(values = mes_couleurs_douces)
3. Modifier les tailles de texte
Adapter la taille des textes avec rel()
La taille des textes joue également un rôle important dans la lisibilité d’un graphique. Dans ggplot2, elle peut être modifiée à l’aide de element_text() et de son argument size.
On pourrait bien sûr attribuer une taille précise à chaque élément du graphique, par exemple size = 12 ou size = 14. Une autre possibilité consiste à utiliser la fonction rel(), qui permet de définir la taille d’un texte relativement à la taille de référence du thème.
Par exemple :
theme(
axis.title = element_text(size = rel(1.2)),
axis.text = element_text(size = rel(1.1)),
legend.title = element_text(size = rel(1.2)),
legend.text = element_text(size = rel(1.1)),
plot.title = element_text(size = rel(1.3))
)Ici, rel(1.2) signifie que le texte sera affiché à 120 % de sa taille de référence, tandis que rel(1.1) correspond à 110 %. Une valeur inférieure à 1 permettrait au contraire de réduire la taille du texte. Dans l’exemple suivant, nous comparons le graphique obtenu avec theme_bw() au même graphique dans lequel les différents éléments textuels ont été agrandis à l’aide de rel().
# Graphique de base
p_base <- ggplot(iris, aes(Petal.Length, Petal.Width, fill = Species)) +
geom_point(shape = 21, colour = "grey50") +
scale_fill_manual(values = mes_couleurs_douces) +
labs(
title = "Graphique de base",
x = "Longueur des pétales (cm)",
y = "Largeur des pétales (cm)",
fill = "Espèce"
) +
theme_bw()
# Même graphique avec tailles de texte modifiées
p_rel <- ggplot(iris, aes(Petal.Length, Petal.Width, fill = Species)) +
geom_point(shape = 21, colour = "grey50") +
scale_fill_manual(values = mes_couleurs_douces) +
labs(
title = "Textes du titre ajustés avec rel()",
x = "Longueur des pétales (cm)",
y = "Largeur des pétales (cm)",
fill = "Espèce"
) +
theme_bw() +
theme(
axis.title = element_text(size = rel(1.2)),
axis.text = element_text(size = rel(1.1)),
legend.title = element_text(size = rel(1.2)),
legend.text = element_text(size = rel(1.1)),
plot.title = element_text(size = rel(1.3))
)
# Affichage côte à côte
p_base + p_rel
L’intérêt de rel() est de conserver des proportions cohérentes entre les différents éléments textuels. Plutôt que de fixer indépendamment la taille du titre, des axes, des graduations ou de la légende, on indique leur importance relative.
Modifier la taille de base :
Il est également possible de modifier en une seule fois la taille de base utilisée par le thème. Les thèmes de ggplot2, comme theme_bw(), possèdent pour cela un argument base_size.
Par exemple : theme_bw(base_size = 16) augmente globalement la taille des textes du graphique, tandis que theme_bw(base_size = 8) les réduit.
L’exemple suivant permet de visualiser directement l’effet de cette modification :
p_8 <- ggplot(iris, aes(Petal.Length, Petal.Width, fill = Species)) +
geom_point(shape = 21, colour = "grey50") +
scale_fill_manual(values = mes_couleurs_douces) +
labs(
title = "Taille base = 8",
x = "Longueur des pétales (cm)",
y = "Largeur des pétales (cm)",
fill = "Espèce"
) +
theme_bw(base_size = 8)
p_16 <- ggplot(iris, aes(Petal.Length, Petal.Width, fill = Species)) +
geom_point(shape = 21, colour = "grey50") +
scale_fill_manual(values = mes_couleurs_douces) +
labs(
title = "Taille base = 16",
x = "Longueur des pétales (cm)",
y = "Largeur des pétales (cm)",
fill = "Espèce"
) +
theme_bw(base_size = 16)
p_8 + p_16
4. Modifier la police
Le choix de la police de caractères peut modifier sensiblement l’apparence d’un graphique. Dans ggplot2, il est possible d’appliquer une même police à l’ensemble des éléments textuels du graphique, mais aussi de personnaliser séparément certains d’entre eux.
Pour modifier la police de tous les textes d’un graphique, on peut utiliser l’argument family de element_text() appliqué à l’élément text du thème.
Comparons par exemple le graphique obtenu avec la police par défaut de ggplot2 au même graphique utilisant la police Times :
# Police par défaut
p_base <- ggplot(
iris,
aes(x = Species, y = Sepal.Width, fill = Species)
) +
geom_boxplot(width = 0.6, colour = "#333333") +
scale_fill_manual(values = mes_couleurs) +
labs(
title = "Police par défaut",
x = NULL,
y = "Largeur des sépales (cm)",
fill = "Espèce"
) +
theme_bw(base_size = 13)
# Police Times
p_times <- ggplot(
iris,
aes(x = Species, y = Sepal.Width, fill = Species)
) +
geom_boxplot(width = 0.6, colour = "#333333") +
scale_fill_manual(values = mes_couleurs) +
labs(
title = "Police Times",
x = NULL,
y = "Largeur des sépales (cm)",
fill = "Espèce"
) +
theme_bw(base_size = 13) +
theme(
text = element_text(family = "Times")
)
p_base + p_times
L’instruction :
text = element_text(family = "Times")s’applique à l’ensemble des éléments textuels du graphique : titre, axes, graduations et légende. Cela permet donc de modifier très simplement l’apparence générale du graphique sans avoir à intervenir sur chaque élément séparément.
Il n’est pas nécessaire d’utiliser la même police partout. Une police peut être définie pour l’ensemble du graphique, puis remplacée uniquement pour certains éléments.
ggplot(iris, aes(x = Species, y = Sepal.Width, fill = Species)) +
geom_boxplot(width = 0.6, colour = "#333333") +
scale_fill_manual(values = mes_couleurs) +
labs(
title = "Le titre est en police Times",
subtitle = "Le reste est en Courier New",
x = NULL,
y = "Largeur des sépales, en cm",
fill = "Espèce"
) +
theme(
base_size = 13,
text = element_text(family = "Courier New"),
plot.title = element_text(family = "Times", face = "bold")
)

Ici, text = element_text(family = “Courier New”) définit la police utilisée par défaut dans l’ensemble du graphique. L’instruction appliquée à plot.title vient ensuite remplacer ce choix uniquement pour le titre, qui est affiché en Times. On peut procéder de la même manière avec les autres éléments du graphique, par exemple axis.title, axis.text, legend.title, legend.text ou encore plot.subtitle.
Comment connaître les polices disponibles ?
Les polices utilisables dépendent notamment de celles qui sont installées sur l’ordinateur. Le package systemfonts permet de connaître les polices auxquelles R a accès. Après avoir installé et chargé le package :
install.packages("systemfonts")Pour obtenir la liste des polices disponibles :
library(systemfonts)
polices <- system_fonts() |>
dplyr::distinct(family) |>
dplyr::arrange(family)
polices# A tibble: 185 × 1
family
<chr>
1 Academy Engraved LET
2 Al Bayan
3 Al Nile
4 Al Tarikh
5 American Typewriter
6 Andale Mono
7 Apple Braille
8 Apple Chancery
9 Apple Color Emoji
10 Apple SD Gothic Neo
# ℹ 175 more rowsPlus d’infos sur la gestion des police dans l’article de Cara Thompson : Getting fonts to work with R
5. De la place pour respirer
Un graphique peut contenir tous les bons éléments et néanmoins paraître chargé si ceux-ci sont trop proches les uns des autres. Ajouter un peu d’espace autour du titre, des axes ou du graphique lui-même permet souvent d’en améliorer la lisibilité.
Dans ggplot2, ces espacements peuvent être contrôlés à l’aide de l’argument margin de element_text() et de la fonction margin().
Comparons le graphique initial avec une version dans laquelle davantage d’espace a été ajouté entre les différents éléments.
p_base <- ggplot(iris, aes(Petal.Length, Petal.Width, fill = Species)) +
geom_point(shape = 21, colour = "grey50") +
scale_fill_manual(values = mes_couleurs_douces) +
labs(
title = "Graphique de base",
x = "Longueur des pétales (cm)",
y = "Largeur des pétales (cm)",
fill = "Espèce"
) +
theme_bw()
p_aere <- ggplot(iris, aes(Petal.Length, Petal.Width, fill = Species)) +
geom_point(shape = 21, colour = "grey50") +
scale_fill_manual(values = mes_couleurs_douces) +
labs(
title = "Graphique aéré",
x = "Longueur des pétales (cm)",
y = "Largeur des pétales (cm)",
fill = "Espèce"
) +
theme_bw() +
theme(
plot.title = element_text(margin = margin(b = 20)),
axis.title.x = element_text(margin = margin(t = 15)),
axis.title.y = element_text(margin = margin(r = 15)),
axis.text.x = element_text(margin = margin(t = 6)),
axis.text.y = element_text(margin = margin(r = 6)),
plot.margin = margin(b=25, t=25, r=25, l=25)
)
p_base + p_aere
La fonction margin() permet de préciser l’espace à ajouter sur chacun des quatre côtés d’un élément :
- t pour top : au-dessus ;
- r pour right : à droite ;
- b pour bottom : en dessous ;
- l pour left : à gauche.
Par exemple :
plot.title = element_text(
margin = margin(b = 20)
)ajoute de l’espace sous le titre du graphique, afin de l’éloigner de la zone de représentation.
De la même manière :
axis.title.x = element_text(
margin = margin(t = 15)
)ajoute de l’espace au-dessus du titre de l’axe des x, et l’éloigne donc des graduations de l’axe. Enfin, plot.margin agit à un autre niveau en ajoutant une marge autour de l’ensemble du graphique.
6. Un fond pour tout rassembler
La couleur de fond peut également participer à l’apparence générale d’un graphique et faciliter son intégration dans un document.
Dans ggplot2, il est possible de modifier séparément le fond de l’ensemble du graphique et le fond de la zone dans laquelle les données sont représentées. Dans l’exemple suivant, nous partons du graphique précédent et lui appliquons deux couleurs de fond légèrement différentes :
p_base+
theme(
plot.background = element_rect(fill = "orange", colour = NA),
panel.background = element_rect(fill = "lightblue", colour = NA)
)
L’élément plot.background contrôle le fond de l’ensemble du graphique. Il s’étend notamment derrière le titre, les axes et la légende :
plot.background = element_rect(
fill = "orange",
colour = NA
)L’élément panel.background, quant à lui, contrôle uniquement le fond de la zone de représentation des données, c’est-à-dire la partie du graphique délimitée par les axes :
colour = NA indique qu’aucun contour ne doit être tracé autour du rectangle.
7. Des petits rappels visuels
Il peut être utile d’attirer l’attention du lecteur sur une information importante directement dans le graphique. Une annotation, un encadré ou un court message permet alors de mettre en évidence un résultat ou de faciliter son interprétation, sans obliger le lecteur à rechercher l’information dans le texte qui accompagne la figure.
Le package ggtext propose notamment la fonction geom_textbox(), qui permet d’ajouter une zone de texte mise en forme directement à l’intérieur d’un graphique. Dans l’exemple suivant, nous ajoutons un encadré destiné à faire ressortir le principal message du graphique :
ggplot(iris, aes(x = Petal.Width, y = Petal.Length, colour = Species)) +
geom_point() +
ggtext::geom_textbox(
x = 1.25,
y = 2,
label = "<b>À retenir</b><br>Les variables liées aux pétales distinguent fortement les espèces.",
width = unit(4.1, "cm"),
box.colour = "blue",
fill = "magenta",
colour = "#333333",
size = 3.4,
lineheight = 1.15
) +
scale_colour_manual(values = mes_couleurs) +
labs(
title = "Un encadtré dans le graphique",
x = "Largeur des pétales, en cm",
y = "Longueur des pétales, en cm",
colour = "Espèce"
) +
theme_bw()
Les arguments x et y déterminent l’emplacement de l’encadré dans le système de coordonnées du graphique :
x = 1.25,
y = 2L’argument label contient le texte à afficher. geom_textbox() accepte une mise en forme simple de type HTML. On peut ainsi utiliser … pour mettre une partie du texte en gras et
pour passer à la ligne.
Les autres arguments permettent de personnaliser l’apparence de l’encadré :
widthdéfinit sa largeur,box.colourla couleur de son contour,fillsa couleur de fond,colourla couleur du texte.sizecontrôle la taille du texte etlineheightl’espacement entre les lignes.
8. Orienter le texte dans le bon sens
Lorsque l’on utilise des facettes disposées verticalement avec facet_grid(), le nom des facettes est affiché par défaut verticalement. Cette orientation permet de gagner de la place, mais elle oblige le lecteur à tourner la tête ou à interrompre sa lecture pour identifier les différents panneaux.
Il est possible de placer ces étiquettes horizontalement afin de faciliter leur lecture. Comparons les deux présentations :
# Orientation par défaut
p_vertical <- p_base +
facet_grid(Species ~ ., switch = "y") +
labs(
title = "Orientation par défaut",
x = "Longueur des pétales (cm)",
y = "Largeur des pétales (cm)"
) +
theme_bw()
# Orientation horizontale
p_horizontal <- p_base +
facet_grid(Species ~ ., switch = "y") +
labs(
title = "Texte horizontal",
x = "Longueur des pétales (cm)",
y = "Largeur des pétales (cm)"
) +
theme_bw() +
theme(
strip.placement = "outside",
strip.text.y.left = element_text(
angle = 0,
face = "bold"
)
)
p_vertical + p_horizontal
La fonction
facet_grid(Species ~ ., switch = "y")
crée une facette par espèce, disposée verticalement. L’argument switch = “y” déplace les étiquettes des facettes du côté gauche du graphique. L’orientation du texte est ensuite contrôlée dans theme() avec :
strip.text.y.left = element_text(angle = 0)strip.text.y.leftdésigne le texte des bandeaux de facettes placés à gauche. Avec angle = 0, les noms des espèces sont affichés horizontalement plutôt que verticalement. L’argument face = "bold" permet ici de les afficher également en gras.
Enfin :
strip.placement = "outside"permet de placer les bandeaux des facettes à l’extérieur des axes, ce qui contribue à bien distinguer le nom de la facette du reste des informations du graphique.
9. Se créer un thème réutilisable
Lorsque l’on réalise régulièrement des graphiques, il peut devenir fastidieux de répéter les mêmes instructions dans theme() : taille et couleur des textes, position de la légende, marges, couleur de fond, suppression de certaines grilles, etc. Une solution consiste à créer son propre thème ggplot2 sous la forme d’une fonction. Il pourra ensuite être appliqué à n’importe quel graphique en une seule ligne de code. Dans l’exemple suivant, nous créons un thème appelé theme_delladata() :
library(tidyverse)
library(ggtext)
data(iris)
theme_delladata <- function(base_size = 12) {
theme_minimal(base_size = base_size) +
theme(
text = element_text(
family = "Times",
colour = "#005FAB"
),
plot.title = element_text(
family = "Times",
face = "bold",
size = rel(1.5),
colour = "#005FAB",
margin = margin(b = 8)
),
plot.subtitle = element_text(
family = "Times",
size = rel(1.05),
colour = "#F06449",
margin = margin(b = 15)
),
axis.title = element_text(
family = "Times",
face = "bold",
colour = "#005FAB"
),
axis.text = element_text(
family = "Times",
colour = "#333333"
),
legend.title = element_text(
family = "Times",
face = "bold",
colour = "#005FAB"
),
legend.text = element_text(
family = "Times",
colour = "#333333"
),
plot.caption = element_text(
family = "Times",
size = rel(0.85),
colour = "#666666",
hjust = 1
),
plot.background = element_rect(
fill = "#F7F9FB",
colour = NA
),
panel.background = element_rect(
fill = "white",
colour = NA
),
panel.grid.major = element_line(
colour = "#D9E3EA",
linewidth = 0.4
),
panel.grid.minor = element_blank(),
legend.position = "bottom",
plot.margin = margin(
t = 20,
r = 25,
b = 20,
l = 25
)
)
}# Graphique avec le thème de base
p1 <- p_base +
labs(
title = "Thème de base",
subtitle = "Graphique avec theme_bw()"
)
# Même graphique avec le thème personnalisé
p2 <- p_base +
labs(
title = "Thème DellaData",
subtitle = "Graphique avec theme_delladata()"
) +
theme_delladata()
# Comparaison
p1 + p2
Conclusion
Ces différents essais montrent qu’il n’est pas nécessaire de transformer complètement un graphique pour en modifier sensiblement le rendu. Quelques choix sur les couleurs, la typographie, les espacements, les annotations ou encore l’orientation des textes peuvent déjà faire une vraie différence.
La création d’un thème personnalisé constitue finalement une bonne manière de rassembler ces choix et de retrouver facilement une identité graphique cohérente d’un graphique à l’autre.
Et vous, parmi les astuces présentées dans cet article, laquelle avez-vous le plus envie de retenir ou d’utiliser dans vos prochains graphiques ?
N’hésitez pas à partager votre astuce préférée en commentaire. Et si vous avez vous-même une petite astuce ggplot2 qui améliore vos graphiques, je suis également preneuse !




Pour répondre à la question
Et vous, parmi les astuces présentées dans cet article, laquelle avez-vous le plus envie de retenir ou d’utiliser dans vos prochains graphiques ?
L’insertion d’un encadré « A retenir »