Chapitre 6 Transformer de données avec dplyr

6.1 Introduction

6.1.1 Objectif de ce chapitre

Le data scientist a très rarement les données structurées dans la forme qui lui convient. Il lui revient de les mettres dans cette forme. De ce fait, il lui est indispensable de savoir manipuler les données. Il s’agit de la maîtrise d’une série de tâches parmi lesquelles nous pouvons citer:

  • la simple sélection d’un sous-ensemble à l’intérieur d’un large groupe ;

  • la sélection d’un nombre déterminé de variables (attributs) ;

  • la combinaison d’informations conservées dans différentes data frame;

  • la suppresion et la création variables;

  • la réorganisation des données à l’intérieur d’un data frame.

Dans ce chapitre, nous allons voir quelques techniques de manipulation de données avec le package dplyr.

6.1.2 Que nous faut-il?

  • R (évidemment) et RStudio (de préférence) installés sur le poste de travail;

  • le package dplyr installés;

  • les fichiers fournis dans le cadre du module.

6.1.3 Données

Nous allons illustrer ce chapitre avec une compilation de données tirées des Recensements Généraux de la Population et de l’Habitat au Mali, menés respectivement en 1976, 1987, 1998 et 2009. Il s’agit:

  • d’un côté, de tableaux sur la population par groupe d’âge (tranche de 5 ans);

  • de l’autre, de tableaux sur la population par commune.

6.2 Aperçu de dplyr

6.2.1 Installer dplyr

Le package dplyr est un package crééé par Hadley Wickham. Il fait partie de l’écosystème tidyverse qui est un ensemble de packages conçus pour la data science et partageant tous les mêmes philoshophie, grammaire et structure. Nous allons, avec l’exploration des packages du tidyverse, comprendre l’importance de cette grammaire. Elle traduit la volonté des auteurs de condenser dans le nom des fonctions l’idée de la tâche que celles-ci exécutent. Dans dplyr, les fonctions majeures sont des verbes (comme nous allons le voir).

Alors, qu’est-ce que dplyr fait? Voici une simple analogie. Si les données constituent un tissu, nous pouvons voir dplyr comme à la fois la paire de ciseaux pour en faire la coupe, et l’aiguille et le fil pour le coudre. Pour le prouver, voici le logo associé au package.

Pour travailler avec dplyr, l’on commence par l’installer sur son poste de travail. Etant intégré au tidyverse, il est possible de l’installer en même temps que les autres composantes de celui-ci.

install.packages("tidyverse")

L’on peut aussi l’installer tout seul.

install.packages("dplyr")

Cette commande télécharge depuis le réseau d’archivage des packages R la dernière version stable publiée. Toutefois, il est aussi possible d’acquérir les versions en développement depuis Github.

install.packages("devtools") # au cas où ce package n'est pas installé
devtools::install_github("tidyverse/dplyr")

Une fois l’installation effectuée, l’on peut charger le package.

library(dplyr)

6.2.2 L’objet tibble

Avant d’aller loin, il est utile d’introduire la notion de tibble qui est une partie intégrante des packages du tidyverse. Il s’agit de la même chose que le data frame, mais celui-ci repensé. Le tibble n’altère pas la structure ni la classe des données contenue dans un data frame. Par contre, il agit sur l’affichage des données et, comme nous le verrons plus tard, leur permet de stocker de nouvelles sortes de données (colonne-list, à noter quelque part…on y reviendra). Pour l’instant regardons-le à l’oeuvre en termes d’affichage.

Prenons les données sur les populations des communes du Mali en 2009 (RGPH, 2009). Nous allons charger les données depuis la source suivante:

source_donnees <- "https://raw.githubusercontent.com/fousseynoubah/dswr_slides/master/5_Manipuler_Donnees_dans_R/data/adm3_pop_2009.csv"
# Importation des données
adm3_pop_2009 <- read.csv(source_donnees)

Quelle est la classe de cet objet?

class(adm3_pop_2009)
## [1] "data.frame"

C’est un data frame! Regardons sa structure ainsi que les six premières observations

str(adm3_pop_2009)
## 'data.frame':    703 obs. of  9 variables:
##  $ id        : int  1 2 3 4 5 6 7 8 9 10 ...
##  $ admin0_nom: Factor w/ 1 level "Mali": 1 1 1 1 1 1 1 1 1 1 ...
##  $ admin1_nom: Factor w/ 9 levels "Bamako","Gao",..: 3 3 3 3 3 3 3 3 3 3 ...
##  $ admin2_nom: Factor w/ 50 levels "Abeibara","Ansongo",..: 23 23 23 23 23 23 23 23 23 23 ...
##  $ admin3_nom: Factor w/ 687 levels "Abeibara","Adarmalane",..: 25 74 116 156 192 210 231 238 249 257 ...
##  $ annee     : int  2009 2009 2009 2009 2009 2009 2009 2009 2009 2009 ...
##  $ homme     : num  6123 6144 7115 11466 5141 ...
##  $ femme     : int  5974 6353 7015 12091 5017 1934 3927 1903 10234 3445 ...
##  $ source    : Factor w/ 1 level "RGPH": 1 1 1 1 1 1 1 1 1 1 ...
head(adm3_pop_2009)
##   id admin0_nom admin1_nom admin2_nom admin3_nom annee homme femme source
## 1  1       Mali      Kayes      Kayes   Bangassi  2009  6123  5974   RGPH
## 2  2       Mali      Kayes      Kayes  Colimbine  2009  6144  6353   RGPH
## 3  3       Mali      Kayes      Kayes     Diamou  2009  7115  7015   RGPH
## 4  4       Mali      Kayes      Kayes   Djelebou  2009 11466 12091   RGPH
## 5  5       Mali      Kayes      Kayes     Faleme  2009  5141  5017   RGPH
## 6  6       Mali      Kayes      Kayes      Fegui  2009  1999  1934   RGPH

Maintenant, déclarons cet objet comme un tibble.

adm3_pop_2009 <- as_tibble(adm3_pop_2009)

Revoyons la classe.

class(adm3_pop_2009)
## [1] "tbl_df"     "tbl"        "data.frame"

La classe a changé, ou plutôt elle s’est consolidée. De nouvelles caractéristiques ont été ajoutées à data.frame. Maintenant, imprimons le jeu de données lui-même.

adm3_pop_2009
## # A tibble: 703 x 9
##       id admin0_nom admin1_nom admin2_nom admin3_nom annee homme femme
##    <int> <fct>      <fct>      <fct>      <fct>      <int> <dbl> <int>
##  1     1 Mali       Kayes      Kayes      Bangassi    2009  6123  5974
##  2     2 Mali       Kayes      Kayes      Colimbine   2009  6144  6353
##  3     3 Mali       Kayes      Kayes      Diamou      2009  7115  7015
##  4     4 Mali       Kayes      Kayes      Djelebou    2009 11466 12091
##  5     5 Mali       Kayes      Kayes      Faleme      2009  5141  5017
##  6     6 Mali       Kayes      Kayes      Fegui       2009  1999  1934
##  7     7 Mali       Kayes      Kayes      Gory Gope~  2009  3939  3927
##  8     8 Mali       Kayes      Kayes      Goumera     2009  1918  1903
##  9     9 Mali       Kayes      Kayes      Guidimaka~  2009  9798 10234
## 10    10 Mali       Kayes      Kayes      Hawa Demb~  2009  3406  3445
## # ... with 693 more rows, and 1 more variable: source <fct>

Avec les tibble, l’affichage d’un jeu de données donne par défaut les dix premières observations et indique la classe et/ou le type des colonnes. Nous voyons par exemple que la variable id est composée d’entiers tandis que la variable admin0_nom est déclarée en facteur. De ce fait, l’impression d’un tibble permet de combiner les résultats qu’on obtiendrait avec les commandes str et head.

Le tibble est l’output par défaut des fonctions du tidyverse. Reprenons l’opération d’importation. Cette fois-ci, au lieu de passer par read.csv qui est une fonction basique, nous utiliserons read_csv du package readr, lui-même membre du club tidyverse.

# Chargement du package "readr"
library(readr)

# Importation des données
adm3_pop_2009 <- read_csv(source_donnees)

# Classe
class(adm3_pop_2009)
## [1] "spec_tbl_df" "tbl_df"      "tbl"         "data.frame"
# Impression
adm3_pop_2009
## # A tibble: 703 x 9
##       id admin0_nom admin1_nom admin2_nom admin3_nom annee homme femme
##    <dbl> <chr>      <chr>      <chr>      <chr>      <dbl> <dbl> <dbl>
##  1     1 Mali       Kayes      Kayes      Bangassi    2009  6123  5974
##  2     2 Mali       Kayes      Kayes      Colimbine   2009  6144  6353
##  3     3 Mali       Kayes      Kayes      Diamou      2009  7115  7015
##  4     4 Mali       Kayes      Kayes      Djelebou    2009 11466 12091
##  5     5 Mali       Kayes      Kayes      Faleme      2009  5141  5017
##  6     6 Mali       Kayes      Kayes      Fegui       2009  1999  1934
##  7     7 Mali       Kayes      Kayes      Gory Gope~  2009  3939  3927
##  8     8 Mali       Kayes      Kayes      Goumera     2009  1918  1903
##  9     9 Mali       Kayes      Kayes      Guidimaka~  2009  9798 10234
## 10    10 Mali       Kayes      Kayes      Hawa Demb~  2009  3406  3445
## # ... with 693 more rows, and 1 more variable: source <chr>

Vous voyez!

Même si l’on passe un data frame à une fonction du tidyverse, le résultat est un tibble. Prenons la fonction glimpse du package dplyr (notez que glimpse veut dire aperçu en anglais).

# Importation des données
adm3_pop_2009 <- read.csv(source_donnees)

# Aperçu avec "glimpse"
glimpse(adm3_pop_2009)
## Observations: 703
## Variables: 9
## $ id         <int> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, ...
## $ admin0_nom <fct> Mali, Mali, Mali, Mali, Mali, Mali, Mali, Mali, Mal...
## $ admin1_nom <fct> Kayes, Kayes, Kayes, Kayes, Kayes, Kayes, Kayes, Ka...
## $ admin2_nom <fct> Kayes, Kayes, Kayes, Kayes, Kayes, Kayes, Kayes, Ka...
## $ admin3_nom <fct> Bangassi, Colimbine, Diamou, Djelebou, Faleme, Fegu...
## $ annee      <int> 2009, 2009, 2009, 2009, 2009, 2009, 2009, 2009, 200...
## $ homme      <dbl> 6123, 6144, 7115, 11466, 5141, 1999, 3939, 1918, 97...
## $ femme      <int> 5974, 6353, 7015, 12091, 5017, 1934, 3927, 1903, 10...
## $ source     <fct> RGPH, RGPH, RGPH, RGPH, RGPH, RGPH, RGPH, RGPH, RGP...
# Comparons à "str"
str(adm3_pop_2009)
## 'data.frame':    703 obs. of  9 variables:
##  $ id        : int  1 2 3 4 5 6 7 8 9 10 ...
##  $ admin0_nom: Factor w/ 1 level "Mali": 1 1 1 1 1 1 1 1 1 1 ...
##  $ admin1_nom: Factor w/ 9 levels "Bamako","Gao",..: 3 3 3 3 3 3 3 3 3 3 ...
##  $ admin2_nom: Factor w/ 50 levels "Abeibara","Ansongo",..: 23 23 23 23 23 23 23 23 23 23 ...
##  $ admin3_nom: Factor w/ 687 levels "Abeibara","Adarmalane",..: 25 74 116 156 192 210 231 238 249 257 ...
##  $ annee     : int  2009 2009 2009 2009 2009 2009 2009 2009 2009 2009 ...
##  $ homme     : num  6123 6144 7115 11466 5141 ...
##  $ femme     : int  5974 6353 7015 12091 5017 1934 3927 1903 10234 3445 ...
##  $ source    : Factor w/ 1 level "RGPH": 1 1 1 1 1 1 1 1 1 1 ...

Nous voyons que glimpse répartit différemment l’espace en les observations affichées. Il se préoccupe plus de l’équilibre entre celles-ci que les fonctions comme str ou head.

Nous allons maintenant explorer les verbes majeurs du package dplyr. Dans une démarche pédagogique - pour rappeler les bases déjà vue et enrichir celles-ci, au besoin - nous tenterons autant que possible de reproduire les exemples avec R-base aussi afin de mettre en exergue les différences.

6.3 Selection et/ou exclusion de variables: select

Comme nous avons vu précédemment, il arrive souvent que l’on veuille sélectionner certaines variables d’un jeu de données. Dans notre cas, supposons que nous sommes seulement intéressés par les chiffres. Il s’agit des colonnes: homme et femme.

Rappelons notre jeu de données.

# Chargement du package "readr"
library(readr)

# Importation des données
adm3_pop_2009 <- read_csv(source_donnees)

# Impression
adm3_pop_2009
## # A tibble: 703 x 9
##       id admin0_nom admin1_nom admin2_nom admin3_nom annee homme femme
##    <dbl> <chr>      <chr>      <chr>      <chr>      <dbl> <dbl> <dbl>
##  1     1 Mali       Kayes      Kayes      Bangassi    2009  6123  5974
##  2     2 Mali       Kayes      Kayes      Colimbine   2009  6144  6353
##  3     3 Mali       Kayes      Kayes      Diamou      2009  7115  7015
##  4     4 Mali       Kayes      Kayes      Djelebou    2009 11466 12091
##  5     5 Mali       Kayes      Kayes      Faleme      2009  5141  5017
##  6     6 Mali       Kayes      Kayes      Fegui       2009  1999  1934
##  7     7 Mali       Kayes      Kayes      Gory Gope~  2009  3939  3927
##  8     8 Mali       Kayes      Kayes      Goumera     2009  1918  1903
##  9     9 Mali       Kayes      Kayes      Guidimaka~  2009  9798 10234
## 10    10 Mali       Kayes      Kayes      Hawa Demb~  2009  3406  3445
## # ... with 693 more rows, and 1 more variable: source <chr>

Maintenant, passons d’abord par les méthodes de R-base, comme nous avons vu avant.

adm3_pop_2009[ , c("homme", "femme")]
## # A tibble: 703 x 2
##    homme femme
##    <dbl> <dbl>
##  1  6123  5974
##  2  6144  6353
##  3  7115  7015
##  4 11466 12091
##  5  5141  5017
##  6  1999  1934
##  7  3939  3927
##  8  1918  1903
##  9  9798 10234
## 10  3406  3445
## # ... with 693 more rows

ou

subset(x = adm3_pop_2009, select = c(homme, femme))
## # A tibble: 703 x 2
##    homme femme
##    <dbl> <dbl>
##  1  6123  5974
##  2  6144  6353
##  3  7115  7015
##  4 11466 12091
##  5  5141  5017
##  6  1999  1934
##  7  3939  3927
##  8  1918  1903
##  9  9798 10234
## 10  3406  3445
## # ... with 693 more rows

Dans dplyr, l’on utilise pour ce faire la fonction select qui va se rapprocher de la fonction subset de R-base.

select(adm3_pop_2009, homme, femme)
## # A tibble: 703 x 2
##    homme femme
##    <dbl> <dbl>
##  1  6123  5974
##  2  6144  6353
##  3  7115  7015
##  4 11466 12091
##  5  5141  5017
##  6  1999  1934
##  7  3939  3927
##  8  1918  1903
##  9  9798 10234
## 10  3406  3445
## # ... with 693 more rows

Le premier argument de la fonction est le jeu de données. Ceci est général pour toutes les fonctions de dplyr. Ensuite viennent les autres arguments. Ici, nous avons énuméré les variables qui nous intéressent. La fonction select présente une grande simplicité par rapport aux alternatives de R-base. A l’instar de subset, elle ne requiert pas que les noms de variables soient entre griffes (" "). Aussi, elle ne requiert pas que l’on spécifie le nombre d’observations à afficher, que l’input soit un data frame ou un tibble. Avec les fonctions de R-base, quand l’input est une tibble, l’affichage est limité à dix observations. Toutefois, cette règle est violée quand l’input est un data.frame.

6.3.1 Sélection simple

Il y a un autre avantage avec select, mais qui est commun au tidyverse tout entier. C’est l’opérateur: %>% que l’on appelle pipe opérator. Ce signe permet d’unir les lignes de codes en chaîne en leur servant de maillon. Il prend l’objet issu d’une ligne de départ ou d’une opération et fournit le résultat comme intrant à la ligne suivante. De ce fait, en l’utilisant, on n’a pas besoin de mettre dans une fonction l’argument spécifique à l’objet intrant. On peut se limiter aux arguments spécifiques à la tâche exécutée par la fonction. Réécrivons l’opération précédente.

adm3_pop_2009 %>% 
  select(homme, femme)
## # A tibble: 703 x 2
##    homme femme
##    <dbl> <dbl>
##  1  6123  5974
##  2  6144  6353
##  3  7115  7015
##  4 11466 12091
##  5  5141  5017
##  6  1999  1934
##  7  3939  3927
##  8  1918  1903
##  9  9798 10234
## 10  3406  3445
## # ... with 693 more rows

Avec %>%, nous verbalisons l’idée que nous partons du jeu de données, adm3_pop_2009, que nous soumettons ensuite à une opération de sélection à travers la fonction select. Nous obtenons le même résultat, mais la lisibilité est améliorée. Le signe %>% nous permet d’ordonner les lignes de codes de sorte à rendre compte du séquençage des opérations. A partir de maintenant, nous allons progressivement adoptée cette façon d’écrire les opérations.

6.3.2 Sélection groupée

Un autre avantage de select est de permettre la sélection de plusieurs variables à travers leur communalité. Dans notre jeu, nous avons trois variables qui portent toutes le terme admin comme préfixe. Plutôt que de les sélectionner une à une nous pouvons les appeler toutes ensembles. Commençons par R-base.

names_df <- names(adm3_pop_2009)
select_df <- startsWith(x = names_df, prefix = "adm")
adm3_pop_2009[, select_df]
## # A tibble: 703 x 4
##    admin0_nom admin1_nom admin2_nom admin3_nom          
##    <chr>      <chr>      <chr>      <chr>               
##  1 Mali       Kayes      Kayes      Bangassi            
##  2 Mali       Kayes      Kayes      Colimbine           
##  3 Mali       Kayes      Kayes      Diamou              
##  4 Mali       Kayes      Kayes      Djelebou            
##  5 Mali       Kayes      Kayes      Faleme              
##  6 Mali       Kayes      Kayes      Fegui               
##  7 Mali       Kayes      Kayes      Gory Gopela         
##  8 Mali       Kayes      Kayes      Goumera             
##  9 Mali       Kayes      Kayes      Guidimakan Keri Kaff
## 10 Mali       Kayes      Kayes      Hawa Dembaya        
## # ... with 693 more rows

Cette opération nous a pris trois lignes différentes. Avec select, nous en faisons juste de deux lignes séquencées (même une si l’on veut).

adm3_pop_2009 %>% 
  select(starts_with("adm"))
## # A tibble: 703 x 4
##    admin0_nom admin1_nom admin2_nom admin3_nom          
##    <chr>      <chr>      <chr>      <chr>               
##  1 Mali       Kayes      Kayes      Bangassi            
##  2 Mali       Kayes      Kayes      Colimbine           
##  3 Mali       Kayes      Kayes      Diamou              
##  4 Mali       Kayes      Kayes      Djelebou            
##  5 Mali       Kayes      Kayes      Faleme              
##  6 Mali       Kayes      Kayes      Fegui               
##  7 Mali       Kayes      Kayes      Gory Gopela         
##  8 Mali       Kayes      Kayes      Goumera             
##  9 Mali       Kayes      Kayes      Guidimakan Keri Kaff
## 10 Mali       Kayes      Kayes      Hawa Dembaya        
## # ... with 693 more rows

L’on peut faire la même chose avec les suffixes…

adm3_pop_2009 %>% 
  select(ends_with("nom"))
## # A tibble: 703 x 4
##    admin0_nom admin1_nom admin2_nom admin3_nom          
##    <chr>      <chr>      <chr>      <chr>               
##  1 Mali       Kayes      Kayes      Bangassi            
##  2 Mali       Kayes      Kayes      Colimbine           
##  3 Mali       Kayes      Kayes      Diamou              
##  4 Mali       Kayes      Kayes      Djelebou            
##  5 Mali       Kayes      Kayes      Faleme              
##  6 Mali       Kayes      Kayes      Fegui               
##  7 Mali       Kayes      Kayes      Gory Gopela         
##  8 Mali       Kayes      Kayes      Goumera             
##  9 Mali       Kayes      Kayes      Guidimakan Keri Kaff
## 10 Mali       Kayes      Kayes      Hawa Dembaya        
## # ... with 693 more rows

…ou chercher des termes indépendemment de leur position dans le nom des variables.

adm3_pop_2009 %>% 
  select(contains("nom"))
## # A tibble: 703 x 4
##    admin0_nom admin1_nom admin2_nom admin3_nom          
##    <chr>      <chr>      <chr>      <chr>               
##  1 Mali       Kayes      Kayes      Bangassi            
##  2 Mali       Kayes      Kayes      Colimbine           
##  3 Mali       Kayes      Kayes      Diamou              
##  4 Mali       Kayes      Kayes      Djelebou            
##  5 Mali       Kayes      Kayes      Faleme              
##  6 Mali       Kayes      Kayes      Fegui               
##  7 Mali       Kayes      Kayes      Gory Gopela         
##  8 Mali       Kayes      Kayes      Goumera             
##  9 Mali       Kayes      Kayes      Guidimakan Keri Kaff
## 10 Mali       Kayes      Kayes      Hawa Dembaya        
## # ... with 693 more rows

dplyr contient une variétés de fonctions similaires dont: matches(), num_range(), one_of(), everything(), group_cols(). Avec R, l’on peut aboutir au même résultat en utilisant différentes méthodes. La force de dplyr - et de tidyverse dans une large mesure - est que la méthode est plus économe en écriture de codes et le séquençage bien explicité à l’aide de l’opérateur %>%.

6.3.3 Index et nom

La sélection peut aussi se faire sur la base de l’index des colonnes, c’est-à-dire leur position. Sélectionnons de la deuxième à la cinquième colonne.

# Avec R-base
adm3_pop_2009[, c(2:5)]
## # A tibble: 703 x 4
##    admin0_nom admin1_nom admin2_nom admin3_nom          
##    <chr>      <chr>      <chr>      <chr>               
##  1 Mali       Kayes      Kayes      Bangassi            
##  2 Mali       Kayes      Kayes      Colimbine           
##  3 Mali       Kayes      Kayes      Diamou              
##  4 Mali       Kayes      Kayes      Djelebou            
##  5 Mali       Kayes      Kayes      Faleme              
##  6 Mali       Kayes      Kayes      Fegui               
##  7 Mali       Kayes      Kayes      Gory Gopela         
##  8 Mali       Kayes      Kayes      Goumera             
##  9 Mali       Kayes      Kayes      Guidimakan Keri Kaff
## 10 Mali       Kayes      Kayes      Hawa Dembaya        
## # ... with 693 more rows
# Avec dpylr
adm3_pop_2009 %>% 
  select(2:5)
## # A tibble: 703 x 4
##    admin0_nom admin1_nom admin2_nom admin3_nom          
##    <chr>      <chr>      <chr>      <chr>               
##  1 Mali       Kayes      Kayes      Bangassi            
##  2 Mali       Kayes      Kayes      Colimbine           
##  3 Mali       Kayes      Kayes      Diamou              
##  4 Mali       Kayes      Kayes      Djelebou            
##  5 Mali       Kayes      Kayes      Faleme              
##  6 Mali       Kayes      Kayes      Fegui               
##  7 Mali       Kayes      Kayes      Gory Gopela         
##  8 Mali       Kayes      Kayes      Goumera             
##  9 Mali       Kayes      Kayes      Guidimakan Keri Kaff
## 10 Mali       Kayes      Kayes      Hawa Dembaya        
## # ... with 693 more rows

La même chose peut se faire avec le nom des variables.

# Avec R-base
adm3_pop_2009[, c("admin0_nom", "admin1_nom", "admin2_nom", "admin3_nom")]
## # A tibble: 703 x 4
##    admin0_nom admin1_nom admin2_nom admin3_nom          
##    <chr>      <chr>      <chr>      <chr>               
##  1 Mali       Kayes      Kayes      Bangassi            
##  2 Mali       Kayes      Kayes      Colimbine           
##  3 Mali       Kayes      Kayes      Diamou              
##  4 Mali       Kayes      Kayes      Djelebou            
##  5 Mali       Kayes      Kayes      Faleme              
##  6 Mali       Kayes      Kayes      Fegui               
##  7 Mali       Kayes      Kayes      Gory Gopela         
##  8 Mali       Kayes      Kayes      Goumera             
##  9 Mali       Kayes      Kayes      Guidimakan Keri Kaff
## 10 Mali       Kayes      Kayes      Hawa Dembaya        
## # ... with 693 more rows
# Avec dplyr
adm3_pop_2009 %>% 
  select(admin0_nom, admin1_nom, admin2_nom, admin3_nom)
## # A tibble: 703 x 4
##    admin0_nom admin1_nom admin2_nom admin3_nom          
##    <chr>      <chr>      <chr>      <chr>               
##  1 Mali       Kayes      Kayes      Bangassi            
##  2 Mali       Kayes      Kayes      Colimbine           
##  3 Mali       Kayes      Kayes      Diamou              
##  4 Mali       Kayes      Kayes      Djelebou            
##  5 Mali       Kayes      Kayes      Faleme              
##  6 Mali       Kayes      Kayes      Fegui               
##  7 Mali       Kayes      Kayes      Gory Gopela         
##  8 Mali       Kayes      Kayes      Goumera             
##  9 Mali       Kayes      Kayes      Guidimakan Keri Kaff
## 10 Mali       Kayes      Kayes      Hawa Dembaya        
## # ... with 693 more rows

L’on peut faire plus simple avec dplyr quand les variables recherchées se suivent.

adm3_pop_2009 %>% 
  select(admin0_nom:admin3_nom)

6.3.4 Exclusion

Comme avec R-base, la sélection peut aussi se faire sur la base de l’exclusion. Imaginez que l’on souhaite exclure les quatre premières variables.

# Avec R-base
adm3_pop_2009[, -c(1:4)]
## # A tibble: 703 x 5
##    admin3_nom           annee homme femme source
##    <chr>                <dbl> <dbl> <dbl> <chr> 
##  1 Bangassi              2009  6123  5974 RGPH  
##  2 Colimbine             2009  6144  6353 RGPH  
##  3 Diamou                2009  7115  7015 RGPH  
##  4 Djelebou              2009 11466 12091 RGPH  
##  5 Faleme                2009  5141  5017 RGPH  
##  6 Fegui                 2009  1999  1934 RGPH  
##  7 Gory Gopela           2009  3939  3927 RGPH  
##  8 Goumera               2009  1918  1903 RGPH  
##  9 Guidimakan Keri Kaff  2009  9798 10234 RGPH  
## 10 Hawa Dembaya          2009  3406  3445 RGPH  
## # ... with 693 more rows
# Avec dplyr
adm3_pop_2009 %>% 
  select(-c(1:4))
## # A tibble: 703 x 5
##    admin3_nom           annee homme femme source
##    <chr>                <dbl> <dbl> <dbl> <chr> 
##  1 Bangassi              2009  6123  5974 RGPH  
##  2 Colimbine             2009  6144  6353 RGPH  
##  3 Diamou                2009  7115  7015 RGPH  
##  4 Djelebou              2009 11466 12091 RGPH  
##  5 Faleme                2009  5141  5017 RGPH  
##  6 Fegui                 2009  1999  1934 RGPH  
##  7 Gory Gopela           2009  3939  3927 RGPH  
##  8 Goumera               2009  1918  1903 RGPH  
##  9 Guidimakan Keri Kaff  2009  9798 10234 RGPH  
## 10 Hawa Dembaya          2009  3406  3445 RGPH  
## # ... with 693 more rows

L’on voit qu’à l’instar de R-base, l’on a juste à précédér les éléments à exclure du signe -.

6.3.5 Une pierre deux coups

dplyr compte une fonction rename qui permet de renommer les variables. Prise indépendemment, elle agit comme select. Supposons que nous voulions changer les noms de variables en majuscules.

## Avec R-base
# Sauvegarde des données dans un nouveau data frame
pop_df <- adm3_pop_2009[ , c("homme", "femme")]
# Voir les noms
names(pop_df)
## [1] "homme" "femme"
# Changer les noms
names(pop_df) <- c("HOMME", "FEMME")
# Vérification
names(pop_df)
## [1] "HOMME" "FEMME"
## Avec dplyr
# Jeu de données de départ
adm3_pop_2009 %>% 
  # Sélection des variables d'intérêt
  select(homme, femme) %>% 
  # Modification des noms de variables
  rename(HOMME = homme, FEMME = femme)
## # A tibble: 703 x 2
##    HOMME FEMME
##    <dbl> <dbl>
##  1  6123  5974
##  2  6144  6353
##  3  7115  7015
##  4 11466 12091
##  5  5141  5017
##  6  1999  1934
##  7  3939  3927
##  8  1918  1903
##  9  9798 10234
## 10  3406  3445
## # ... with 693 more rows

Nous voyons qu’une telle opération qu’avec R-base requiert la création d’un objet intermédiaire tandis qu’avec dplyr elle s’insère tout simplement dans la séquence. Mais select peut elle-même prendre en charge la tâche de changement de noms.

# Jeu de données de départ
adm3_pop_2009 %>% 
  # Sélection des variables d'intérêt et changement de noms
  select(HOMME = homme, FEMME = femme)
## # A tibble: 703 x 2
##    HOMME FEMME
##    <dbl> <dbl>
##  1  6123  5974
##  2  6144  6353
##  3  7115  7015
##  4 11466 12091
##  5  5141  5017
##  6  1999  1934
##  7  3939  3927
##  8  1918  1903
##  9  9798 10234
## 10  3406  3445
## # ... with 693 more rows

L’on indique le nouveau nom suivi du signe = et ensuite le nouveau nom.

6.4 Création et/ou suppression de variables: mutate

La sélection et la suppression de variables peuvent s’inscrire dans le cadre d’une stratégie d’exploration plus large qui peut elle-même impliquer la création de nouvelles variables.

6.4.1 Création de variable

Revenons à l’exploration de la supériorité numérique entre hommes et femmes, sujet que nous avons abordé dans le chapitre précédent. Supposons que nous souhaitions:

  • sélectionner les populations pour les hommes et les femmes pour chaque commune;

  • calculer un ratio femme/homme pour chaque commune.

## Avec R-base
# Sélection des variables d'intérêt
pop_df <- adm3_pop_2009[ , c("admin3_nom", "homme", "femme")]
# Création d'une nouvelle variable
pop_df$ratio <- pop_df$femme / pop_df$homme
# Aperçu
pop_df
## # A tibble: 703 x 4
##    admin3_nom           homme femme ratio
##    <chr>                <dbl> <dbl> <dbl>
##  1 Bangassi              6123  5974 0.976
##  2 Colimbine             6144  6353 1.03 
##  3 Diamou                7115  7015 0.986
##  4 Djelebou             11466 12091 1.05 
##  5 Faleme                5141  5017 0.976
##  6 Fegui                 1999  1934 0.967
##  7 Gory Gopela           3939  3927 0.997
##  8 Goumera               1918  1903 0.992
##  9 Guidimakan Keri Kaff  9798 10234 1.04 
## 10 Hawa Dembaya          3406  3445 1.01 
## # ... with 693 more rows
## Avec dplyr
  # Jeu de données de départ
adm3_pop_2009 %>% 
  # Sélection des variables d'intérêt
  select(admin3_nom, homme, femme) %>% 
  # Création d'une nouvelle variable
  mutate(ratio = homme/femme)
## # A tibble: 703 x 4
##    admin3_nom           homme femme ratio
##    <chr>                <dbl> <dbl> <dbl>
##  1 Bangassi              6123  5974 1.02 
##  2 Colimbine             6144  6353 0.967
##  3 Diamou                7115  7015 1.01 
##  4 Djelebou             11466 12091 0.948
##  5 Faleme                5141  5017 1.02 
##  6 Fegui                 1999  1934 1.03 
##  7 Gory Gopela           3939  3927 1.00 
##  8 Goumera               1918  1903 1.01 
##  9 Guidimakan Keri Kaff  9798 10234 0.957
## 10 Hawa Dembaya          3406  3445 0.989
## # ... with 693 more rows

Le résultat est le même, mais le gain avec dplyr est visible. Le séquençage rend la lecture du code facile. Il évite aussi la création d’un objet intermédiaire, comme ce fut le cas de pop_df avec R-base.

Dans le cas précédent, la variable était numérique. Elle peut aussi prendre la forme catégorielle. Considérons par exemple des intervalles de population qu’on souhaiterait créer pour séparer les communes en catégories. Nous allons d’abord faire la somme des deux groupes, hommes et femmes, et ensuite créer la variable catégorielle.

## Avec R-base
# Sélection des variables d'intérêt
pop_df <- adm3_pop_2009[ , c("admin3_nom", "homme", "femme")]
# Création d'une nouvelle variable: numérique
pop_df$total <- pop_df$femme + pop_df$homme
# Création d'une nouvelle variable: catégorielle
pop_df$pop_cat <- ifelse(pop_df$total < 10000, "<10000", ">=10000")
# Aperçu
pop_df
## # A tibble: 703 x 5
##    admin3_nom           homme femme total pop_cat
##    <chr>                <dbl> <dbl> <dbl> <chr>  
##  1 Bangassi              6123  5974 12097 >=10000
##  2 Colimbine             6144  6353 12497 >=10000
##  3 Diamou                7115  7015 14130 >=10000
##  4 Djelebou             11466 12091 23557 >=10000
##  5 Faleme                5141  5017 10158 >=10000
##  6 Fegui                 1999  1934  3933 <10000 
##  7 Gory Gopela           3939  3927  7866 <10000 
##  8 Goumera               1918  1903  3821 <10000 
##  9 Guidimakan Keri Kaff  9798 10234 20032 >=10000
## 10 Hawa Dembaya          3406  3445  6851 <10000 
## # ... with 693 more rows
## Avec dplyr
  # Jeu de données de départ
adm3_pop_2009 %>% 
  # Sélection des variables d'intérêt
  select(admin3_nom, homme, femme) %>% 
  # Création d'une nouvelle variable: numérique
  mutate(total = homme + femme) %>%
  # Création d'une nouvelle variable: catégorielle
  mutate(pop_cat = ifelse(total < 10000, "<10000", ">=10000"))
## # A tibble: 703 x 5
##    admin3_nom           homme femme total pop_cat
##    <chr>                <dbl> <dbl> <dbl> <chr>  
##  1 Bangassi              6123  5974 12097 >=10000
##  2 Colimbine             6144  6353 12497 >=10000
##  3 Diamou                7115  7015 14130 >=10000
##  4 Djelebou             11466 12091 23557 >=10000
##  5 Faleme                5141  5017 10158 >=10000
##  6 Fegui                 1999  1934  3933 <10000 
##  7 Gory Gopela           3939  3927  7866 <10000 
##  8 Goumera               1918  1903  3821 <10000 
##  9 Guidimakan Keri Kaff  9798 10234 20032 >=10000
## 10 Hawa Dembaya          3406  3445  6851 <10000 
## # ... with 693 more rows

Il est intéréssant de rélever qu’avec cet exemple l’on vient de montrer que la fonction mutate prend en charge les déclarations conditionnelles.

A l’instar de select qui accepte la liste de toutes les variables à sélection, mutate aussi peut, avec un seul appel, exécuter plusieurs opérations de création de variables.

  # Jeu de données de départ
adm3_pop_2009 %>% 
  # Sélection des variables d'intérêt
  select(admin3_nom, homme, femme) %>% 
  # Création de deux nouvelles variables: numérique et catégorielle
  mutate(total = homme + femme,
         pop_cat = ifelse(total < 10000, "<10000", ">=10000"))
## # A tibble: 703 x 5
##    admin3_nom           homme femme total pop_cat
##    <chr>                <dbl> <dbl> <dbl> <chr>  
##  1 Bangassi              6123  5974 12097 >=10000
##  2 Colimbine             6144  6353 12497 >=10000
##  3 Diamou                7115  7015 14130 >=10000
##  4 Djelebou             11466 12091 23557 >=10000
##  5 Faleme                5141  5017 10158 >=10000
##  6 Fegui                 1999  1934  3933 <10000 
##  7 Gory Gopela           3939  3927  7866 <10000 
##  8 Goumera               1918  1903  3821 <10000 
##  9 Guidimakan Keri Kaff  9798 10234 20032 >=10000
## 10 Hawa Dembaya          3406  3445  6851 <10000 
## # ... with 693 more rows

L’appel de mutate n’a pas à être spécifique à une seule variable. La fonction peut effectuer plusieurs opérations lors d’un seul appel.

6.4.2 Suppression de variables

Comme dans R-base, l’on supprime une variable en lui affectant la valeur NULL.

  # Jeu de données de départ
adm3_pop_2009 %>% 
  # Sélection des variables d'intérêt
  select(admin3_nom, homme, femme) %>% 
  mutate(
    # Création de deux nouvelles variables: numérique et catégorielle
    total = homme + femme, 
    pop_cat = ifelse(total < 10000, "<10000", ">=10000"),
    # Suppression de variables
    homme = NULL,
    femme = NULL
    )
## # A tibble: 703 x 3
##    admin3_nom           total pop_cat
##    <chr>                <dbl> <chr>  
##  1 Bangassi             12097 >=10000
##  2 Colimbine            12497 >=10000
##  3 Diamou               14130 >=10000
##  4 Djelebou             23557 >=10000
##  5 Faleme               10158 >=10000
##  6 Fegui                 3933 <10000 
##  7 Gory Gopela           7866 <10000 
##  8 Goumera               3821 <10000 
##  9 Guidimakan Keri Kaff 20032 >=10000
## 10 Hawa Dembaya          6851 <10000 
## # ... with 693 more rows

6.4.3 Ne garder que le résultat

Une variante de la fonction mutate est la fonction transmute qui a la particularité de ne garder que les résultats issus des tâches qui lui ont été confiées. Elle présente certes une approche radicale par rapport à une suppression sélective des variables, mais elle est très commode pour celui que n’est intéréssé que par les résultats. Elle se distingue ainsi de mutate qui, quant à elle, préserve les variables préexistantes à l’opération de création de nouvelles colonnes

Reprenons le dernier exemple.

## Avec R-base
# Sélection des variables d'intérêt
pop_df <- adm3_pop_2009[ , c("admin3_nom", "homme", "femme")]
# Création d'une nouvelle variable: numérique
pop_df$total <- pop_df$femme + pop_df$homme
# Création d'une nouvelle variable: catégorielle
pop_df$pop_cat <- ifelse(pop_df$total < 10000, "<10000", ">=10000")
# Suppression de variables
pop_df$admin3_nom <- NULL
pop_df$homme <- NULL
pop_df$femme <- NULL
# Alternative: sélection des variables créées
# Aperçu
pop_df
## # A tibble: 703 x 2
##    total pop_cat
##    <dbl> <chr>  
##  1 12097 >=10000
##  2 12497 >=10000
##  3 14130 >=10000
##  4 23557 >=10000
##  5 10158 >=10000
##  6  3933 <10000 
##  7  7866 <10000 
##  8  3821 <10000 
##  9 20032 >=10000
## 10  6851 <10000 
## # ... with 693 more rows
## Avec dplyr
  # Jeu de données de départ
adm3_pop_2009 %>% 
  # Sélection des variables d'intérêt
  select(admin3_nom, homme, femme) %>% 
  # Création de deux nouvelles variables: numérique et catégorielle
  transmute(total = homme + femme, 
            pop_cat = ifelse(total < 10000, "<10000", ">=10000"))
## # A tibble: 703 x 2
##    total pop_cat
##    <dbl> <chr>  
##  1 12097 >=10000
##  2 12497 >=10000
##  3 14130 >=10000
##  4 23557 >=10000
##  5 10158 >=10000
##  6  3933 <10000 
##  7  7866 <10000 
##  8  3821 <10000 
##  9 20032 >=10000
## 10  6851 <10000 
## # ... with 693 more rows

Vous voyez! Comme résultat, nous avons les deux nouvelles colonnes. Toutes les autres ont été omises. Toutefois, le nombre d’observations n’a pas varié.

Les avantages de dplyr deviennent évident avec l’augmentation du nombre d’opérations à effectuer sur une intrant donné, très généralement un jeu de données rectangulaires (data frame ou tibble).

6.5 Sélection d’observations: filter

Dans le chapitre précédent, nous avions vu quelques techniques de sélections d’observations. Souvent à partir de la position, souvent à partir de critères définis. Re-appliquons certaines de ces techniques à nos données et comparons à la démarche de dplyr.

6.5.1 Sur la base de critères numériques

Regardons à nouveau notre jeu de données.

glimpse(adm3_pop_2009)
## Observations: 703
## Variables: 9
## $ id         <dbl> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, ...
## $ admin0_nom <chr> "Mali", "Mali", "Mali", "Mali", "Mali", "Mali", "Ma...
## $ admin1_nom <chr> "Kayes", "Kayes", "Kayes", "Kayes", "Kayes", "Kayes...
## $ admin2_nom <chr> "Kayes", "Kayes", "Kayes", "Kayes", "Kayes", "Kayes...
## $ admin3_nom <chr> "Bangassi", "Colimbine", "Diamou", "Djelebou", "Fal...
## $ annee      <dbl> 2009, 2009, 2009, 2009, 2009, 2009, 2009, 2009, 200...
## $ homme      <dbl> 6123, 6144, 7115, 11466, 5141, 1999, 3939, 1918, 97...
## $ femme      <dbl> 5974, 6353, 7015, 12091, 5017, 1934, 3927, 1903, 10...
## $ source     <chr> "RGPH", "RGPH", "RGPH", "RGPH", "RGPH", "RGPH", "RG...

Nous avons 703 observations, donc 703 communes. Regardons les plus grandes en matière de population. Disons, celles qui sont au dessus du seuil de 100000 habitants.

## Avec R-base.
# Sélection des variables d'intérêt
pop_df <- adm3_pop_2009[ , c("admin3_nom", "homme", "femme")]
# Création d'une nouvelle variable: numérique
pop_df$total <- pop_df$femme + pop_df$homme
# Critère de sélection: valeurs logiques (TRUE/FALSE)
pop_100000_plus <- pop_df$total > 100000
# Mise en oeuvre de la sélection
pop_df[pop_100000_plus, ]
## # A tibble: 12 x 4
##    admin3_nom        homme  femme  total
##    <chr>             <dbl>  <dbl>  <dbl>
##  1 Kayes Commune     65135  61184 126319
##  2 Kalabancoro       81018  80864 161882
##  3 Koutiala Commune  70905  70539 141444
##  4 Sikasso Commune  114171 112447 226618
##  5 Segou Commune     66819  66682 133501
##  6 Mopti Commune     60080  60706 120786
##  7 Commune I        168308 166587 334895
##  8 Commune II        78690  80670 159360
##  9 Commune III       63792  64874 128666
## 10 Commune IV       152153 152373 304526
## 11 Commune V        206749 206517 413266
## 12 Commune VI       237951 231702 469653
## Avec dplyr
  # Jeu de données de départ
adm3_pop_2009 %>% 
  # Sélection des variables d'intérêt
  select(admin3_nom, homme, femme) %>% 
  # Création d'une nouvelle variable
  mutate(total = homme + femme) %>% 
  # Sélection d'observations d'intérêt
  filter(total > 100000)
## # A tibble: 12 x 4
##    admin3_nom        homme  femme  total
##    <chr>             <dbl>  <dbl>  <dbl>
##  1 Kayes Commune     65135  61184 126319
##  2 Kalabancoro       81018  80864 161882
##  3 Koutiala Commune  70905  70539 141444
##  4 Sikasso Commune  114171 112447 226618
##  5 Segou Commune     66819  66682 133501
##  6 Mopti Commune     60080  60706 120786
##  7 Commune I        168308 166587 334895
##  8 Commune II        78690  80670 159360
##  9 Commune III       63792  64874 128666
## 10 Commune IV       152153 152373 304526
## 11 Commune V        206749 206517 413266
## 12 Commune VI       237951 231702 469653

Là aussi, nous voyons que la séquence est plus économe en écriture.

Il arrive souvent aussi que la sélection porte sur un interval ou une région. Dans ce genre de cas, dplyr a des fonctions spécialisées comme between ou near.

Si l’on cherche les communes dont la population est comprise entre 50000 et 60000

## Avec R-base.
# Sélection des variables d'intérêt
pop_df <- adm3_pop_2009[ , c("admin3_nom", "homme", "femme")]
# Création d'une nouvelle variable: numérique
pop_df$total <- pop_df$femme + pop_df$homme
# Critère de sélection: valeurs logiques (TRUE/FALSE)
pop_50k_60k <- pop_df$total >= 50000 & pop_df$total <= 60000
# Mise en oeuvre de la sélection
pop_df[pop_50k_60k, ]
## # A tibble: 13 x 4
##    admin3_nom       homme femme total
##    <chr>            <dbl> <dbl> <dbl>
##  1 Massigui         26249 28003 54252
##  2 Baguineda Camp   26406 25415 51821
##  3 Mande            28734 28615 57349
##  4 Ouelessebougou   24694 25345 50039
##  5 Kadiolo          25394 26622 52016
##  6 Koury            26842 27448 54290
##  7 Kolondieba       25976 27404 53380
##  8 Wassoulou Balle  25532 25941 51473
##  9 Bougouni Commune 29581 28957 58538
## 10 Koumantou        24828 26381 51209
## 11 Pelengana        27796 28051 55847
## 12 Tombouctou       27915 26714 54629
## 13 Tonka            25698 27578 53276
## Avec dplyr
  # Jeu de données de départ
adm3_pop_2009 %>% 
  # Sélection des variables d'intérêt
  select(admin3_nom, homme, femme) %>% 
  # Création d'une nouvelle variable
  mutate(total = homme + femme) %>% 
  # Sélection d'observations d'intérêt
  filter(between(x = total, left = 50000, right = 60000))
## # A tibble: 13 x 4
##    admin3_nom       homme femme total
##    <chr>            <dbl> <dbl> <dbl>
##  1 Massigui         26249 28003 54252
##  2 Baguineda Camp   26406 25415 51821
##  3 Mande            28734 28615 57349
##  4 Ouelessebougou   24694 25345 50039
##  5 Kadiolo          25394 26622 52016
##  6 Koury            26842 27448 54290
##  7 Kolondieba       25976 27404 53380
##  8 Wassoulou Balle  25532 25941 51473
##  9 Bougouni Commune 29581 28957 58538
## 10 Koumantou        24828 26381 51209
## 11 Pelengana        27796 28051 55847
## 12 Tombouctou       27915 26714 54629
## 13 Tonka            25698 27578 53276

Et pour les communes autour de 50000 habitants. Disons que nous prendrons en compte les communes dans les valeurs environnantes et ce jusqu’au 2500 personnes

## Avec R-base.
# Sélection des variables d'intérêt
pop_df <- adm3_pop_2009[ , c("admin3_nom", "homme", "femme")]
# Création d'une nouvelle variable: numérique
pop_df$total <- pop_df$femme + pop_df$homme
# Critère de sélection: valeurs logiques (TRUE/FALSE)
pop_50k_tol2500 <- pop_df$total >= 50000 - 2500 & pop_df$total <= 50000 + 2500
# Mise en oeuvre de la sélection
pop_df[pop_50k_tol2500, ]
## # A tibble: 9 x 4
##   admin3_nom      homme femme total
##   <chr>           <dbl> <dbl> <dbl>
## 1 Kita Commune    24054 24989 49043
## 2 Guegneka        23949 24092 48041
## 3 Baguineda Camp  26406 25415 51821
## 4 Ouelessebougou  24694 25345 50039
## 5 Kadiolo         25394 26622 52016
## 6 Misseni         28443 19230 47673
## 7 Wassoulou Balle 25532 25941 51473
## 8 Koumantou       24828 26381 51209
## 9 Sony Aliber     23472 24146 47618
## Avec dplyr
  # Jeu de données de départ
adm3_pop_2009 %>% 
  # Sélection des variables d'intérêt
  select(admin3_nom, homme, femme) %>% 
  # Création d'une nouvelle variable
  mutate(total = homme + femme) %>% 
  # Sélection d'observations d'intérêt
  filter(near(x = total, y = 50000, tol = 2500))
## # A tibble: 9 x 4
##   admin3_nom      homme femme total
##   <chr>           <dbl> <dbl> <dbl>
## 1 Kita Commune    24054 24989 49043
## 2 Guegneka        23949 24092 48041
## 3 Baguineda Camp  26406 25415 51821
## 4 Ouelessebougou  24694 25345 50039
## 5 Kadiolo         25394 26622 52016
## 6 Misseni         28443 19230 47673
## 7 Wassoulou Balle 25532 25941 51473
## 8 Koumantou       24828 26381 51209
## 9 Sony Aliber     23472 24146 47618

6.5.2 Sur la base de critères catégoriels.

La sélection peut aussi porter sur des variables en caractères ou catégorielles. Supposons que nous souhaitons connaître la population d’une commune dont nous avons le nom: Bambara Maoudé.

## Avec R-base
# Sélection des variables d'intérêt
pop_df <- adm3_pop_2009[ , c("admin3_nom", "homme", "femme")]
# Création d'une nouvelle variable: numérique
pop_df$total <- pop_df$femme + pop_df$homme
# Critère de sélection: valeurs logiques (TRUE/FALSE)
bambara_maoude <- pop_df$admin3_nom == "Bambara Maoude"
# Mise en oeuvre de la sélection
pop_df[bambara_maoude, ]
## # A tibble: 1 x 4
##   admin3_nom     homme femme total
##   <chr>          <dbl> <dbl> <dbl>
## 1 Bambara Maoude  8315  8170 16485
## Avec dplyr
  # Jeu de données de départ
adm3_pop_2009 %>% 
  # Sélection des variables d'intérêt
  select(admin3_nom, homme, femme) %>% 
  # Création d'une nouvelle variable
  mutate(total = homme + femme) %>% 
  # Sélection d'observations d'intérêt
  filter(admin3_nom == "Bambara Maoude")
## # A tibble: 1 x 4
##   admin3_nom     homme femme total
##   <chr>          <dbl> <dbl> <dbl>
## 1 Bambara Maoude  8315  8170 16485

En ce qui concernent les critères alternatifs, dplyr offre une commodité avec le signe %in%. Imaginez qu’au lieu d’une seule commune, Bambara Maoude, que l’on souhaite sélectionner les résultats d’un groupe de communes dont on a connait le nom. Plutôt que d’utiliser |, l’on peut passer par %in%.

## Avec R-base
# Sélection des variables d'intérêt
pop_df <- adm3_pop_2009[ , c("admin3_nom", "homme", "femme")]
# Création d'une nouvelle variable: numérique
pop_df$total <- pop_df$femme + pop_df$homme
# Critère de sélection: valeurs logiques (TRUE/FALSE)
groupe_commune <- pop_df$admin3_nom == "Bambara Maoude" |  
                  pop_df$admin3_nom == "Segou Commune" |
                  pop_df$admin3_nom == "Soumpi" | 
                  pop_df$admin3_nom == "Ansongo"
# Mise en oeuvre de la sélection
pop_df[groupe_commune, ]
## # A tibble: 4 x 4
##   admin3_nom     homme femme  total
##   <chr>          <dbl> <dbl>  <dbl>
## 1 Segou Commune  66819 66682 133501
## 2 Bambara Maoude  8315  8170  16485
## 3 Soumpi          8547  8401  16948
## 4 Ansongo        14707 15384  30091
## Avec dplyr
  # Jeu de données de départ
adm3_pop_2009 %>% 
  # Sélection des variables d'intérêt
  select(admin3_nom, homme, femme) %>% 
  # Création d'une nouvelle variable
  mutate(total = homme + femme) %>% 
  # Sélection d'observations d'intérêt
  filter(admin3_nom %in% c("Bambara Maoude", "Segou Commune", "Soumpi", "Ansongo"))
## # A tibble: 4 x 4
##   admin3_nom     homme femme  total
##   <chr>          <dbl> <dbl>  <dbl>
## 1 Segou Commune  66819 66682 133501
## 2 Bambara Maoude  8315  8170  16485
## 3 Soumpi          8547  8401  16948
## 4 Ansongo        14707 15384  30091

Moins de lignes! Même résultat!

6.5.3 Sur la base d’expressions régulières

Comme avec select, les fonctions relatives aux préfixes et suffixes (et similaires) peuvent être mobilisées dans filter aussi. Suppossons que l’on veuille connaître la population de toutes les communes dont le nom se termine par dougou.

## Avec R-base
# Sélection des variables d'intérêt
pop_df <- adm3_pop_2009[ , c("admin3_nom", "homme", "femme")]
# Création d'une nouvelle variable: numérique
pop_df$total <- pop_df$femme + pop_df$homme
# Sélection des communes répondant au critère
select_nom <- endsWith(x = pop_df$admin3_nom, suffix = "dougou")
# Mise en oeuvre de la sélection
pop_df[select_df, ]
## Warning: Length of logical index must be 1 or 703, not 9
## # A tibble: 312 x 4
##    admin3_nom        homme femme  total
##    <chr>             <dbl> <dbl>  <dbl>
##  1 Colimbine          6144  6353  12497
##  2 Diamou             7115  7015  14130
##  3 Djelebou          11466 12091  23557
##  4 Faleme             5141  5017  10158
##  5 Karakoro           7436  7770  15206
##  6 Kayes Commune     65135 61184 126319
##  7 Kemene Tambo       8381  8574  16955
##  8 Khouloum           9734  9260  18994
##  9 Marena Diombougou  8996  9676  18672
## 10 Marintoumania      4001  4060   8061
## # ... with 302 more rows
## Avec dplyr
  # Jeu de données de départ
adm3_pop_2009 %>% 
  # Sélection des variables d'intérêt
  select(admin3_nom, homme, femme) %>% 
  # Création d'une nouvelle variable
  mutate(total = homme + femme) %>% 
  # Sélection d'observations d'intérêt
  filter(endsWith(x = admin3_nom, suffix = "dougou"))
## # A tibble: 28 x 4
##    admin3_nom    homme femme total
##    <chr>         <dbl> <dbl> <dbl>
##  1 Gomitradougou  3638  3658  7296
##  2 Dinandougou   10571 10789 21360
##  3 Diedougou     17541 18351 35892
##  4 Dolendougou    6831  7389 14220
##  5 Kaladougou    19429 19742 39171
##  6 Kilidougou     7578  7930 15508
##  7 N'dlondougou  10326 10667 20993
##  8 N'garadougou   7633  7960 15593
##  9 Tenindougou    7681  7725 15406
## 10 Maramandougou  7237  7302 14539
## # ... with 18 more rows

La fonction filter épouse aussi bien les fonctions spécifiques aux expressions régulières dans R-base - comme dans l’exemple précédent - que celles présentes dans les packages dédiés du tidyverse. Les fonctions de stringr peuvent s’avérer très commode dans la sélection d’observations. Considérons les observations pour les communes qui ont la lettre z dans leur nom.

## Avec R-base
# Sélection des variables d'intérêt
pop_df <- adm3_pop_2009[ , c("admin3_nom", "homme", "femme")]
# Création d'une nouvelle variable: numérique
pop_df$total <- pop_df$femme + pop_df$homme
# Sélection des communes répondant au critère
detect_z <- grepl(pattern = "z", x = tolower(pop_df$admin3_nom))
# Mise en oeuvre de la sélection
pop_df[detect_z, ]
## # A tibble: 21 x 4
##    admin3_nom    homme femme total
##    <chr>         <dbl> <dbl> <dbl>
##  1 Zan Coulibaly  9235  9255 18490
##  2 Zegoua        16480 16638 33118
##  3 Zanfigue       7492  7747 15239
##  4 Zangasso       9391 10105 19496
##  5 Zanina         3619  3806  7425
##  6 Zebala         8293  8997 17290
##  7 Zantiebougou  17667 18100 35767
##  8 Kafouziela     3108  3304  6412
##  9 Sanzana        5479  5820 11299
## 10 Zanferebougou  2237  2416  4653
## # ... with 11 more rows
## Avec dplyr et stringr
# Chargement du package stringr
library(stringr)
  # Jeu de données de départ
adm3_pop_2009 %>% 
  # Sélection des variables d'intérêt
  select(admin3_nom, homme, femme) %>% 
  # Création d'une nouvelle variable
  mutate(total = homme + femme) %>% 
  # Sélection d'observations d'intérêt
  filter(str_detect(string = tolower(admin3_nom), pattern = "z"))
## # A tibble: 21 x 4
##    admin3_nom    homme femme total
##    <chr>         <dbl> <dbl> <dbl>
##  1 Zan Coulibaly  9235  9255 18490
##  2 Zegoua        16480 16638 33118
##  3 Zanfigue       7492  7747 15239
##  4 Zangasso       9391 10105 19496
##  5 Zanina         3619  3806  7425
##  6 Zebala         8293  8997 17290
##  7 Zantiebougou  17667 18100 35767
##  8 Kafouziela     3108  3304  6412
##  9 Sanzana        5479  5820 11299
## 10 Zanferebougou  2237  2416  4653
## # ... with 11 more rows

6.5.4 Sur la base d’index

Comme nous l’avons vu pour les variables, avec les observations aussi, la sélection peut se faire à partir de l’index.

Chercons à afficher les observations pour les 10 premières observations impaires.

## Avec R-base
# Sélection des variables d'intérêt
pop_df <- adm3_pop_2009[ , c("admin3_nom", "homme", "femme")]
# Création d'une nouvelle variable: numérique
pop_df$total <- pop_df$femme + pop_df$homme
# Mise en oeuvre de la sélection
pop_df[seq(from = 1, to = 19, by = 2), ]
## # A tibble: 10 x 4
##    admin3_nom           homme femme total
##    <chr>                <dbl> <dbl> <dbl>
##  1 Bangassi              6123  5974 12097
##  2 Diamou                7115  7015 14130
##  3 Faleme                5141  5017 10158
##  4 Gory Gopela           3939  3927  7866
##  5 Guidimakan Keri Kaff  9798 10234 20032
##  6 Karakoro              7436  7770 15206
##  7 Kemene Tambo          8381  8574 16955
##  8 Koniakary             4061  4080  8141
##  9 Koussane             10472 11118 21590
## 10 Logo                  6022  5967 11989
## Avec dplyr
  # Jeu de données de départ
adm3_pop_2009 %>% 
  # Sélection des variables d'intérêt
  select(admin3_nom, homme, femme) %>% 
  # Création d'une nouvelle variable
  mutate(total = homme + femme) %>% 
  # Sélection d'observations d'intérêt
  filter(row_number() %in% seq(from = 1, to = 19, by = 2))
## # A tibble: 10 x 4
##    admin3_nom           homme femme total
##    <chr>                <dbl> <dbl> <dbl>
##  1 Bangassi              6123  5974 12097
##  2 Diamou                7115  7015 14130
##  3 Faleme                5141  5017 10158
##  4 Gory Gopela           3939  3927  7866
##  5 Guidimakan Keri Kaff  9798 10234 20032
##  6 Karakoro              7436  7770 15206
##  7 Kemene Tambo          8381  8574 16955
##  8 Koniakary             4061  4080  8141
##  9 Koussane             10472 11118 21590
## 10 Logo                  6022  5967 11989

6.5.5 Filtres multiples

Dans le chapitre précédent, nous avons qu’en matière de sélections d’observations, il y a plusieurs façons de combiner des critères. On peut :

  • les ajouter avec le signe &;

  • les présenter comme des alternatives avec le signe |; ou

  • opérer avec une logique de négation avec le signe !.

Avec dplyr, ces signes demeurent valides.

Supposons que nous voulons connaître les communes de plus de 100000 où il y a plus de femmes que d’hommes. Ici, les deux critères s’accumulent.

## Avec R-base.
# Sélection des variables d'intérêt
pop_df <- adm3_pop_2009[ , c("admin3_nom", "homme", "femme")]
# Création d'une nouvelle variable: numérique
pop_df$total <- pop_df$femme + pop_df$homme
# Critère de sélection (1): valeurs logiques (TRUE/FALSE)
pop_100000_plus <- pop_df$total > 100000
# Critère de sélection (1): valeurs logiques (TRUE/FALSE)
femmes_sup_hommes <- pop_df$femme > pop_df$homme
# Mise en oeuvre de la sélection
pop_df[pop_100000_plus & femmes_sup_hommes, ]
## # A tibble: 4 x 4
##   admin3_nom     homme  femme  total
##   <chr>          <dbl>  <dbl>  <dbl>
## 1 Mopti Commune  60080  60706 120786
## 2 Commune II     78690  80670 159360
## 3 Commune III    63792  64874 128666
## 4 Commune IV    152153 152373 304526
## Avec dplyr
  # Jeu de données de départ
adm3_pop_2009 %>% 
  # Sélection des variables d'intérêt
  select(admin3_nom, homme, femme) %>% 
  # Création d'une nouvelle variable
  mutate(total = homme + femme) %>% 
  # Sélection d'observations d'intérêt
  filter(
    # Critère 1: population > 100000
    total > 100000, 
    # Critère 2: femme > homme
    femme > homme
    )
## # A tibble: 4 x 4
##   admin3_nom     homme  femme  total
##   <chr>          <dbl>  <dbl>  <dbl>
## 1 Mopti Commune  60080  60706 120786
## 2 Commune II     78690  80670 159360
## 3 Commune III    63792  64874 128666
## 4 Commune IV    152153 152373 304526

Ce sont quatre lignes qui répondent à nos critères.

Maintenant regardons ces mêmes critères, mais en termes d’alternatives. Les communes qui ont soit plus de 100000 habitants soit plus de femmes que d’hommes.

## Avec R-base.
# Sélection des variables d'intérêt
pop_df <- adm3_pop_2009[ , c("admin3_nom", "homme", "femme")]
# Création d'une nouvelle variable: numérique
pop_df$total <- pop_df$femme + pop_df$homme
# Critère de sélection (1): valeurs logiques (TRUE/FALSE)
pop_100000_plus <- pop_df$total > 100000
# Critère de sélection (1): valeurs logiques (TRUE/FALSE)
femmes_sup_hommes <- pop_df$femme > pop_df$homme
# Mise en oeuvre de la sélection
pop_df[pop_100000_plus | femmes_sup_hommes, ]
## # A tibble: 538 x 4
##    admin3_nom           homme femme  total
##    <chr>                <dbl> <dbl>  <dbl>
##  1 Colimbine             6144  6353  12497
##  2 Djelebou             11466 12091  23557
##  3 Guidimakan Keri Kaff  9798 10234  20032
##  4 Hawa Dembaya          3406  3445   6851
##  5 Karakoro              7436  7770  15206
##  6 Kayes Commune        65135 61184 126319
##  7 Kemene Tambo          8381  8574  16955
##  8 Koniakary             4061  4080   8141
##  9 Konsiga               2308  2620   4928
## 10 Koussane             10472 11118  21590
## # ... with 528 more rows
## Avec dplyr 
  # Jeu de données de départ
adm3_pop_2009 %>% 
  # Sélection des variables d'intérêt
  select(admin3_nom, homme, femme) %>% 
  # Création d'une nouvelle variable
  mutate(total = homme + femme) %>% 
  # Sélection d'observations d'intérêt
  filter(
    # Critère 1: population > 100000
    total > 100000 |
    # Critère 2: femme > homme
    femme > homme
    )
## # A tibble: 538 x 4
##    admin3_nom           homme femme  total
##    <chr>                <dbl> <dbl>  <dbl>
##  1 Colimbine             6144  6353  12497
##  2 Djelebou             11466 12091  23557
##  3 Guidimakan Keri Kaff  9798 10234  20032
##  4 Hawa Dembaya          3406  3445   6851
##  5 Karakoro              7436  7770  15206
##  6 Kayes Commune        65135 61184 126319
##  7 Kemene Tambo          8381  8574  16955
##  8 Koniakary             4061  4080   8141
##  9 Konsiga               2308  2620   4928
## 10 Koussane             10472 11118  21590
## # ... with 528 more rows

Pendant qu’avec R-base, le nombre d’objets intermédiaires continue d’augmenter, avec dplyr, nous nous contentons de l’opérateur %>% et de nouvelles lignes.

6.5.6 Tri d’observations: arrange

Souvent, il arrive qu’à la suite d’opération de sélections (aussi bien de variables que de colonnes) que l’on souhaite ordonner les résultats selon un ordre bien précis. Ceci peut servir souvent en matière d’affichage ou même servir de base pour des sélections.

Considérons qu’après avoir filtré pour ne garder que les communes qui ont plus de 100000 habitants et plus de femmes que d’hommes, que nous souhaitions ordonner la population.

## Avec R-base
# Sélection des variables d'intérêt
pop_df <- adm3_pop_2009[ , c("admin3_nom", "homme", "femme")]
# Création d'une nouvelle variable: numérique
pop_df$total <- pop_df$femme + pop_df$homme
# Critère de sélection (1): valeurs logiques (TRUE/FALSE)
pop_100000_plus <- pop_df$total > 100000
# Critère de sélection (1): valeurs logiques (TRUE/FALSE)
femmes_sup_hommes <- pop_df$femme > pop_df$homme
# Mise en oeuvre de la sélection
pop_df_filtre <- pop_df[pop_100000_plus | femmes_sup_hommes, ]
# Tri: ordre croissant
pop_decroissant <- order(pop_df_filtre$total)
# Mise en oeuvre du tri
pop_df_filtre[pop_decroissant, ]
## # A tibble: 538 x 4
##    admin3_nom            homme femme total
##    <chr>                 <dbl> <dbl> <dbl>
##  1 Adarmalane              463   492   955
##  2 Bassirou                825   893  1718
##  3 Arham                  1358  1461  2819
##  4 Soignebougou           1547  1552  3099
##  5 Ouro Modi              1566  1762  3328
##  6 Sokourani Missirikoro  1632  1740  3372
##  7 Diou                   1744  1760  3504
##  8 Kende                  1805  1921  3726
##  9 Somo                   1853  1891  3744
## 10 M'bouna                1894  1937  3831
## # ... with 528 more rows
# Tri: ordre décroissant
pop_decroissant <- order(pop_df_filtre$total, decreasing = TRUE)
# Mise en oeuvre du tri
pop_df_filtre[pop_decroissant, ]
## # A tibble: 538 x 4
##    admin3_nom        homme  femme  total
##    <chr>             <dbl>  <dbl>  <dbl>
##  1 Commune VI       237951 231702 469653
##  2 Commune V        206749 206517 413266
##  3 Commune I        168308 166587 334895
##  4 Commune IV       152153 152373 304526
##  5 Sikasso Commune  114171 112447 226618
##  6 Kalabancoro       81018  80864 161882
##  7 Commune II        78690  80670 159360
##  8 Koutiala Commune  70905  70539 141444
##  9 Segou Commune     66819  66682 133501
## 10 Commune III       63792  64874 128666
## # ... with 528 more rows
## Avec dplyr
  # Jeu de données de départ
adm3_pop_2009 %>% 
  # Sélection des variables d'intérêt
  select(admin3_nom, homme, femme) %>% 
  # Création d'une nouvelle variable
  mutate(total = homme + femme) %>% 
  # Sélection d'observations d'intérêt
  filter(
    # Critère 1: population > 100000
    total > 100000 |
    # Critère 2: femme > homme
    femme > homme
    ) %>% 
  # Tri: ordre décroissant
  arrange(desc(total))
## # A tibble: 538 x 4
##    admin3_nom        homme  femme  total
##    <chr>             <dbl>  <dbl>  <dbl>
##  1 Commune VI       237951 231702 469653
##  2 Commune V        206749 206517 413266
##  3 Commune I        168308 166587 334895
##  4 Commune IV       152153 152373 304526
##  5 Sikasso Commune  114171 112447 226618
##  6 Kalabancoro       81018  80864 161882
##  7 Commune II        78690  80670 159360
##  8 Koutiala Commune  70905  70539 141444
##  9 Segou Commune     66819  66682 133501
## 10 Commune III       63792  64874 128666
## # ... with 528 more rows

L’on peut agrémenter arrange avec une fonction qui spécifie le nombre d’observations à afficher ou à sauvegarder: top_n. Celle-ci peut opérer par le haut (les valeurs élevées)…

  # Jeu de données de départ
adm3_pop_2009 %>% 
  # Sélection des variables d'intérêt
  select(admin3_nom, homme, femme) %>% 
  # Création d'une nouvelle variable
  mutate(total = homme + femme) %>% 
  # Sélection d'observations d'intérêt
  filter(
    # Critère 1: population > 100000
    total > 100000 |
    # Critère 2: femme > homme
    femme > homme
    ) %>% 
  # Tri: décroissant
  arrange(total) %>%
  # Sélection des 5 premières observations
  top_n(n = 5, wt = total)
## # A tibble: 5 x 4
##   admin3_nom       homme  femme  total
##   <chr>            <dbl>  <dbl>  <dbl>
## 1 Sikasso Commune 114171 112447 226618
## 2 Commune IV      152153 152373 304526
## 3 Commune I       168308 166587 334895
## 4 Commune V       206749 206517 413266
## 5 Commune VI      237951 231702 469653

…ou par le bas (les valeurs faibles).

# Jeu de données de départ
adm3_pop_2009 %>% 
  # Sélection des variables d'intérêt
  select(admin3_nom, homme, femme) %>% 
  # Création d'une nouvelle variable
  mutate(total = homme + femme) %>% 
  # Sélection d'observations d'intérêt
  filter(
    # Critère 1: population > 100000
    total > 100000 |
    # Critère 2: femme > homme
    femme > homme
    ) %>% 
  # Tri: décroissant
  arrange(total) %>%
  # Sélection des 5 dernières observations
  top_n(n = -5, wt = total)
## # A tibble: 5 x 4
##   admin3_nom   homme femme total
##   <chr>        <dbl> <dbl> <dbl>
## 1 Adarmalane     463   492   955
## 2 Bassirou       825   893  1718
## 3 Arham         1358  1461  2819
## 4 Soignebougou  1547  1552  3099
## 5 Ouro Modi     1566  1762  3328

6.6 Vers l’agrégation: group_by et summarize

Jusque là, nous avons opéré en ajoutant ou enlevant des variables, en sélectionnant ou excluant des observations. Ces opérations ont toutes été intra-individuelles c’est-à-dire qu’à aucun moment il n’a été nécéssaire de mélanger les valeurs de deux ou plusieurs observations. Or, il arrive souvant que le data scientist ait besoin d’agréer des valeurs pour approfondir sa propre compréhension ou tout simplement synthétiser ses résultats. dplyr comptent deux fonctions sont pratiques pour ce faire. Il s’agit de group_by et summarize (summarise aussi marche). Elles viennent consolider les quatre que nous avons vues. La première group_by définit les groupes sur lesquels les opérations d’agrégation doivent être exécutées. Quant à summarize, elle explicite ces opérations. Illustrons pour mieux comprendre.

Supposons que l’on veuille agréger la population totale par région (admin1_nom) et ordonner celle-ci par ordre décroissant. Ceci reviendrait à faire la somme de la population totale en définissant admin1_nom comme variable de groupage.

## Avec R-base
# Sélection des variables d'intérêt
pop_df <- adm3_pop_2009[ , c("admin1_nom", "homme", "femme")]
# Création d'une nouvelle variable: numérique
pop_df$total <- pop_df$femme + pop_df$homme
# Opération d'agrégation
pop_df_adm1 <- aggregate(formula = total ~ admin1_nom, data = pop_df, FUN = sum)
# Tri: ordre décroissant
pop_decroissant <- order(pop_df_adm1$total, decreasing = TRUE)
# Mise en oeuvre du tri
pop_df_adm1[pop_decroissant, ]
##   admin1_nom   total
## 8    Sikasso 2644458
## 5 Koulikouro 2419212
## 7      Segou 2321651
## 6      Mopti 2038855
## 3      Kayes 2013076
## 1     Bamako 1810366
## 9 Tombouctou  671005
## 2        Gao  542304
## 4      Kidal   67739
## Avec dplyr
# Jeu de données de départ
adm3_pop_2009 %>% 
  # Création d'une nouvelle variable
  mutate(total = homme + femme) %>% 
  # Spécification du niveau d'agrégation
  group_by(admin1_nom) %>% 
  # Opération d'agrégation 
  summarize(population = sum(total)) %>% 
  # Tri: décroissant
  arrange(desc(population))
## # A tibble: 9 x 2
##   admin1_nom population
##   <chr>           <dbl>
## 1 Sikasso       2644458
## 2 Koulikouro    2419212
## 3 Segou         2321651
## 4 Mopti         2038855
## 5 Kayes         2013076
## 6 Bamako        1810366
## 7 Tombouctou     671005
## 8 Gao            542304
## 9 Kidal           67739

Et si voulions connaitre en même temps le nombre de communes par région? Nous ajoutons une opération supplémentaire à l’intérieur de summarize.

# Jeu de données de départ
adm3_pop_2009 %>% 
  # Création d'une nouvelle variable
  mutate(total = homme + femme) %>% 
  # Spécification du niveau d'agrégation
  group_by(admin1_nom) %>% 
  # Opération d'agrégation 
  summarize(
    # Population totale par région
    population = sum(total),
    # Nombre de communes par région
    nombre_communes = n()
    ) %>% 
  # Tri: décroissant
  arrange(desc(population))
## # A tibble: 9 x 3
##   admin1_nom population nombre_communes
##   <chr>           <dbl>           <int>
## 1 Sikasso       2644458             147
## 2 Koulikouro    2419212             108
## 3 Segou         2321651             118
## 4 Mopti         2038855             108
## 5 Kayes         2013076             129
## 6 Bamako        1810366               6
## 7 Tombouctou     671005              52
## 8 Gao            542304              24
## 9 Kidal           67739              11

Nous pouvons même ajouter la population moyenne par commune.

# Jeu de données de départ
adm3_pop_2009 %>% 
  # Création d'une nouvelle variable
  mutate(total = homme + femme) %>% 
  # Spécification du niveau d'agrégation
  group_by(admin1_nom) %>% 
  # Opération d'agrégation 
  summarize(
    # Population totale par région
    population = sum(total),
    # Nombre de communes par région
    nombre_communes = n()
    ) %>% 
  # Création d'une nouvelle variable %>% 
  mutate(pop_par_commune = population / nombre_communes) %>% 
  # Tri: décroissant
  arrange(desc(population))
## # A tibble: 9 x 4
##   admin1_nom population nombre_communes pop_par_commune
##   <chr>           <dbl>           <int>           <dbl>
## 1 Sikasso       2644458             147          17990.
## 2 Koulikouro    2419212             108          22400.
## 3 Segou         2321651             118          19675.
## 4 Mopti         2038855             108          18878.
## 5 Kayes         2013076             129          15605.
## 6 Bamako        1810366               6         301728.
## 7 Tombouctou     671005              52          12904.
## 8 Gao            542304              24          22596 
## 9 Kidal           67739              11           6158.

summarize acceptent la majorité des fonctions statistiques de R-base: sum pour la somme, mean pour la moyenne, sd pour l’écart-type, min pour le minimum, max pour le maximum, etc.

Il est utile de noter que, bien que les deux fonctions opèrent généralement en paire, elles ne sont pas toutefois obligées d’être ensemble…enfin, pas tout le temps.

Considérons par exemple que l’on veut agréger la population totale aussi bien pour les hommes que pour les femmes. Comme le groupe de référence est l’ensemble des observations (toutes les communes), l’on n’a pas besoin de group_by.

# Jeu de données de départ
adm3_pop_2009 %>% 
  # Création d'une nouvelle variable
  mutate(total = homme + femme) %>% 
  # Opérations d'agrégation 
  summarize(
    # Hommes
    homme = sum(homme),
    # Femmes
    femme = sum(femme),
    # Total
    total = sum(total)
    )
## # A tibble: 1 x 3
##     homme   femme    total
##     <dbl>   <dbl>    <dbl>
## 1 7204994 7323672 14528666

Là, nous avons utilisé summarize sans group_by. Maintenant, faisons l’inverse. Déterminons la part de chaque commune dans la population régionale. Et gardons seulement celles qui représentent plus de 5% de la population de leur région.

# Jeu de données de départ
adm3_pop_2009 %>% 
  # Création d'une nouvelle variable
  mutate(total = homme + femme) %>% 
  # Spécification du niveau d'agrégation
  group_by(admin1_nom) %>% 
  # Création d'une nouvelle variable 
  mutate(
    # Population au niveau de admin1_nom
    population_region = sum(total),
    # Ratio population de la commune / population de la région
    part_commune = total / population_region
    ) %>% 
  # Filtre: part > 5%
  filter(part_commune > 0.05) %>% 
  # Tri des résultats: ordre décroissant
  arrange(desc(part_commune)) %>% 
  # Sélection des variables d'intérêt
  select(contains("nom"), part_commune)
## # A tibble: 28 x 5
## # Groups:   admin1_nom [9]
##    admin0_nom admin1_nom admin2_nom admin3_nom      part_commune
##    <chr>      <chr>      <chr>      <chr>                  <dbl>
##  1 Mali       Kidal      Kidal      Kidal                 0.383 
##  2 Mali       Bamako     Bamako     Commune VI            0.259 
##  3 Mali       Bamako     Bamako     Commune V             0.228 
##  4 Mali       Bamako     Bamako     Commune I             0.185 
##  5 Mali       Bamako     Bamako     Commune IV            0.168 
##  6 Mali       Gao        Gao        Gao                   0.159 
##  7 Mali       Kidal      Tessalit   Adjelhoc              0.117 
##  8 Mali       Bamako     Bamako     Commune II            0.0880
##  9 Mali       Gao        Gao        Sony Aliber           0.0878
## 10 Mali       Sikasso    Sikasso    Sikasso Commune       0.0857
## # ... with 18 more rows

6.7 Conclusion

Nous venons de voir que dplyr est un outil très riche. Avec un vocabulaire simple et accessible, il met à la disposition du data scientist une panoplie d’outil qui facilite la manipulation de données.

Dans le prochain chapitre, nous allons explorer un autre package du tidyverse: tidyr.