Skip to Tutorial Content

Bienvenue

Dans cette étude de cas, vous allez explorer la popularité de votre propre prénom au fil du temps. En cours de route, vous maîtriserez certaines des fonctions les plus utiles pour isoler les variables, les observations et les valeurs d’un jeu de données :

  • select() et filter(), permettent de selectionner des colonnes et des lignes d’un jeu de données
  • arrange(), permet de réorganiser les lignes de vos données
  • |>, organise votre code en “pipes” (“flux” de traitement) faciles à lire

Ce module de cours utilise les packages de base du tidyverse, notamment {ggplot2}, {tibble} et {dplyr}, ainsi que le package {prenoms}. Tous ces packages ont été préinstallés et préchargés.

Cliquez sur le bouton “Suivant” pour commencer.

prenoms

La popularité d’un prénom au cours du temps

## `summarise()` has grouped output by 'name', 'year'. You can override using the
## `.groups` argument.
## `summarise()` has grouped output by 'year'. You can override using the
## `.groups` argument.

Nous avons au préalable modifié pour les besoins du cours les données de prenoms (comparé à celles disponibles dans le package) pour faciliter les tâches qui viennent. Voici maintenant le format des données prenoms (prop représente la proportion de bébés d’un sexe donné qui ont eu ce prénom cette année précise) :

## # A tibble: 264,296 × 5
##     year sex   name         n      prop
##    <int> <chr> <chr>    <int>     <dbl>
##  1  1900 M     Abel       378 0.00227  
##  2  1900 M     Abraham      8 0.0000480
##  3  1900 M     Achille    150 0.000900 
##  4  1900 M     Achilles     4 0.0000240
##  5  1900 M     Adam         9 0.0000540
##  6  1900 F     Adelaide   140 0.000629 
##  7  1900 F     Adelheid     3 0.0000135
##  8  1900 F     Adelina     25 0.000112 
##  9  1900 F     Adeline    168 0.000754 
## 10  1900 M     Adolphe    461 0.00277  
## # ℹ 264,286 more rows

Vous pouvez utiliser les données de prenoms pour créer des graphiques comme celui-ci, qui révèlent la popularité d’un prénom au cours du temps, peut-être votre prénom.

Avant d’afficher les informations à propos d’un autre prénom, vous devrez réduire prenoms. Pour le moment, il y a plus de lignes dans prenoms que vous n’en avez besoin pour construire un graphique à propos d’un seul prénom.

Exemple

Voyons la façon dont nous avons créé le graphique ci-dessus : nous avons commencé avec le jeu de données entier qui, si il était affiché sous la forme d’un nuage de points, aurait ressemblé à ceci :

Nous avons ensuite réduit les données aux seules lignes contenant le prénom “Margot” de sexe féminin, avant de tracer les données avec un graphique. Voici à quoi ressemblent les lignes avec ce prénom comme un nuage de points.

Si nous avions sauté cette étape, notre graphique linéaire aurait connecté tous les points du jeu de données entier, créant un graphique non informatif.

Votre objectif dans cette section est de répéter ce processus pour un autre prénom, par exemple le votre. En cours de route, vous apprendrez un ensemble de fonctions qui isolent les informations dans un jeu de données.

Isoler des données

Ce type de tâche se produit souvent en Data science : vous devez extraire les données d’une table avant de pouvoir l’utiliser. Vous pouvez effectuer cette tâche rapidement avec trois fonctions fournies dans le package {dplyr} :

  1. select() - qui selectionne des colonnes d’un jeu de données
  2. filter() - qui extrait des lignes d’un jeu de données
  3. arrange() - qui déplace les lignes importantes vers le haut d’un jeu de données

Chaque fonction prend un data.frame ou un tibble et renvoie un nouveau data.frame ou un tibble en sortie.

select()

select() selectionne les colonnes d’un jeu de données et retourne les colonnes comme un nouveau jeu de données. Pour utiliser select(), passez-lui le nom du jeu de données dont il faut extraire les colonnes, puis les noms des colonnes à extraire.

Aparté pour les déjà utilisateurs de R qui découvriraient le tidyverse : les noms de colonnes n’ont pas besoin d’apparaître entre guillemets ni d’être précédés par un $. En effet, select() sait les trouver dans le jeu de données que vous lui fournissez.

Exercice - select()

Utilisez l’exemple ci-dessous pour avoir une idée du fonctionnement de select(). Pouvez-vous sélectionner uniquement la colonne name ? Et comment extraire name et year ? Que diriez-vous de sélectionner toutes les colonnes sauf prop ?

select(prenoms, name, sex)
# A tibble: 264,296 × 2
   name     sex  
   <chr>    <chr>
 1 Abel     M    
 2 Abraham  M    
 3 Achille  M    
 4 Achilles M    
 5 Adam     M    
 6 Adelaide F    
 7 Adelheid F    
 8 Adelina  F    
 9 Adeline  F    
10 Adolphe  M    
# ℹ 264,286 more rows
select(prenoms, name)
select(prenoms, name, year)
select(prenoms, year, sex, name, n)

Outils de select()

Il existe également une série d’outils appelés “helpers” fournis avec select() et destinés à nous faciliter la vie. Par exemple, si vous placez un signe ‘-’ devant un nom de colonne, select() renverra toutes les colonnes sauf cette colonne. Pouvez-vous prédire comment le signe moins va fonctionner ici ?

select(prenoms, -year, -prop)

Le tableau ci-dessous résume les autres outils de select() disponibles dans {dplyr}. Étudiez-le, puis cliquez sur “Continue” pour tester votre compréhension.

Outil Utilisation Exemple
- Exclusion de colonnes select(prenoms, -sex)
: Sélection des colonnes entre 2 colonnes spécifiques (inclusive) select(prenoms, year:n)
contains() Sélection des colonnes qui contiennent une chaîne de caractère spécifique select(prenoms, contains("n"))
ends_with() Sélection des colonnes qui se terminent par une chaîne de caractère spécifique select(prenoms, ends_with("n"))
matches() Sélection des colonnes qui correspondent à une expression réguliere select(prenoms, matches("n"))
num_range() Sélection des colonnes avec un suffixe numérique dans l’étendue demandée Pas applicable à prenoms
one_of() Sélection des colonnes dont le nom apparaît dans l’ensemble demandé select(prenoms, one_of(c("sex", "name")))
starts_with() Sélection des colonnes qui commencent par une chaîne de caractère spécifique select(prenoms, starts_with("n"))

Quiz select()

filter()

filter() extrait les lignes d’un jeu de données et les renvoie comme un nouveau jeu de données. Comme avec select(), le premier argument de filter() doit être un jeu de données dont on souhaite extraire des lignes. Les arguments qui suivent doivent être des tests logiques : filter() renverra chaque ligne pour laquelle les tests renverront TRUE (c’est-à-dire pour lesquelles la condition que l’on teste est vérifiée).

filter() en action

Par exemple, le bloc de code ci-dessous renvoie chaque ligne avec le prénom “Annie” dans prenoms.

filter(prenoms, name == "Annie")
## # A tibble: 110 × 5
##     year sex   name      n       prop
##    <int> <chr> <chr> <int>      <dbl>
##  1  1903 F     Annie     1 0.00000406
##  2  1904 F     Annie     8 0.0000320 
##  3  1907 F     Annie     3 0.0000118 
##  4  1908 F     Annie     1 0.00000377
##  5  1909 F     Annie     4 0.0000151 
##  6  1910 F     Annie     3 0.0000112 
##  7  1911 F     Annie     7 0.0000274 
##  8  1913 F     Annie     6 0.0000222 
##  9  1914 F     Annie    15 0.0000564 
## 10  1915 F     Annie     7 0.0000416 
## # ℹ 100 more rows

Tests logiques

Pour tirer le meilleur parti du filtre, vous devrez savoir comment utiliser les opérateurs de test logique de R, qui sont résumés ci-dessous.

Opérateur logique Tests Exemple
> x est-il supérieur que y ? x > y
>= x est-il supérieur ou égal à y ? x >= y
< x est-il inférieur à y ? x < y
<= x est-il inférieur ou égale à y ? x <= y
== x est-il égal à y ? x == y
!= x est-il différent de y ? x != y
is.na() x est-il une information manquante NA ? is.na(x)
!is.na() x n’est pas une information manquante NA? !is.na(x)

Exercice - Opérateurs logiques

Voyez si vous pouvez utiliser les opérateurs logiques pour manipuler le code ci-dessous pour afficher :

  • Tous les prénoms pour lequels prop est supérieure ou égale à 0.08
  • Tous les enfants prénommés “Paulette”
  • Tous les prénoms qui ont une valeur manquante pour n (Astuce : cela devrait retourner un ensemble de données vide).
filter(prenoms, name == "Annie")
filter(prenoms, prop >= 0.08)
filter(prenoms, name == "Paulette")
filter(prenoms, is.na(n))

Deux erreurs courantes

Lorsque vous utilisez des tests logiques, il est une erreur très courante (même parmi les développeurs avertis). Elles apparaissent dans les blocs de code ci-dessous. Pouvez-vous les identifier ? Lorsque vous repérez une erreur, corrigez-la, puis exécutez le bloc pour confirmer que cela fonctionne comme attendu.

filter(prenoms, name = "Annie")
filter(prenoms, name == "Annie")
filter(prenoms, name == Annie)
filter(prenoms, name == "Annie")

Deux erreurs - Récapitulatif

Lorsque vous utilisez des tests logiques, veillez à rechercher ces deux erreurs courantes :

  1. utiliser = au lieu de == pour tester l’égalité
  2. oublier d’utiliser des guillemets lors de la comparaison de chaînes, par ex. name == Marie, au lieu dename == "Marie".

Combinaison de tests

Si vous fournissez plus d’un test à filter(), filter() combinera les tests avec une instruction et (&) : il ne renverra que les lignes qui satisfont tous les tests.

Pour combiner plusieurs tests d’une manière différente, utilisez les opérateurs booléens de R. Par exemple, le code ci-dessous renverra tous les enfants prénommés Julie ou Antoinette.

filter(prenoms, name == "Julie" | name == "Antoinette")
## # A tibble: 236 × 5
##     year sex   name           n    prop
##    <int> <chr> <chr>      <int>   <dbl>
##  1  1900 F     Antoinette  1514 0.00680
##  2  1900 F     Julie       1019 0.00458
##  3  1901 F     Antoinette  1735 0.00715
##  4  1901 F     Julie       1138 0.00469
##  5  1902 F     Antoinette  1698 0.00689
##  6  1902 F     Julie       1018 0.00413
##  7  1903 F     Antoinette  1673 0.00680
##  8  1903 F     Julie       1054 0.00428
##  9  1904 F     Antoinette  1638 0.00656
## 10  1904 F     Julie        918 0.00368
## # ℹ 226 more rows

Opérateurs booléens

Vous pouvez trouver une liste complète des opérateurs booléens de base de R dans le tableau ci-dessous.

Opérateur booléen Signification Exemple
& Est-ce que les conditionsA et B sont toutes les deux vraies ? A & B
| Est-ce que l’ une ou les deux conditions A et B sont vraies ? A | B
! Est-ce que A n’est pas vraie ? !A
xor() Est-ce que l’ une et uniquement une des conditions A et B est vraie ? xor(A, B)
%in% Est-ce que x est dans l’ensemble a, b, et c ? x %in% c(a, b, c)
any() Est-ce que l’une des conditions A, B, ou C est vraie ? any(A, B, C)
all() Est-ce que toutes les conditions A, B, ou C sont vraies ? all(A, B, C)

Exercice - Combinaison de tests

Utilisez les opérateurs booléens pour modifier le bloc de code ci-dessous pour renvoyer uniquement les lignes qui contiennent :

  • Les filles prénommées Agnès
  • Les prénoms qui ont été données à exactement 5 ou 6 enfants en 1900
  • Les prénoms Marie, Mariette ou Marine
filter(prenoms, name == "Julie" | name == "Antoinette")
# A tibble: 236 × 5
    year sex   name           n    prop
   <int> <chr> <chr>      <int>   <dbl>
 1  1900 F     Antoinette  1514 0.00680
 2  1900 F     Julie       1019 0.00458
 3  1901 F     Antoinette  1735 0.00715
 4  1901 F     Julie       1138 0.00469
 5  1902 F     Antoinette  1698 0.00689
 6  1902 F     Julie       1018 0.00413
 7  1903 F     Antoinette  1673 0.00680
 8  1903 F     Julie       1054 0.00428
 9  1904 F     Antoinette  1638 0.00656
10  1904 F     Julie        918 0.00368
# ℹ 226 more rows
filter(prenoms, name == "Agnès", sex == "F")
filter(prenoms, n == 5 | n == 6, year == 1900)
filter(prenoms, name %in% c("Marie", "Mariette", "Marine"))

Deux erreurs courantes supplémentaires

Les tests logiques peuvent également être liés à deux erreurs fréquentes que nous allons explorer. Chacune est affichée dans un bloc de code ci-dessous. L’un des codes génère une erreur et l’autre est inutilement verbeux. Diagnostiquez les problèmes, puis corrigez le code.

filter(prenoms, 10 < n < 20)
filter(prenoms, 10 < n, n < 20)
filter(prenoms, n == 5 | n == 6 | n == 7 | n == 8 | n == 9)
filter(prenoms, n %in% c(5, 6, 7, 8, 9))

Deux erreurs courantes supplémentaires - Récapitulatif

Lorsque vous combinez plusieurs tests logiques, veillez à rechercher ces deux erreurs courantes :

  1. Réduire plusieurs tests logiques en un seul test sans utiliser d’opérateur booléen
  2. Utilisation répétitive de | au lieu de %in%, par ex. x == 1 | x == 2 | x == 3 au lieu de x %in% c (1, 2, 3)

arrange()

arrange() renvoie toutes les lignes d’un jeu données réorganisées par les valeurs d’une colonne. Comme avec select(), le premier argument de arrange() doit être un jeu de données et les arguments restants sont les noms des colonnes. Si vous donnez à arrange() un seul nom de colonne, il renverra les lignes du jeu de données réorganisées de sorte que la ligne avec la valeur la plus basse dans cette colonne apparaisse en premier, la ligne avec la deuxième valeur la plus basse apparaisse en deuxième, et ainsi de suite. Si la colonne contient des chaînes de caractères, arrange() les placera par ordre alphabétique.

Exercice - arrange()

Utilisez le bloc de code ci-dessous pour organiser les prénoms en fonction de n. Pouvez-vous dire quelle est la plus petite valeur de n?

arrange(prenoms, n)

Gestion des ex-aequo

Si vous renseignez plusieurs noms de colonnes, arrange() les utilisera successivement pour réorganiser les lignes qui ont des valeurs identiques dans les colonnes précédentes. Complétez le code ci-dessous avec la colonne prop pour illustrer ce fonctionnement. Le résultat doit d’abord classer les lignes en fonction de la valeur de n, puis réorganiser les lignes de chaque valeur de n en fonction des valeurs de prop.

arrange(prenoms, n)
# A tibble: 264,296 × 5
    year sex   name        n       prop
   <int> <chr> <chr>   <int>      <dbl>
 1  1900 F     Aida        1 0.00000449
 2  1900 F     Arlette     1 0.00000449
 3  1900 M     Carlos      1 0.00000600
 4  1900 F     Dorothy     1 0.00000449
 5  1900 F     Ellen       1 0.00000449
 6  1900 M     Jacob       1 0.00000600
 7  1900 F     Liane       1 0.00000449
 8  1900 F     Mary        1 0.00000449
 9  1900 M     Nathan      1 0.00000600
10  1900 F     Sabine      1 0.00000449
# ℹ 264,286 more rows
arrange(prenoms, n, prop)

desc

Si vous préférez organiser les lignes dans l’ordre inverse, c’est-à-dire des valeurs les plus grandes aux valeurs les plus petites, entourez un nom de colonne avec la fonction desc(). arrange() réordonnera les lignes des plus grandes valeurs aux plus petites.

Ajoutez un desc() au code ci-dessous pour afficher le prénom le plus populaire pour la plus grande année du jeu de données au lieu de 1900 (la plus petite année du jeu de données).

arrange(prenoms, year, desc(prop))
# A tibble: 264,296 × 5
    year sex   name           n   prop
   <int> <chr> <chr>      <int>  <dbl>
 1  1900 F     Marie      48708 0.219 
 2  1900 M     Jean       14094 0.0846
 3  1900 F     Jeanne     13977 0.0628
 4  1900 M     Louis       9050 0.0543
 5  1900 M     Pierre      7451 0.0447
 6  1900 M     Joseph      7254 0.0435
 7  1900 M     Henri       6914 0.0415
 8  1900 M     Marcel      6531 0.0392
 9  1900 F     Marguerite  8054 0.0362
10  1900 M     Georges     5649 0.0339
# ℹ 264,286 more rows
arrange(prenoms, desc(year), desc(prop))

Vous pensez avoir compris ? Cliquez sur “Continue” pour tester vos acquis.

Quiz arrange()

Quel prénom était le plus populaire pour un seul sexe en une seule année ? Dans le bloc de code ci-dessous, utilisez arrange() pour faire apparaître la ligne avec la plus grande valeur de prop en haut du jeu de données.

arrange(prenoms, desc(prop))

Arrangez maintenant prenoms pour que la ligne avec la plus grande valeur de n apparaisse en haut du jeu de données. Est-ce que ce sera la même ligne d’après vous ?

arrange(prenoms, desc(n))

|>

Étapes

Remarquez comment chaque fonction de {dplyr} prend un jeu de données en entrée et renvoie un jeu de données en sortie. Cela rend les fonctions faciles à “brancher” les unes aux autres pour réaliser des suites d’étapes. Par exemple, vous pourriez :

  1. Filtrer les prénoms de bébé pour les garçons nés en 2018
  2. Sélectionner les colonnes name et n dans le résultat
  3. Organiser ces colonnes de sorte que les prénoms les plus populaires apparaissent en haut.
boys_2018 <- filter(prenoms, year == 2018, sex == "M")
boys_2018 <- select(boys_2018, name, n)
boys_2018 <- arrange(boys_2018, desc(n))
boys_2018
## # A tibble: 2,294 × 2
##    name        n
##    <chr>   <int>
##  1 Gabriel  5422
##  2 Raphaël  4604
##  3 Léo      4450
##  4 Louis    4410
##  5 Lucas    3979
##  6 Adam     3886
##  7 Arthur   3749
##  8 Jules    3697
##  9 Hugo     3689
## 10 Maël     3264
## # ℹ 2,284 more rows

Redondance

Le résultat nous montre les prénoms de garçons les plus populaires de 2018. Mais jetez un œil au code. Remarquez-vous comment nous recréons boys_2018 à chaque étape afin que nous ayons quelque chose à passer à l’étape suivante ?

Vous pouvez éviter de créer boys_2018 à chaque fois. Pour cela, une première stratégie consiste à imbriquer vos fonctions les unes dans les autres. Cependant, cela crée du code difficile à lire :

arrange(select(filter(prenoms, year == 2018, sex == "M"), name, n), desc(n))

Une autre façon d’écrire des séquences de fonctions est possible: le pipe |>. Le pipe peut être vu comme un flux, dans lequel nous réalisons une série d’opérations sur les données.

|>

L’opérateur pipe |> effectue la tâche suivante : il passe l’objet à gauche en premier argument de la fonction à droite. Ou en d’autres termes, x |> f(y) est identique à f(x, y). Cette manière d’écrire du code facilite l’écriture et la lecture d’une série de fonctions qui sont appliquées étape par étape. Par exemple, nous pouvons utiliser le pipe pour réécrire notre code ci-dessus :

prenoms |> 
  filter(year == 2018, sex == "M") |> 
  select(name, n) |> 
  arrange(desc(n))
## # A tibble: 2,294 × 2
##    name        n
##    <chr>   <int>
##  1 Gabriel  5422
##  2 Raphaël  4604
##  3 Léo      4450
##  4 Louis    4410
##  5 Lucas    3979
##  6 Adam     3886
##  7 Arthur   3749
##  8 Jules    3697
##  9 Hugo     3689
## 10 Maël     3264
## # ℹ 2,284 more rows

Lorsque vous lisez le code, prononcez |> comme “puis”. Si nous considérons que chaque nom de fonction est un verbe, notre code ressemble à la déclaration : “Prenez les prénoms, puis filtrez-les par année et par sexe, puis sélectionnez les colonnes name et n, puis organisez les résultats dans l’ordre descendant des valeurs de n.”

{dplyr} facilite également l’écriture des pipes. Chaque fonction de {dplyr} renvoie un jeu de données qui peut être utilisé dans une autre fonction de {dplyr} (qui acceptera alors le jeu de données comme premier argument). En fait, les fonctions de dplyr sont écrites pour permettre l’usage du pipe : chaque fonction fait une tâche simple, et {dplyr} s’attend à ce que vous utilisiez des pipes pour combiner ces tâches simples pour produire des résultats plus sophistiqués.

Exercice - Pipes

Nous utiliserons des pipes pour le reste du module. Pratiquons un peu en écrivant un nouveau pipe dans le code ci-dessous. Le flux de traitement doit être le suivant :

  1. Filtrer les prénoms de bébé uniquement pour les filles nées en 2018
  2. Sélectionner les colonnes name et n
  3. Organiser les résultats de manière à ce que les prénoms les plus populaires soient en haut dans le résultat.

Essayez d’écrire votre propre pipe, sans copier ni coller le code ci-dessus.

prenoms |> 
  filter(year == 2018, sex == "F") |> 
  select(name, n) |> 
  arrange(desc(n))

Tester un autre prénom

Vous maîtrisez maintenant un ensemble de compétences qui vont vous permettre de tracer facilement la popularité de n’importe quel prénom au fil du temps (pourquoi pas le votre ?). Dans le bloc de code ci-dessous, utilisez une combinaison de fonctions de {dplyr} et de {ggplot2} avec |> pour :

  1. Réduire prenoms aux seules lignes qui contiennent le prénom et le sexe que vous souhaitez étudier
  2. Réduire le résultat aux seules colonnes qui apparaîtront dans votre graphique (pas strictement nécessaire, mais pratique pour avoir une meilleure visibilité)
  3. Tracer les résultats sous la forme d’un graphique linéaire avec year sur l’axe des x et prop sur l’axe des y

Notez que le premier argument de ggplot() est un jeu de données. Cela signifie que vous pouvez ajouter ggplot() directement à la fin d’un pipe. Cependant, vous devrez passer de |> à + pour terminer l’ajout de couches à votre graphique.

prenoms |> 
  filter(name == "Louis", sex == "M") |> 
  select(year, prop) |> 
  ggplot() +
    aes(x = year, y = prop) +
    geom_line() +
    labs(title = "Popularité du prénom Louis")

Récapitulatif

Ensemble, select(), filter() et arrange() vous permettent de trouver rapidement les informations disponibles dans vos données.

Le module suivant vous montrera comment calculer des informations implicites dans vos données, mais non disponibles telles quelles dans le jeu de données.

Dans ce module, vous continuerez à utiliser l’opérateur |>, qui est une partie essentielle de la programmation dans le tidyverse. Dans le tidyverse, les fonctions sont comme des verbes : chacune accomplit une tâche simple. Vous pouvez combiner ces tâches en un flux de traitements avec |> pour effectuer des procédures complexes et personnalisées. C’est ainsi que les pipes contribuent à rendre R intelligible, comme une langue parlée. Les langues parlées sont en effet constituées de mots simples que vous combinez en phrases complexes pour créer des pensées sophistiquées.

Isoler des données avec {dplyr}