L’histogramme peut être un excellent moyen de visualiser la distribution globale d’une variable numérique. Le principe de cette visualisation est assez simple puisqu’elle consiste à regrouper les observations par intervalles de valeurs (bin en anglais), puis à représenter le nombre d’observations dans chaque intervalle par des barres verticales.
L’apparence de l’histogramme dépend alors de la largeur des intervalles choisis. Plus les intervalles sont larges, moins il y a de barres, mais plus elles sont hautes. À l’inverse, plus les intervalles sont étroits, plus il y a de barres, mais moins elles sont hautes.
Bien que la création d’un histogramme soit simple en théorie, en pratique, elle me pose souvent des difficultés :
Pour éviter de perdre du temps dans ces manipulations, je me suis fait un petit aide-mémoire, que je partage avec vous aujourd’hui.
Nous allons employer le package ggplot2
pour créer des histogrammes. Si vous ne l’avez pas encore installé, vous pouvez le faire en utilisant la commande suivante :
install.packages("ggplot2")
library(ggplot2)
Pour ce tutoriel, nous utiliserons la variable Sepal.Length
du jeu de données iris
intégré à R. Il y a 150 valeurs, qui s’étendent de 4.3 à 7.9 cm.
summary(iris$Sepal.Length)
Min. 1st Qu. Median Mean 3rd Qu. Max.
4.300 5.100 5.800 5.843 6.400 7.900
Pour créer un histogramme avec ggplot2
, nous employons la géométrie geom_histogram()
.
L’argument fill
permet de spécifier la couleur de remplissage des barres, tandis que l’argument color
permet de spécifier la couleur des contours des barres. En utilisant une couleur noire, cela permet de mieux faire ressortir les barres.
Voici un exemple d’histogramme de la longueur des sépales (Sepal.Length
) de l’iris :
ggplot(iris, aes(x = Sepal.Length)) +
geom_histogram(fill="orange", color="black") +
ggtitle("Histogramme de la Longueur des Sépales")+
theme_minimal()
Par défaut, le nombre d’intervalles est de 30. Vous pouvez modifier ce nombre en utilisant l’argument bins
dans geom_histogram()
.
Pour modifier le nombre de barres et donc le nombre d’intervalles, nous devons spécifier le nombre souhaité avec l’argument bins
dans geom_histogram()
; 7 par exemple ici :
ggplot(iris, aes(x = Sepal.Length)) +
geom_histogram(bins=7,fill="orange", color="black") +
ggtitle("Utilisation de 7 intervalles")+
theme_minimal()
Les valeurs des intervalles ne sont pas faciles à identifier, mais nous pouvons les connaitre en employant la fonction ggplot_build()
pour obtenir les valeurs des intervalles utilisées pour l’histogramme.
g1 <-ggplot(iris, aes(x = Sepal.Length)) +
geom_histogram(bins=7,fill="orange", color="black") +
ggtitle("Utilisation de 7 intervalles")+
theme_minimal()
ggplot_build(g1)$data[[1]]
y count x xmin xmax density ncount ndensity flipped_aes PANEL group
1 5 5 4.2 3.9 4.5 0.05555556 0.1388889 0.1388889 FALSE 1 -1
2 36 36 4.8 4.5 5.1 0.40000000 1.0000000 1.0000000 FALSE 1 -1
3 32 32 5.4 5.1 5.7 0.35555556 0.8888889 0.8888889 FALSE 1 -1
4 35 35 6.0 5.7 6.3 0.38888889 0.9722222 0.9722222 FALSE 1 -1
5 29 29 6.6 6.3 6.9 0.32222222 0.8055556 0.8055556 FALSE 1 -1
6 7 7 7.2 6.9 7.5 0.07777778 0.1944444 0.1944444 FALSE 1 -1
7 6 6 7.8 7.5 8.1 0.06666667 0.1666667 0.1666667 FALSE 1 -1
ymin ymax colour fill linewidth linetype alpha
1 0 5 black orange 0.5 1 NA
2 0 36 black orange 0.5 1 NA
3 0 32 black orange 0.5 1 NA
4 0 35 black orange 0.5 1 NA
5 0 29 black orange 0.5 1 NA
6 0 7 black orange 0.5 1 NA
7 0 6 black orange 0.5 1 NA
Les colonnes xmin
et xmax
nous renseignent sur les valeurs des bornes, et la variable count
nous renseigne sur le nombre d’observations. Les intervalles créés par la fonction geom_histogram()
sont fermés à droite. Ici les intervalles sont (3.9,4.5],(4.5,5.1], (5.1,5.7], (5.7,6.3], (6.3,6.9], (6.9,7.5] et (7.5,8.1].
Cet histogramme ne me plait pas beaucoup parce que les valeurs des intervalles n’ont pas de signification et il donne l’impression que la valeur minimale est inférieure à 4, et la valeur maximale supérieure à 8 alors que les valeurs min et max sont 4,3 et 7.9.
Pour modifier le nombre de barres, nous pouvons également préciser la largeur désirée des intervalles, en employant l’argument binwidth
dans geom_histogram()
. Dans l’exemple ci-dessous, les barres sont de largeur 1cm :
ggplot(iris, aes(x = Sepal.Length)) +
geom_histogram(binwidth=1,fill="orange", color="black") +
ggtitle("Utilisation d'intervalles de largeur 1 cm")+
theme_minimal()
Les arguments bins
et binwidth
sont mutuellement exclusifs. Vous ne pouvez pas les utiliser ensemble.
Ici les intervalles sont de (3.5,4.5], (4.5,5.5], (5.5,6.5], (6.5,7.5] et (7.5,8.5]. En étant centrés sur des valeurs entières, les intervalles me semblent avoir plus de sens, mais les valeurs min et max sont toujours trompeuses.
Si vous souhaitez centrer les intervalles sur d’autres valeurs, vous pouvez utiliser l’argument center
dans geom_histogram()
. Par exemple, pour centrer les intervalles sur 4.5, 5.5, 6.5 etc, , il suffit d’indiquer une des valeurs ; par exemple 5.5
ggplot(iris, aes(x = Sepal.Length)) +
geom_histogram(binwidth=1, center = 5.5, fill="orange", color="black") +
ggtitle("Utilisation d'intervalles de largeur 1 cm \n et en spécifiant le centre des intervalles")+
theme_minimal()
L’argument boundary
permet également de modifier les intervalles, mais en spécifiant, cette fois, la valeur des bords par rapport à l’axe x. Par exemple, boundary=0.3
permet d’obtenir des intervalles de largeur 1 cm commençant à 4.3, 5.3, 6.3 etc.
ggplot(iris, aes(x = Sepal.Length)) +
geom_histogram( fill="orange", color="black", binwidth=1, boundary=0.3) +
ggtitle("Utilisation d'intervalles de largeur 1 cm \n et en spécifiant le bord des intervalles") +
scale_x_continuous(breaks = seq(4.3, 8.3, by = 1))+
theme_minimal()
En spécifiant boundary = 0
, les intervalles commenceront exactement aux entiers multiples de l’intervalle..
Grâce à l’argument breaks
de la fonction geom_histogram()
, il est possible de créer des intervalles personnalisés. Par exemple, un premier intervalle entre la valeur minimale (4,3) et 5, puis des intervalles de largeur 1 cm, et enfin un intervalle entre 7 et la valeur maximale (7,9). Les étiquettes de ces valeurs peuvent être affichées grâce à la couche scale_x_continuous(breaks = breaks)
.
breaks <- c(4.3, 5:7,7.9)
breaks
[1] 4.3 5.0 6.0 7.0 7.9
ggplot(iris, aes(x = Sepal.Length)) +
geom_histogram( fill="orange", color="black", breaks=breaks) +
ggtitle("Histogramme avec Intervalles Personnalisés")+
scale_x_continuous(breaks = breaks)+
theme_minimal()
Le premier intervalle n’a pas la même largeur que les autres et cela est visible sur le graphique (le dernier aussi, mais à peine et cela n’est pas visible).
Pour que la largeur des barres soit identique, nous pouvons créer les intervalles en utilisant la fonction cut()
et en spécifiant right = TRUE
(pour avoir des intervalles fermés à droite) et include.lowest = TRUE
pour inclure les valeurs limites dans les intervalles.
breaks <- c(4.3, 5:7,7.9)
iris$Sepal.Length.Bins <- cut(iris$Sepal.Length, breaks = breaks, include.lowest = TRUE, right = TRUE)
iris$Sepal.Length.Bins
[1] (5,6] [4.3,5] [4.3,5] [4.3,5] [4.3,5] (5,6] [4.3,5] [4.3,5] [4.3,5]
[10] [4.3,5] (5,6] [4.3,5] [4.3,5] [4.3,5] (5,6] (5,6] (5,6] (5,6]
[19] (5,6] (5,6] (5,6] (5,6] [4.3,5] (5,6] [4.3,5] [4.3,5] [4.3,5]
[28] (5,6] (5,6] [4.3,5] [4.3,5] (5,6] (5,6] (5,6] [4.3,5] [4.3,5]
[37] (5,6] [4.3,5] [4.3,5] (5,6] [4.3,5] [4.3,5] [4.3,5] [4.3,5] (5,6]
[46] [4.3,5] (5,6] [4.3,5] (5,6] [4.3,5] (6,7] (6,7] (6,7] (5,6]
[55] (6,7] (5,6] (6,7] [4.3,5] (6,7] (5,6] [4.3,5] (5,6] (5,6]
[64] (6,7] (5,6] (6,7] (5,6] (5,6] (6,7] (5,6] (5,6] (6,7]
[73] (6,7] (6,7] (6,7] (6,7] (6,7] (6,7] (5,6] (5,6] (5,6]
[82] (5,6] (5,6] (5,6] (5,6] (5,6] (6,7] (6,7] (5,6] (5,6]
[91] (5,6] (6,7] (5,6] [4.3,5] (5,6] (5,6] (5,6] (6,7] (5,6]
[100] (5,6] (6,7] (5,6] (7,7.9] (6,7] (6,7] (7,7.9] [4.3,5] (7,7.9]
[109] (6,7] (7,7.9] (6,7] (6,7] (6,7] (5,6] (5,6] (6,7] (6,7]
[118] (7,7.9] (7,7.9] (5,6] (6,7] (5,6] (7,7.9] (6,7] (6,7] (7,7.9]
[127] (6,7] (6,7] (6,7] (7,7.9] (7,7.9] (7,7.9] (6,7] (6,7] (6,7]
[136] (7,7.9] (6,7] (6,7] (5,6] (6,7] (6,7] (6,7] (5,6] (6,7]
[145] (6,7] (6,7] (6,7] (6,7] (6,7] (5,6]
Levels: [4.3,5] (5,6] (6,7] (7,7.9]
Les intervalles créés sont ensuite employés dans la fonction aes()
de la fonction ggplot()
; il est également nécessaire d’employer l’argument stat = "count"
dans geom_histogram()
.
ggplot(iris, aes(x = Sepal.Length.Bins)) +
geom_histogram(stat = "count", fill="orange", colour="black") +
ggtitle("Histogramme avec Intervalles Personnalisés\n et largeur de barre identique")+
theme_minimal()
La fonction stat_bin()
permet de calculer les pourcentages, et l’argument geom = "text"
permet de les afficher en texte. L’argument vjust = -0.5
permet de positionner les pourcentages légèrement au-dessus des barres.
ggplot(iris, aes(x = Sepal.Length)) +
geom_histogram(binwidth = 1, fill = "orange", color = "black") +
ggtitle("Utilisation d'intervalles de largeur 1 cm") +
stat_bin(binwidth = 1, aes(label = scales::percent(..count../sum(..count..))),
geom = "text", vjust = -0.5) +
theme_minimal()
Pour vérifier :
library(dplyr)
iris %>%
mutate(interval = cut(Sepal.Length, breaks = seq(3.5, 8.5, by = 1))) %>%
group_by(interval) %>%
summarise(n = n()) %>%
mutate(percentage = n / sum(n))
# A tibble: 5 × 3
interval n percentage
<fct> <int> <dbl>
1 (3.5,4.5] 5 0.0333
2 (4.5,5.5] 54 0.36
3 (5.5,6.5] 61 0.407
4 (6.5,7.5] 24 0.16
5 (7.5,8.5] 6 0.04
Les pourcentages affichés sont bien les bons !
Pour les intervalles personnalisés réalisés avec l’argument breaks
, il faut aussi spécifier les breaks dans la fonction stat_bin()
:
breaks <- c(4.3, 5:7,7.9)
ggplot(iris, aes(x = Sepal.Length)) +
geom_histogram( fill="orange", color="black", breaks=breaks) +
ggtitle("Histogramme avec Intervalles Personnalisés")+
scale_x_continuous(breaks = breaks)+
stat_bin(breaks=breaks, aes(label = scales::percent(..count../sum(..count..))),
geom = "text", vjust = -0.5) +
theme_minimal()
Pour vérifier :
iris %>%
group_by(Sepal.Length.Bins) %>%
summarise(n = n()) %>%
mutate(percentage = n / sum(n))
# A tibble: 4 × 3
Sepal.Length.Bins n percentage
<fct> <int> <dbl>
1 [4.3,5] 32 0.213
2 (5,6] 57 0.38
3 (6,7] 49 0.327
4 (7,7.9] 12 0.08
Là encore, les pourcentages affichés sont bien les bons !
Et si nous avons réalisé les intervalles avec la fonction cut()
, et l’histogramme réalisé avec l’option stats=“count”
, nous pouvons utiliser la fonction geom_text()
en utilisant également l’argument stat = "count"
pour afficher les pourcentages de données dans chaque intervalle.
ggplot(iris, aes(x = Sepal.Length.Bins)) +
geom_histogram(stat = "count", fill = "orange", color = "black") +
geom_text(stat = "count", aes(label = scales::percent(..count../sum(..count..))),
vjust = -0.5) +
ggtitle("Histogramme avec Intervalles Personnalisés") +
theme_minimal()
Vous avez maintenant toutes les clés en main pour créer des histogrammes efficaces et pertinents avec R. Que ce soit pour ajuster le nombre d’intervalles, les centrer, ou ajouter des pourcentages, vous êtes en mesure de manipuler tous les paramètres pour obtenir la visualisation la plus adaptée à vos données. Si ce tutoriel vous a été utile, n’hésitez pas à laisser un commentaire ci-dessous avec vos impressions ou questions, et partagez vos expériences avec les histogrammes en R !
Retrouver le planning et les programmes de mes formations ici 👇👇👇
Retrouver mes propositions de services ici 👇👇👇
C’est possible en faisant un don sur la page Tipeee du blog
Enregistrez vous pour recevoir gratuitement mes fiches “aide mémoire” (ou cheat sheets) qui vous permettront de réaliser facilement les principales analyses biostatistiques avec le logiciel R et pour être informés des mises à jour du site.
Une réponse
Bonjour,
J’apprécie beaucoup votre blog que j’utilise dans mon cours de statistiques sur R. Mais là je dois réagir.
Désolé, mais les histogrammes proposés sont faux lorsque les amplitudes sont inégales. C’est la surface des bâtons qui doit être proportionnelle à l’effectif et non pas la hauteur des barres. Lorsque les classes sont inégales il faut utiliser comme hauteur de bâton la densité de probabilité (effectif / amplitude).
Pour ma part j’utilise la bonne vieille fonction R-base hist() qui ne commet jamais d’erreur et bascule automatiquement vers la densité de probabilité lorsque les amplitudes sont inégales….
Bien cordialement,
Claude Grasland