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.