Pour le second post de la série, nous examinons les diagrammes à bâtons pairés. Il s’agit ici de comparer les fréquences des différentes modalités d’une variable en mettant en perspective la situation prévalent sur deux groupes en mettant côte à côte les barres (bâtons) les représentant. Ce type de graphe peut, sans grandes difficultés, être étendu à plus de groupes . Néanmoins, il faut veiller à ce que l’ensemble reste lisible. Leur avantage est qu’ils facilitent les comparaisons en positionnant les valeurs sur une même échelle (qui dans l’idéal débute à 0). L’examen des positions des extrémités des barres donne une idée claire des proportions de différences entre les groupes. Ils ne sont par contre pas très efficaces pour mettre au jour des relations entre variables ou des tendances.
Voyons cela à partir d’un exemple concret en réalisant un diagramme à bâtons pairés avec GGPLOT. Pour ce faire, utilisons les données de l’ONU sur les populations urbaines et rurales dans le monde que vous pouvez télécharger à l’adresse en lien ici. Limitons-nous néanmoins à l’Afrique et comparons des situations prévalant sur différentes grandes zones géographiques.
Commençons par charger les packages utiles: le tidyverse et readxl.
library(tidyverse)
library(readxl)
Chargeons les données dans R (après les avoirs chargé sur votre machine) et regardons à quoi elles ressemblent.
dat <- read_excel("WUP2018-F01-Total_Urban_Rural.xls",skip = 16)
dat
## # A tibble: 273 × 8
## Index Region, subregion, country…¹ Note Count…² Urban Rural Total Perce…³
## <dbl> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 1 WORLD <NA> 900 4.22e6 3.41e6 7.63e6 55.3
## 2 2 More developed regions a 901 9.94e5 2.69e5 1.26e6 78.7
## 3 3 Less developed regions b 902 3.23e6 3.14e6 6.37e6 50.6
## 4 4 Least developed countries c 941 3.44e5 6.82e5 1.03e6 33.6
## 5 5 Less developed regions, exc… d 934 2.88e6 2.46e6 5.34e6 53.9
## 6 6 Less developed regions, exc… <NA> 948 2.36e6 2.56e6 4.92e6 48.0
## 7 7 High-income countries e 1503 9.75e5 2.22e5 1.20e6 81.5
## 8 8 Middle-income countries e 1517 3.02e6 2.72e6 5.74e6 52.6
## 9 9 Upper-middle-income countri… e 1502 1.76e6 8.81e5 2.64e6 66.6
## 10 10 Lower-middle-income countri… e 1501 1.26e6 1.84e6 3.10e6 40.6
## # … with 263 more rows, and abbreviated variable names
## # ¹`Region, subregion, country or area`, ²`Country\ncode`,
## # ³`Percentage urban`
Il y a bien plus de données que nécessaires. Limitons donc le contenu à ce que l’on veut traiter.
dat<-dat %>%
select(`Region, subregion, country or area`,Urban,Rural) %>%
rename(Reg=`Region, subregion, country or area`) %>%
filter(Reg%in%c('Eastern Africa','Middle Africa','Northern Africa',
'Southern Africa','Western Africa'))
dat
## # A tibble: 5 × 3
## Reg Urban Rural
## <chr> <dbl> <dbl>
## 1 Eastern Africa 121316. 312328.
## 2 Middle Africa 83484. 85055.
## 3 Northern Africa 123644. 114141.
## 4 Southern Africa 41970. 24004.
## 5 Western Africa 177189. 204792.
On note que les données ne se présentent pas dans une configuration directement utilisable. Nous aimerions avoir une variable zone (Reg), une variable pour la population (value) et une variable indiquant si l’observation est faite sur une zone rurale ou urbaine (type). Pour aboutir à ce résultat, utilisons la fonction pivot_longer(). Indiquons que les colonnes à la base de le transformation sont Urban et Rural et que le nom de la nouvelle variable générée est type.
dat<-dat %>% pivot_longer(cols=c(Urban,Rural),names_to='type')
dat
## # A tibble: 10 × 3
## Reg type value
## <chr> <chr> <dbl>
## 1 Eastern Africa Urban 121316.
## 2 Eastern Africa Rural 312328.
## 3 Middle Africa Urban 83484.
## 4 Middle Africa Rural 85055.
## 5 Northern Africa Urban 123644.
## 6 Northern Africa Rural 114141.
## 7 Southern Africa Urban 41970.
## 8 Southern Africa Rural 24004.
## 9 Western Africa Urban 177189.
## 10 Western Africa Rural 204792.
Maintenant que notre base est au bon format traduisons les différentes valeurs textuelles qui la compose en français. Cela permettra d’harmoniser la langue sur le graphe final.
dat<-dat %>% mutate(type=ifelse(type=="Rural","Rurale","Urbaine"),
Reg=ifelse(Reg=="Eastern Africa","Afrique de l'est",
ifelse(Reg=="Western Africa","Afrique de l'ouest",
ifelse(Reg=="Northern Africa","Afrique du nord",
ifelse(Reg=="Middle Africa","Afrique centrale",
ifelse(Reg=="Southern Africa","Afrique du sud",""))))))
dat
## # A tibble: 10 × 3
## Reg type value
## <chr> <chr> <dbl>
## 1 Afrique de l'est Urbaine 121316.
## 2 Afrique de l'est Rurale 312328.
## 3 Afrique centrale Urbaine 83484.
## 4 Afrique centrale Rurale 85055.
## 5 Afrique du nord Urbaine 123644.
## 6 Afrique du nord Rurale 114141.
## 7 Afrique du sud Urbaine 41970.
## 8 Afrique du sud Rurale 24004.
## 9 Afrique de l'ouest Urbaine 177189.
## 10 Afrique de l'ouest Rurale 204792.
Les données sont prêtes pour alimenter notre représentation graphique. Mais, avant de tracer un diagramme pairé, commençons par juxtaposer les diagrammes à bâtons des effectifs des zones rurale et urbaine pour nos aires géographiques. Pour cela, utilisons l’option stat du geom_bar() et indiquons “identity” de manière à mobiliser la valeur y indiqué comme esthétique pour les effectifs à représenter. Utilisons également facet_wrap() de manière à obtenir les deux graphes simultanément (arrangeons également les étiquettes de l’axe des abscisses pour qu’elles apparaissent entières).
ggplot(dat,aes(x=Reg,y=value))+
geom_bar(stat = "identity")+
facet_wrap(.~type)+
theme(axis.text.x = element_text(angle=90))
Cette représentation pourrait être améliorée pour aboutir à quelque chose de bien plus parlant. Mais, ce n’est pas l’objectif ici. Voyons ce que donnerait un graphe pairé. Pour ce faire, utilisons l’option position du geom_bar() en indiquant “dodge”. Ajoutons comme esthétique le type comme base de différenciation des couleurs de remplissages des barres.
ggplot(dat,aes(x=Reg,y=value,fill=type))+
geom_bar(stat = "identity",position = "dodge")
Le résultat est intéressant. Essayons de l’améliorer. Revoyons les titres des axes, renversons les coordonnées pour avoir des barres horizontales et optons pour un thème plus neutre.
ggplot(dat,aes(x=Reg,y=value,fill=type))+
geom_bar(stat = "identity",position = "dodge")+
labs(x='Régions',y='Population (en milliers)')+
coord_flip()+
theme_minimal()
Ajoutons un titre et un caption pour indiquer l’origine des données. Changeons les couleurs des barres (avec un jaune et un bleu sympathiques trouver en fouillant sur https://htmlcolorcodes.com/fr/) et réduisons la traille des barres pour bien délimiter l’espace entre elles.
ggplot(dat,aes(x=Reg,y=value,fill=type))+
geom_bar(stat = "identity",position = "dodge",colour='white',size=2)+
labs(title="Population urbaine c. rurale dans les régions d'Afrique en 2018",
caption="Source: United Nations, Department of Economic and Social Affairs, World Urbanization Prospects",
x='Régions',y='Population (en milliers)')+
scale_fill_manual(values=c('#F1D739','#399CF1'))+
coord_flip()+
theme_minimal()
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
L’axe reprenant valeur de population est peu lisible arrangeons cela en utilisant la fonction unit_format() du package scale. Affichons le nombre de milliers avec un chiffre après l’unité suivie de la lettre M.
ggplot(dat,aes(x=Reg,y=value,fill=type))+
geom_bar(stat = "identity",position = "dodge",colour='white',size=2)+
labs(title="Population urbaine c. rurale dans les régions d'Afrique en 2018",
caption="Source: United Nations, Department of Economic and Social Affairs, World Urbanization Prospects",
x='Régions',y='Population (en milliers)')+
scale_fill_manual(values=c('#F1D739','#399CF1'))+
scale_y_continuous(labels = scales::unit_format(
unit = "M", scale = 1e-3, accuracy = 0.1))+
coord_flip()+
theme_minimal()
C’est mieux. On pourrait presque s’arrêter là. Mais, continuons à améliorer l’aspect du graphe. Remontons le titre de l’axe des Régions tout en haut et orientons le pour qu’il soit plus lisible avec un léger retrait par rapport aux étiquettes de l’axe.
ggplot(dat,aes(x=Reg,y=value,fill=type))+
geom_bar(stat = "identity",position = "dodge",colour='white',size=2)+
labs(title="Population urbaine c. rurale dans les régions d'Afrique en 2018",
caption="Source: United Nations, Department of Economic and Social Affairs, World Urbanization Prospects",
x='Région',y='Population (en milliers)')+
scale_fill_manual(values=c('#F1D739','#399CF1'))+
scale_y_continuous(labels = scales::unit_format(
unit = "M", scale = 1e-3, accuracy = 0.1))+
coord_flip()+
theme_minimal()+
theme(axis.title.y=element_text(hjust=1, angle=0,margin = margin(r=-35)))
Alignons les étiquettes de l’axe Régions sur la gauche et supprimons l’extension de la fenêtre du graphe mise en oeuvre par défaut dans le jeu de coordonnées. Profitons-en pour centrer le titre, réduire la taille du caption, le passer en italic et l’aligner sur la gauche.
ggplot(dat,aes(x=Reg,y=value,fill=type))+
geom_bar(stat = "identity",position = "dodge",colour='white',size=2)+
labs(title="Population urbaine c. rurale dans les régions d'Afrique en 2018",
caption="Source: United Nations, Department of Economic and Social Affairs, World Urbanization Prospects",
x='Région',y='Population (en milliers)')+
scale_fill_manual(values=c('#F1D739','#399CF1'))+
scale_y_continuous(labels = scales::unit_format(
unit = "M", scale = 1e-3, accuracy = 0.1))+
coord_flip(expand=FALSE)+
theme_minimal()+
theme(plot.title = element_text(hjust = 0.5) ,
plot.caption = element_text(hjust = 1, face='italic',size = 6),
axis.title.y=element_text(hjust=1, angle=0,margin = margin(r=-35)),
axis.text.y = element_text(hjust=0))
Supprimons la légende et inscrivons à la place dans chaque barre s’il s’agit de mesures pour les zones rurales ou urbaines. Pour cela, utilisons le geom_text(). L’option position avec la commande position_dodge(), nous permet de situer le texte dans la barre (mettons-le en blanc). Notez que j’ai également changer la taille du graphe de sortie pour rendre l’ensemble plus lisible sur la page du site. Je suis passé à 5 inch (pouces) de hauteur et 10 de largeur.
ggplot(dat,aes(x=Reg,y=value,fill=type))+
geom_bar(stat = "identity",position = "dodge",colour='white',size=2)+
geom_text(aes(label = type), hjust = 1.5,
position = position_dodge(.9),size=3,
color='white')+
labs(title="Population urbaine c. rurale dans les régions d'Afrique en 2018",
caption="Source: United Nations, Department of Economic and Social Affairs, World Urbanization Prospects",
x='Région',y='Population (en milliers)')+
scale_fill_manual(values=c('#F1D739','#399CF1'))+
scale_y_continuous(labels = scales::unit_format(
unit = "M", scale = 1e-3, accuracy = 0.1))+
coord_flip(expand=FALSE)+
theme_minimal()+
theme(plot.title = element_text(hjust = 0.5) ,
plot.caption = element_text(hjust = 1, face='italic',size = 6),
axis.title.y=element_text(hjust=1, angle=0,margin = margin(r=-35)),
axis.text.y = element_text(hjust=0),
legend.position = "none")
Supprimons la grille à l’arrière du graphe et ajoutons les valeurs (arrondies) de chaque groupe au bout des barres (encore une fois avec le geom_text).
ggplot(dat,aes(x=Reg,y=value,fill=type))+
geom_bar(stat = "identity",position = "dodge",colour='white',size=2)+
geom_text(aes(label = type), hjust = 1.5,
position = position_dodge(.9),size=3,
color='white')+
geom_text(aes(label = round(value)), hjust = -0.1,
position = position_dodge(.9),size=3)+
labs(title="Population urbaine c. rurale dans les régions d'Afrique en 2018",
caption="Source: United Nations, Department of Economic and Social Affairs, World Urbanization Prospects",
x='Région',y='Population (en milliers)')+
scale_fill_manual(values=c('#F1D739','#399CF1'))+
scale_y_continuous(labels = scales::unit_format(
unit = "M", scale = 1e-3, accuracy = 0.1))+
coord_flip(expand=FALSE)+
theme_minimal()+
theme(plot.title = element_text(hjust = 0.5) ,
plot.caption = element_text(hjust = 1, face='italic',size = 6),
axis.title.y=element_text(hjust=1, angle=0,margin = margin(r=-35)),
axis.text.y = element_text(hjust=0),
panel.grid = element_blank(),
legend.position = "none")
La valeur pour l’Afrique de l’est rurale ne s’affiche pas. Elle est en dehors de la fenêtre du graphe. Pour y remédier, il suffit d’agrandir celle-ci dans le système de coordonnées grâce à l’option ylim (puisque nous avons inversé les axes).
ggplot(dat,aes(x=Reg,y=value,fill=type))+
geom_bar(stat = "identity",position = "dodge",colour='white',size=2)+
geom_text(aes(label = type), hjust = 1.5,
position = position_dodge(.9),size=3,
color='white')+
geom_text(aes(label = round(value)), hjust = -0.1,
position = position_dodge(.9),size=3)+
labs(title="Population urbaine c. rurale dans les régions d'Afrique en 2018",
caption="Source: United Nations, Department of Economic and Social Affairs, World Urbanization Prospects",
x='Région',y='Population (en milliers)')+
scale_fill_manual(values=c('#F1D739','#399CF1'))+
scale_y_continuous(labels = scales::unit_format(
unit = "M", scale = 1e-3, accuracy = 0.1))+
coord_flip(ylim=c(0,370000),expand=FALSE)+
theme_minimal()+
theme(plot.title = element_text(hjust = 0.5) ,
plot.caption = element_text(hjust = 1, face='italic',size = 6),
axis.title.y=element_text(hjust=1, angle=0,margin = margin(r=-35)),
axis.text.y = element_text(hjust=0),
panel.grid = element_blank(),
legend.position = "none")
Voilà qui règle le problème. Le graphe est quasi fini. Je pense. On peux encore l’améliorer en présentant en premier les régions avec les plus grands effectifs. Pour cela, on transforme la variable Reg en facteur que l’on recode avec reorder() en fonction de value.
ggplot(dat,aes(x=reorder(factor(Reg),value),y=value,fill=type))+
geom_bar(stat = "identity",position = "dodge",colour='white',size=2)+
geom_text(aes(label = type), hjust = 1.5,
position = position_dodge(.9),size=3,
color='white')+
geom_text(aes(label = round(value)), hjust = -0.1,
position = position_dodge(.9),size=3)+
labs(title="Population urbaine c. rurale dans les régions d'Afrique en 2018",
caption="Source: United Nations, Department of Economic and Social Affairs, World Urbanization Prospects",
x='Région',y='Population (en milliers)')+
scale_fill_manual(values=c('#F1D739','#399CF1'))+
scale_y_continuous(labels = scales::unit_format(
unit = "M", scale = 1e-3, accuracy = 0.1))+
coord_flip(ylim=c(0,370000),expand=FALSE)+
theme_minimal()+
theme(plot.title = element_text(hjust = 0.5) ,
plot.caption = element_text(hjust = 1, face='italic',size = 6),
axis.title.y=element_text(hjust=1, angle=0,margin = margin(r=-35)),
axis.text.y = element_text(hjust=0),
panel.grid = element_blank(),
legend.position = "none")
Et voilà le tour est joué. On a un diagramme à bâtons pairés à la fois parlant et esthétique.