5 Tableaux de données
Ce chapitre s’appuie sur les Sections 2.2.2 Tableaux de données et 2.4.6 Tableaux de données des notes de cours.
Dans les chapitres Matrices et listes et Importation de données, vous avez appris à manipuler des matrices et à importer des données tabulaires dans R. Dans ce document, vous allez dans un premier temps utliser des techniques similaires à celles permettant de manipuler les matrices pour les appliquer à des tableaux que vous aurez importé depuis un fichier CSV dans R. Ensuite, vous apprendrez d’autres techniques proposées par l’environnement {tidyverse} pour manipuler des tableaux de données. Vous serez capable, une fois que vous aurez terminé de parcourir ce document, d’effectuer des opérations basiques de manipulation de tableau pour produire des statistiques descriptives.
5.1 Importation des données de la séance
Dans un premier temps, vous allez importer les données de notes des étudiant•es pour l’ensemble des matières, pour la première année (L1) et la deuxième année (L2). Ces données sont disponibles au format CSV, dans l’archive téléchargeable à l’adresse suivante : https://egallic.fr/Enseignement/R/Exercices/exercice_notes.zip.
- Créez un nouveau projet RStudio dans un dossier que nous intitulerez
TD_5
, au sein de votre espace étudiant sur les serveurs de l’Université. - Dans le répertoire
TD_5
, créez trois répertoires :Data
,Script
etOutput
. - Créez un script R que vous appellerez
notes.R
et enregistrez-le dans le répertoireScript
. - Téléchargez l’archive
exercice_notes.zip
en suivant le lien donné plus haut, et extrayez son contenu. - Placez les deux fichiers CSV (
notes_L1.csv
etnotes_L2.csv
) et le fichier de données R (moyennes.RData
) dans le répertoireData
.
L’arborescence de votre dossier de travaux dirigés pour cette séance doit être comme suit :
TD_5
├── notes.RProj
├── Data
│ └── notes_L1.csv
│ └── notes_L2.csv
│ └── moyennes.RData
├── Script
| └── notes.R
├── Output
- À présent, dans R, dans un objet que vous appellerez
notes_L1
, importez les données dans un tableau depuis le fichiernotes_L1.csv
. - Dans un objet que vous appellerez
notes_L2
, importez les données dans un tableau depuis le fichiernotes_L2.csv
.
En appelant les deux tableaux dans la console, vous devez voir les aperçus suivants :
## # A tibble: 224 × 5
## nom prenom id matiere note
## <chr> <chr> <dbl> <chr> <dbl>
## 1 Amsberry Evan 1 Microéconomie 1 11.5
## 2 Basurto Anthony 2 Microéconomie 1 9
## 3 Begaye Kai 3 Microéconomie 1 16.5
## 4 Brack Michael 4 Microéconomie 1 4
## 5 Burgess Jamie 5 Microéconomie 1 6.5
## 6 Christian Colton 6 Microéconomie 1 14.5
## 7 Cly Jesse 7 Microéconomie 1 2.5
## 8 Coberley Rebecca 8 Microéconomie 1 20
## 9 De Venecia Madison 9 Microéconomie 1 6
## 10 Gurule Elliott 12 Microéconomie 1 7.5
## # ℹ 214 more rows
## # A tibble: 217 × 5
## nom prenom id matiere note
## <chr> <chr> <dbl> <chr> <dbl>
## 1 Amsberry Evan 1 Microéconomie 2 5.5
## 2 Basurto Anthony 2 Microéconomie 2 5
## 3 Begaye Kai 3 Microéconomie 2 8.5
## 4 Brack Michael 4 Microéconomie 2 5
## 5 Burgess Jamie 5 Microéconomie 2 9
## 6 Christian Colton 6 Microéconomie 2 20
## 7 Coberley Rebecca 8 Microéconomie 2 15.5
## 8 De Venecia Madison 9 Microéconomie 2 5.5
## 9 Dewitt Amelia 10 Microéconomie 2 6.5
## 10 Eisenberg Kelly 11 Microéconomie 2 7
## # ℹ 207 more rows
5.2 Tibbles
Les tableaux de données sont traditionnellement des objets à deux dimensions, comme les matrices. Une dimension pour les colonnes, et une autre pour les lignes. En R, les tableaux de données pricipaux sont appelés data frames. Nous allons, dans le cadre de ce cours, utiliser majoritairement des tableaux de données de classe tbl_df
, une sous classe de data.frame
, que l’on nommera des tibbles. Il s’agit de la structure de données centrale dans l’environnement tidyverse. Pour pouvoir créer ou manipuler des tibbles, il est nécessaire de charger le package {tibble}. Ce package est automatiquement chargé lorsque vous chargez {tidyverse} :
Avant de manipuler les tableaux de données que vous venez d’importer, vous allez apprendre quelques notions élémentaires au sujet des tibbles. La fonction tibble()
permet de créer un tableau de données. On lui donne en arguments les colonnes, en les séparant par une virgule. Pour une facilité d’utilisation, il est préférable de nommer ces colonnes, en inscrivant simplement le nom suivi du symbole =
avant le contenu de la colonne :
tableau <- tibble(
x = c(1,2,3,4, 5),
y = c(10, 20, 30, 40, 50),
z = c("A","B","C","D", "E"),
t = x + y)
tableau
## # A tibble: 5 × 4
## x y z t
## <dbl> <dbl> <chr> <dbl>
## 1 1 10 A 11
## 2 2 20 B 22
## 3 3 30 C 33
## 4 4 40 D 44
## 5 5 50 E 55
Une colonne doit contenir des observations de même type. Comme vous l’avez vu dans le chapitre 2, les éléments d’un vecteur sont tous de même type. Aussi, dans l’exemple précédent, où chaque colonne est un vecteur, l’ensemble des éléments de chaque colonne est bien de même type (double pour x
, y
et t
, character pour z
).
Il est possible de donner des noms non conventionnels aux colonnes. En pratique, lorsque nous importons des données issues d’un fichier CSV, il n’est pas rare de faire face à des noms de colonnes non conventionnels (contenant des espaces par exemple, ou commençant par un nombre ou bien contenant des caractères spéciaux). Aussi, il est important de savoir comment faire face à cette situation : en utilisant des accents graves (`
, backtick) :
## # A tibble: 3 × 1
## `nom de colonne`
## <dbl>
## 1 1
## 2 2
## 3 3
5.2.1 Dimensions
Lors de l’affichage dans la console de l’aperçu d’un tableau de données, les premières colonnes, leur type, et leur contenu s’affichent. Les dimensions sont données dans la première ligne d’affichage :
## # A tibble: 5 × 4
## x y z t
## <dbl> <dbl> <chr> <dbl>
## 1 1 10 A 11
## 2 2 20 B 22
## 3 3 30 C 33
## 4 4 40 D 44
## 5 5 50 E 55
La première valeur correspond au nombre de lignes, tandis que la deuxième valeur correspond au nombre de colonnes. Pour accéder à ces valeurs, R propose la fonction dim()
, qui retourne les dimensions sous la forme d’un vecteur :
## [1] 5 4
On peut ensuite, comme expliqué dans le chapitre introductif accéder à une dimension spécifique avec la fonction crochet :
## [1] 5
## [1] 4
Il est également possible d’utiliser les fonctions nrow()
et ncol()
qui donnent le nombre de lignes (rows en anglais) et de colonnes (columns en anglais), respectivement :
## [1] 5
## [1] 4
5.2.2 Accès aux éléments
Pour accéder aux éléments d’un tibble, on peut utiliser les crochets simples ([]
) ou doubles ([[]]
), en utilisant l’indexation (par position, nom, ou condition). Avec les crochets simples, un tibble est retourné :
## # A tibble: 2 × 4
## x y z t
## <dbl> <dbl> <chr> <dbl>
## 1 1 10 A 11
## 2 3 30 C 33
## # A tibble: 5 × 2
## y t
## <dbl> <dbl>
## 1 10 11
## 2 20 22
## 3 30 33
## 4 40 44
## 5 50 55
## # A tibble: 5 × 2
## x t
## <dbl> <dbl>
## 1 1 11
## 2 2 22
## 3 3 33
## 4 4 44
## 5 5 55
Avec les crochets doubles, le contenu de la colonne que l’on souhaite extraire est retourné :
## [1] 10 20 30 40 50
## [1] "A" "B" "C" "D" "E"
Pour extraire le contenu d’une colonne, R propose aussi d’utiliser le dollar plutôt que les crochets doubles, pour une écriture plus compacte :
## [1] "A" "B" "C" "D" "E"
Exercice
- Affichez, à l’aide d’une fonction, le nombre de lignes du tableau
notes_L1
. - Idem avec le nombre de colonnes.
- Extrayez les valeurs de la colonne
note
du tableaunotes_L1
. - Sur un moteur de recherche, cherchez comment afficher les valeurs distinctes d’un vecteur, puis appliquez les fruits de votre recherche pour afficher les valeurs distinctes de la colonne
matiere
du tableaunotes_L1
. Stockez le résultat dans un objet que vous nommerezmatieres
. - Combien de matières différentes y a-t-il dans le tableau
notes_L1
? Utilisez le vecteurmatieres
et une fonction retournant le nombre d’éléments dans un vecteur pour répondre à cette question.
5.3 Résumés statistiques sur les colonnes d’un tableau
Des statistiques descriptives sur un vecteur peuvent facilement être obtenues à l’aide des fonctions suivantes :
- somme :
sum()
- moyenne :
mean()
- écart-type :
sd()
- min :
min()
- max :
max()
- médiane :
median()
- quantile quelconque :
quantile()
Il suffit de donner un vecteur de valeurs numériques à ces fonctions pour obtenir la statistique calculée sur la base de l’échantillon de valeurs fournies.
La moyenne et l’écart-type de la colonne x
du tableau tableau
:
## [1] 3
## [1] 1.581139
Attention, la fonction sd()
retourne la valeur de l’estimateur de l’écart-type d’une population : \(\frac{1}{n-1}\sum_{i=1}^{n} (x_i - \bar{x})^2\), où \(\bar{x} = \frac{1}{n}\sum_{i=1}^{n} x_i\).
## [1] 3
## [1] 2.5
## [1] 1.581139
Le minimum et le maximum :
## [1] 1
## [1] 5
La médiane :
## [1] 3
Pour d’autres quantiles que la médiane, on utilise la fonction quantile()
, en précisant le quantile à l’argument probs
:
## 25%
## 2
## 75%
## 4
## 90%
## 4.6
En cas de présence de valeurs manquantes (NA
), les fonctions sum()
mean()
, sd()
, min()
, etc. retournent la valeur NA
:
## [1] NA
Pour que la fonction soit appliquée en retirant au préalable du calcul les observations manquantes, on peut ajouter l’argument na.rm=TRUE
(avec rm
pour remove, c’est-à-dire retirer) :
## [1] 2.5
Exercice
- À partir du tableau
notes_L1
, calculez la moyenne et l’écart-type des valeurs dans la colonnenote
. - Extrayez le vecteur de notes du tableau
notes_L1
, et conservez uniquement les 32 premières valeurs (ce qui correspond aux notes de microéconomie), à l’aide des crochets. Calculez la moyenne en microéconomie, ainsi que les premier et troisième quartiles.
5.4 Sélection d’une ou plusieurs colonnes
La fonction select()
du package {dplyr} (qui est chargé lorsque {tiduverse} est chargé) permet de sélectionner une ou plusieurs colonnes. On donne un tableau de données comme premier argument à cette fonction. On indique ensuite la ou les noms des colonnes à conserver, en les séparant par une virgule. Admettons par exemple que l’on souhaite conserver uniquement les colonnes x
et z
de tableau
:
## # A tibble: 5 × 2
## x z
## <dbl> <chr>
## 1 1 A
## 2 2 B
## 3 3 C
## 4 4 D
## 5 5 E
Pour conserver l’ensemble des colonnes excepté certaines, il faut faire précéder le nom de ces colonnes que l’on souhaite ne pas conserver par le signe moins (-
) dans la fonction select
## # A tibble: 5 × 1
## x
## <dbl>
## 1 1
## 2 2
## 3 3
## 4 4
## 5 5
L’ordre dans lequel sont écrits les noms de colonnes lors de l’appel à la fonction select()
définit l’odre d’apparition des colonnes dans le résultat. Pour changer la position des colonnes d’un tibble, il existe une fonction dans {tidyverse} : relocate()
. Si on souhaite voir apparaître certaines colonnes sans se soucier de l’ordre d’autres colonnes, il suffit de nommer les colonnes à positionner dans les premières positions :
## # A tibble: 5 × 4
## z x y t
## <chr> <dbl> <dbl> <dbl>
## 1 A 1 10 11
## 2 B 2 20 22
## 3 C 3 30 33
## 4 D 4 40 44
## 5 E 5 50 55
Il est également possible de préciser que l’on désire placer une colonne avant ou après une autre colonne, en renseignant les arguments .before
ou .after
:
## # A tibble: 5 × 4
## x z y t
## <dbl> <chr> <dbl> <dbl>
## 1 1 A 10 11
## 2 2 B 20 22
## 3 3 C 30 33
## 4 4 D 40 44
## 5 5 E 50 55
Exercice
- À partir du tableau
notes_L1
, créez le tableaueleves
qui contiendra uniquement les colonnesnom
,prenom
etid
. - Appliquez la fonction
unique()
au tableaueleves
pour ne conserver dans le tableaueleves
que les enregistrements distincts (de sorte à avoir 1 ligne correspondant à une seule personne).
5.5 Création/Modification d’une nouvelle colonne
Le package {tidyverse} offre une fonction permettant de créer ou de modifier une colonne d’un tableau de données : mutate()
. Son premier argument est le tableau de données, le ou les arguments suivants correspondent aux colonnes à créer ou modifier.
Illustrons le fonctionnement de cette fonction en ramenant les notes de la colonne note
de tableau
sur 10 plutôt que sur 20. Appelons notes_10
la colonne contenant les résultats de la division par deux des valeurs de la colonne note
:
## # A tibble: 224 × 6
## nom prenom id matiere note notes_10
## <chr> <chr> <dbl> <chr> <dbl> <dbl>
## 1 Amsberry Evan 1 Microéconomie 1 11.5 5.75
## 2 Basurto Anthony 2 Microéconomie 1 9 4.5
## 3 Begaye Kai 3 Microéconomie 1 16.5 8.25
## 4 Brack Michael 4 Microéconomie 1 4 2
## 5 Burgess Jamie 5 Microéconomie 1 6.5 3.25
## 6 Christian Colton 6 Microéconomie 1 14.5 7.25
## 7 Cly Jesse 7 Microéconomie 1 2.5 1.25
## 8 Coberley Rebecca 8 Microéconomie 1 20 10
## 9 De Venecia Madison 9 Microéconomie 1 6 3
## 10 Gurule Elliott 12 Microéconomie 1 7.5 3.75
## # ℹ 214 more rows
Admettons à présent que l’on souhaite ajouter 1 point à l’ensemble des élèves :
Regardons les valeurs, en utilisant la fonction select()
pour éviter d’afficher toutes les colonnes :
## # A tibble: 224 × 4
## nom note notes_10 notes_10_augmentees
## <chr> <dbl> <dbl> <dbl>
## 1 Amsberry 11.5 5.75 6.75
## 2 Basurto 9 4.5 5.5
## 3 Begaye 16.5 8.25 9.25
## 4 Brack 4 2 3
## 5 Burgess 6.5 3.25 4.25
## 6 Christian 14.5 7.25 8.25
## 7 Cly 2.5 1.25 2.25
## 8 Coberley 20 10 11
## 9 De Venecia 6 3 4
## 10 Gurule 7.5 3.75 4.75
## # ℹ 214 more rows
Admettons que l’on souhaite ajouter 1 autre point à l’ensemble des élèves. Cette fois, nous allons modifier la colonne notes_10_augmentees
en récupérant la valeur déjà présente, puis en lui ajoutante la valeur 1.
Regardons à nouveau les valeurs, en utilisant la fonction select()
pour éviter d’afficher toutes les colonnes :
## # A tibble: 224 × 4
## nom note notes_10 notes_10_augmentees
## <chr> <dbl> <dbl> <dbl>
## 1 Amsberry 11.5 5.75 7.75
## 2 Basurto 9 4.5 6.5
## 3 Begaye 16.5 8.25 10.2
## 4 Brack 4 2 4
## 5 Burgess 6.5 3.25 5.25
## 6 Christian 14.5 7.25 9.25
## 7 Cly 2.5 1.25 3.25
## 8 Coberley 20 10 12
## 9 De Venecia 6 3 5
## 10 Gurule 7.5 3.75 5.75
## # ℹ 214 more rows
Ainsi, lorsque le nom de la colonne que l’on donne en argument de la fonction select()
est déjà présent dans le tableau donné en premier argument, la fonction select()
effectue une modification de cette colonne. Si le nom de colonne fait référence à une colonne qui n’existe pas dans le tableau, alors la fonction select()
créé une nouvelle colonne.
Ces opérations en plusieurs étapes peuvent se réaliser à l’aide d’une seule instruction :
notes_L1 <- mutate(notes_L1,
notes_10 = note / 2,
notes_10_augmentees = notes_10 + 1,
notes_10_augmentees = notes_10_augmentees + 1)
select(notes_L1, nom, note, notes_10, notes_10_augmentees)
## # A tibble: 224 × 4
## nom note notes_10 notes_10_augmentees
## <chr> <dbl> <dbl> <dbl>
## 1 Amsberry 11.5 5.75 7.75
## 2 Basurto 9 4.5 6.5
## 3 Begaye 16.5 8.25 10.2
## 4 Brack 4 2 4
## 5 Burgess 6.5 3.25 5.25
## 6 Christian 14.5 7.25 9.25
## 7 Cly 2.5 1.25 3.25
## 8 Coberley 20 10 12
## 9 De Venecia 6 3 5
## 10 Gurule 7.5 3.75 5.75
## # ℹ 214 more rows
Exercice
Dans le tableau notes_L1
, créez la colonne notes_100
qui contiendra les notes exprimées sur 100 points et non pas sur 20.
5.6 Renommer une colonne
Pour renommer une colonne, le package {dplyr} propose la fonction rename()
. Elle s’applique directement à un tableau de données et retourne un tableau de données. Il suffit d’indiquer le nouveau nom suivi du symbole égal (=
) puis de l’ancien nom. Lorsqu’un nom n’est pas conventionnel, on utilise l’accent grave (`
, backtick) pour entourer le nom :
notes_L1 <-
rename(notes_L1,
notes_dix = notes_10,
`notes 10 augmentees` = notes_10_augmentees)
notes_L1
## # A tibble: 224 × 7
## nom prenom id matiere note notes_dix `notes 10 augmentees`
## <chr> <chr> <dbl> <chr> <dbl> <dbl> <dbl>
## 1 Amsberry Evan 1 Microéconomie… 11.5 5.75 7.75
## 2 Basurto Anthony 2 Microéconomie… 9 4.5 6.5
## 3 Begaye Kai 3 Microéconomie… 16.5 8.25 10.2
## 4 Brack Michael 4 Microéconomie… 4 2 4
## 5 Burgess Jamie 5 Microéconomie… 6.5 3.25 5.25
## 6 Christian Colton 6 Microéconomie… 14.5 7.25 9.25
## 7 Cly Jesse 7 Microéconomie… 2.5 1.25 3.25
## 8 Coberley Rebecca 8 Microéconomie… 20 10 12
## 9 De Venecia Madison 9 Microéconomie… 6 3 5
## 10 Gurule Elliott 12 Microéconomie… 7.5 3.75 5.75
## # ℹ 214 more rows
5.7 Filtrage
Pour conserver uniquement les lignes d’un tableau qui remplissent les conditions d’un filtre, la fonction filter()
du package {dplyr} s’avère être très pratique. Cette fonction qui fait égalemnt partie de l’environnement {tidyverse}, s’applique directement à un tableau de données, et retourne un tableau de données comprenant les lignes pour lesquels le filtre retourne une valeur logique TRUE
.
Le premier argument de la fonction filter()
est le tableau de données. Les arguments suivants correspondent au(x) filtre(s) à appliquer. Par exemple, pour conserver uniquement les lignes du tableau notes_L1
pour lesquelles la note est inférieure à 10 :
## # A tibble: 148 × 7
## nom prenom id matiere note notes_dix `notes 10 augmentees`
## <chr> <chr> <dbl> <chr> <dbl> <dbl> <dbl>
## 1 Basurto Anthony 2 Microéconomie… 9 4.5 6.5
## 2 Brack Michael 4 Microéconomie… 4 2 4
## 3 Burgess Jamie 5 Microéconomie… 6.5 3.25 5.25
## 4 Cly Jesse 7 Microéconomie… 2.5 1.25 3.25
## 5 De Venecia Madison 9 Microéconomie… 6 3 5
## 6 Gurule Elliott 12 Microéconomie… 7.5 3.75 5.75
## 7 Israel Joshua 14 Microéconomie… 4 2 4
## 8 Jacket Kanae 15 Microéconomie… 6.5 3.25 5.25
## 9 Kinney Jonah 17 Microéconomie… 2 1 3
## 10 Ledbetter Conor 18 Microéconomie… 9 4.5 6.5
## # ℹ 138 more rows
Pour chaque ligne, le test logique consistant à regarder si la valeur de la colonne note
est strictement supérieure à 10 est réalisé. Si la valeur retournée est TRUE
, la ligne est retournée. Dans tous les autres cas, la ligne est retirée du résultat.
Des filtres plus complexes peuvent être réalisés, à l’aide des opérateurs logiques présentés dans la section portant sur l’indexation par condition (ET logique &
, OU logique |
, !
négation logique).
Par exemple, pour obtenir les lignes du tableau notes_L1
dont la valeur de la colonne note
est comprise dans l’intervalle \([10;12]\), on écrira :
## # A tibble: 32 × 7
## nom prenom id matiere note notes_dix `notes 10 augmentees`
## <chr> <chr> <dbl> <chr> <dbl> <dbl> <dbl>
## 1 Amsberry Evan 1 Microéc… 11.5 5.75 7.75
## 2 Medicine Blanket Robert 23 Microéc… 11 5.5 7.5
## 3 Thiede Tyler 33 Microéc… 10.5 5.25 7.25
## 4 Gurule Elliott 12 Macroéc… 12 6 8
## 5 Medicine Blanket Robert 23 Macroéc… 10.5 5.25 7.25
## 6 Pereyra Emilie 27 Macroéc… 11.5 5.75 7.75
## 7 Jacket Kanae 15 Mathéma… 11.5 5.75 7.75
## 8 Oyebi Rachael 26 Mathéma… 12 6 8
## 9 Joy Michael 16 Informa… 10 5 7
## 10 Kinney Jonah 17 Informa… 10 5 7
## # ℹ 22 more rows
Pour conserver les lignes pour lesquelles la valeur d’une colonne fait partie d’un ensemble de valeurs, on utilise l’opérateur %in%
. Par exemple, pour conserver les observations du tableau notes_L1
pour lesquelles le nom est "Amsberry"
ou "Basurto 1"
, on écrira :
## # A tibble: 14 × 7
## nom prenom id matiere note notes_dix `notes 10 augmentees`
## <chr> <chr> <dbl> <chr> <dbl> <dbl> <dbl>
## 1 Amsberry Evan 1 Microéconomie 1 11.5 5.75 7.75
## 2 Basurto Anthony 2 Microéconomie 1 9 4.5 6.5
## 3 Amsberry Evan 1 Macroéconomie 1 7.5 3.75 5.75
## 4 Basurto Anthony 2 Macroéconomie 1 4.5 2.25 4.25
## 5 Amsberry Evan 1 Mathématiques 1 5 2.5 4.5
## 6 Basurto Anthony 2 Mathématiques 1 6 3 5
## 7 Amsberry Evan 1 Informatique 1 5.5 2.75 4.75
## 8 Basurto Anthony 2 Informatique 1 3.5 1.75 3.75
## 9 Amsberry Evan 1 Statistiques 1 9 4.5 6.5
## 10 Basurto Anthony 2 Statistiques 1 4 2 4
## 11 Amsberry Evan 1 Anglais 1 4 2 4
## 12 Basurto Anthony 2 Anglais 1 5.5 2.75 4.75
## 13 Amsberry Evan 1 Economie enviro… 6 3 5
## 14 Basurto Anthony 2 Economie enviro… 12 6 8
Exercice
Filtrez le tableau
notes_L1
pour ne conserver que les lignes pour lesquelles la valeur de la colonnenote
est supérieure ou égale à 10.Filtrez le tableau
notes_L1
pour ne conserver que les lignes concernant la matière “Microéconomie 1”.Filtrez le tableau
notes_L1
pour ne conserver que les lignes pour lesquelles la valeur de la colonnematiere
est soitMicroéconomie 1
, soitMacroéconomie 1
. Stockez le résultat dans un objet que vous appellerezeco
.
5.8 Résumés statistiques sur l’ensemble du tableau
Nous avons vu précédemment que les fonctions mean()
, sum()
, sd()
, etc. permettent de calculer des statistiques sur des vecteurs de valeurs numériques. Il est possible d’appliquer ces mêmes fonctions à travers la fonction summarise()
sur les colonnes des tableaux de données, pour obtenir les mêmes statistiques. Le résultat sera retourné à l’intérieur d’un tableau de données.
Le premier argment de la fonction summarise
est le tableau de données sur lequel les résumés statistiques sont effectués. Les arguments suivants indiquent les fonctions à appliquer sur une colonne. Ces fonctions doivent retourner une valeur unique (ce qui est le cas des fonctions mean()
, sum
, sd()
, etc.). On indique d’abord le nom de la colonne qui contiendra la valeur calculée, puis la fonction à appliquer à une ou plusieurs colonnes du tableau. Par exemple, pour calculer la moyenne et l’écart-type des colonnes note
et notes 10 augmentees
, on écrira :
summarise(notes_L1,
moyenne = mean(note),
ecart_type = sd(note),
moyennes_aug = mean(`notes 10 augmentees`),
sd_aug = sd(`notes 10 augmentees`)
)
## # A tibble: 1 × 4
## moyenne ecart_type moyennes_aug sd_aug
## <dbl> <dbl> <dbl> <dbl>
## 1 8.52 4.75 6.26 2.37
La fonction summarise
a été utilisée sur l’ensemble du tableau notes_L1
. Nous avons fourni 4 opérations à éffectuer, le tableau retourné contient ainsi 4 colonnes correspondant aux résultats de ces opérations.
5.9 Agrégation par groupes
La colonne matiere
du tableau de données tableau
indique la matière dans lequel la note de l’élève est obtenue. Si l’on souhaite obtenir les moyennes de chaque matière, il est nécessaire de réaliser des agrégations par matière. Commençons par réaliser le calcul à la main.
Regardons les différentes matières :
## [1] "Microéconomie 1" "Macroéconomie 1"
## [3] "Mathématiques 1" "Informatique 1"
## [5] "Statistiques 1" "Anglais 1"
## [7] "Economie environnementale 1" "Finance 1"
Calculons la note moyenne dans le groupe pour la microéconomie :
micro <- filter(notes_L1, matiere == "Microéconomie 1")
moyenne_micro <- mean(micro$note)
moyenne_micro
## [1] 8.96875
Pour la macroéconomie :
macro <- filter(notes_L1, matiere == "Macroéconomie 1")
moyenne_macro <- mean(macro$note)
moyenne_macro
## [1] 8.484375
Bien qu’il soit possible de continuer, on se rend rapidement compte que ce calcul répétitif est pénible. Heureusement, {tidyverse} propose une combo de fonctions qui permet de grouper les observations d’un tableau dans un premier temps, puis d’appliquer une fonction à une ou plusieurs colonnes à chacun des sous groupes, et enfin de retourner le résultat. Ces fonctions sont les suivantes :
group_by()
: dans un premier temps, les données du tableau sont regroupées selon les modalités d’une ou de plusieurs colonnes. Il s’agit de créer des sous-groupes dans le tableau de données. Dans notre cas, nous allons effectuer le regroupement selon les valeurs prises par la colonnematiere
.summarise()
: dans un deuxième temps, pour chaque groupe, les observations des lignes sont agrégées, résumées.
Regroupons les observations de notes_L1
en fonction des valeurs de la colonne matière
(la microéconomie 1 avec la microéconomie 1, la macroéconomie 1 avec la macroéconomie 1, etc.) :
## # A tibble: 224 × 7
## # Groups: matiere [8]
## nom prenom id matiere note notes_dix `notes 10 augmentees`
## <chr> <chr> <dbl> <chr> <dbl> <dbl> <dbl>
## 1 Amsberry Evan 1 Microéconomie… 11.5 5.75 7.75
## 2 Basurto Anthony 2 Microéconomie… 9 4.5 6.5
## 3 Begaye Kai 3 Microéconomie… 16.5 8.25 10.2
## 4 Brack Michael 4 Microéconomie… 4 2 4
## 5 Burgess Jamie 5 Microéconomie… 6.5 3.25 5.25
## 6 Christian Colton 6 Microéconomie… 14.5 7.25 9.25
## 7 Cly Jesse 7 Microéconomie… 2.5 1.25 3.25
## 8 Coberley Rebecca 8 Microéconomie… 20 10 12
## 9 De Venecia Madison 9 Microéconomie… 6 3 5
## 10 Gurule Elliott 12 Microéconomie… 7.5 3.75 5.75
## # ℹ 214 more rows
On note dans la sortie précédente que cela correspond à 8 groupes (il y a en effet 8 valeurs distinctes dans la colonne matiere
du tableau de données).
Une fois les groupes désignés, il reste à effectuer le calcul de résumé (la moyenne des valeurs de la colonne note
) sur chacun des groupes, à l’aide de la fonction summarise()
.Le résultat du calcul sera donné dans une colonne que l’on pourra nommer, par exemple, moyenne
.
## # A tibble: 8 × 2
## matiere moyenne
## <chr> <dbl>
## 1 Anglais 1 7.11
## 2 Economie environnementale 1 8.56
## 3 Finance 1 8.75
## 4 Informatique 1 8.38
## 5 Macroéconomie 1 8.48
## 6 Mathématiques 1 9.05
## 7 Microéconomie 1 8.97
## 8 Statistiques 1 9
Pour éviter d’écrire les compositions de fonctions de manière condensée comme dans l’exemple précédent, le package {magrittr} propose un opérateur nommé “pipe”, dont la syntaxe est la suivante %>%
.
Cet opérateur fournit le résultat de l’évaluation de ce qui se trouve avant lui en premier argument de la fonction qui se situe immédiatement après.
Le code devient plus facile à lire :
- on part du tableau de données
notes_L1
; - ce tableau est donné en premier argument de la fonction
group_by()
; - le regroupement est fait selon la colonne
matiere
; - une fois le regroupement effectué, le résultat est donné comme premier argument de la fonction
summarise()
; - le calcul de la moyenne des valeurs de la colonne
note
est effectué pour chaque groupe du tableau de données, et le résultat est indiqué dans une colonne nomméemoyenne
.
Si on souhaite effectuer des regroupements en fonction des valeurs de plusieurs colonnes, il suffit d’ajouter les noms de colonnes dans la fonction group_by()
. La syntaxe est la suivante :
L’exercice qui suit vous permettra d’essayer un regroupement selon plusieurs colonnes.
Exercice
- Intéressez-vous aux résultats de Rebecca Coberley. Créez un tableau que vous appellerez
notes_coberley
qui contiendra les observations denotes_L1
concernant l’élève Rebecca Coberley (Note : vous devez créer ce nouveau tableau en manipulant le tableaunotes_L1
, pas en inscrivant à la main les valeurs). - Calculez la moyenne des notes de cette élève à partir du tableau
notes_coberley
. - À partir de
notes_L1
, calculez la moyenne générale de chaque élève. Pour ce faire :
- regroupez les valeurs par les colonnes
nom
,prenom
,id
- calculez la moyenne de la colonne
note
pour chaque sous-groupe.
- Retrouvez dans le tableau ainsi obtenu la moyenne de Rebecca Coberley
5.10 Tri
La fonction arrange()
du package {dplyr} permet d’ordonner les observations par valeurs croissantes ou décroissantes d’une ou de plusieurs colonnes. À nouveau, le premier argument attendu est un tableau de données, et le résultat est un tableau de données. Les arguments suivants sont les noms des colonnes sur lesquels effectuer le tri. Par défaut, le tri se fait par valeurs croissantes.
Par exemple, pour trier les valeurs par valeurs croissantes de la colonne notes
, on écrit simplement :
## # A tibble: 224 × 7
## nom prenom id matiere note notes_dix `notes 10 augmentees`
## <chr> <chr> <dbl> <chr> <dbl> <dbl> <dbl>
## 1 Lehi Savannah 19 Informatique… 1 0.5 2.5
## 2 Cly Jesse 7 Mathématique… 1.5 0.75 2.75
## 3 De Venecia Madison 9 Mathématique… 1.5 0.75 2.75
## 4 Brack Michael 4 Anglais 1 1.5 0.75 2.75
## 5 Lucero Cole 21 Economie env… 1.5 0.75 2.75
## 6 Brack Michael 4 Finance 1 1.5 0.75 2.75
## 7 Kinney Jonah 17 Microéconomi… 2 1 3
## 8 Cly Jesse 7 Macroéconomi… 2 1 3
## 9 Slovonsky Tevin 32 Informatique… 2 1 3
## 10 Thiede Tyler 33 Informatique… 2 1 3
## # ℹ 214 more rows
Pour trier par valeurs décroissantes, on applique la fonction desc()
sur le nom de la colonne, à l’intérieur de la fonction arrange
:
## # A tibble: 224 × 7
## nom prenom id matiere note notes_dix `notes 10 augmentees`
## <chr> <chr> <dbl> <chr> <dbl> <dbl> <dbl>
## 1 Coberley Rebecca 8 Microéc… 20 10 12
## 2 Joy Michael 16 Microéc… 20 10 12
## 3 Massey Taylor 22 Mathéma… 20 10 12
## 4 Medicine Blanket Robert 23 Mathéma… 20 10 12
## 5 Scholer Julia 31 Informa… 20 10 12
## 6 Riley Paige 28 Statist… 20 10 12
## 7 Rosen Richard 29 Anglais… 20 10 12
## 8 Rosen Richard 29 Economi… 20 10 12
## 9 Begaye Kai 3 Statist… 19 9.5 11.5
## 10 Scholer Julia 31 Statist… 19 9.5 11.5
## # ℹ 214 more rows
Lorsque une colonne utilisée pour faire un tri est une chaîne de caractères, l’ordre alphanumérique est utilisé :
## # A tibble: 224 × 7
## nom prenom id matiere note notes_dix `notes 10 augmentees`
## <chr> <chr> <dbl> <chr> <dbl> <dbl> <dbl>
## 1 Amsberry Evan 1 Microéconomie 1 11.5 5.75 7.75
## 2 Amsberry Evan 1 Macroéconomie 1 7.5 3.75 5.75
## 3 Amsberry Evan 1 Mathématiques 1 5 2.5 4.5
## 4 Amsberry Evan 1 Informatique 1 5.5 2.75 4.75
## 5 Amsberry Evan 1 Statistiques 1 9 4.5 6.5
## 6 Amsberry Evan 1 Anglais 1 4 2 4
## 7 Amsberry Evan 1 Economie enviro… 6 3 5
## 8 Basurto Anthony 2 Microéconomie 1 9 4.5 6.5
## 9 Basurto Anthony 2 Macroéconomie 1 4.5 2.25 4.25
## 10 Basurto Anthony 2 Mathématiques 1 6 3 5
## # ℹ 214 more rows
Selon l’ordre alphanumérique, les caractères spéciaux apparaissent en premier, suivis des valeurs numériques, puis par les lettres.
Pour trier par une colonne, puis par une autre, il suffit d’ajouter les noms des colonnes en arguments. L’ordre d’énumération définit l’ordre du tri. Par exemple, pour trier par valeurs croissantes des matières (colonne matiere
), puis, pour chaque matière, par valeurs décroissantes des notes (colonne note
) :
## # A tibble: 224 × 7
## nom prenom id matiere note notes_dix `notes 10 augmentees`
## <chr> <chr> <dbl> <chr> <dbl> <dbl> <dbl>
## 1 Rosen Richard 29 Anglais… 20 10 12
## 2 Joy Michael 16 Anglais… 13.5 6.75 8.75
## 3 Massey Taylor 22 Anglais… 13 6.5 8.5
## 4 Begaye Kai 3 Anglais… 11 5.5 7.5
## 5 Medicine Blanket Robert 23 Anglais… 10.5 5.25 7.25
## 6 Pereyra Emilie 27 Anglais… 10 5 7
## 7 Mullins Brenna 24 Anglais… 9.5 4.75 6.75
## 8 Slovonsky Tevin 32 Anglais… 9.5 4.75 6.75
## 9 Schlaver Lexa 30 Anglais… 9 4.5 6.5
## 10 Kinney Jonah 17 Anglais… 8.5 4.25 6.25
## # ℹ 214 more rows
Pour avoir une meilleure idée de ce qu’il se passe, regardons avec un plus petit tableau. Considérons le tableau suivant :
tableau <-
tibble(
numero_ligne_initial = c(1,2,3,4),
matiere = c("Microéconomie 1", "Anglais 1",
"Microéconomie 1", "Anglais 1"),
notes = c(20,18,15,5))
tableau
## # A tibble: 4 × 3
## numero_ligne_initial matiere notes
## <dbl> <chr> <dbl>
## 1 1 Microéconomie 1 20
## 2 2 Anglais 1 18
## 3 3 Microéconomie 1 15
## 4 4 Anglais 1 5
Si on ordonne uniquement par la colonne matiere
, par valeurs croissantes :
## # A tibble: 4 × 3
## numero_ligne_initial matiere notes
## <dbl> <chr> <dbl>
## 1 2 Anglais 1 18
## 2 4 Anglais 1 5
## 3 1 Microéconomie 1 20
## 4 3 Microéconomie 1 15
Les lignes où matiere
vaut "Anglais 1"
sont remontées avant celles où matiere
vaut "Microéconomie 1"
.
Si on veut, une fois ce tri effectué, trier par valeurs croissantes de notes
, en conservant les observations pour l’anglais avant celles de la microéconomie :
## # A tibble: 4 × 3
## numero_ligne_initial matiere notes
## <dbl> <chr> <dbl>
## 1 4 Anglais 1 5
## 2 2 Anglais 1 18
## 3 3 Microéconomie 1 15
## 4 1 Microéconomie 1 20
À votre tour.
- Trier le tableau
notes_L1
par valeurs décroissante des noms (colonnenom
) . - Trier le tableau
notes_L1
par valeurs croissante des matières (colonnematiere
) et valeurs croissante des noms (colonnenom
). - Affichez le top 3 des élèves par matière. Pour ce faire :
- regroupez les les observations par matiere (colonne
matiere
), - triez les observations par valeurs décroissantes des notes (colonne
note
), - utilisez la fonction
slice_head()
sur le tableau trié (et groupé) pour extraire uniquement les 3 premières observations de chaque groupe.
5.11 Jointures
Il n’est pas rare d’avoir deux tableaux de données qui disposent d’une ou de plusieurs colonnes communes, et qui peuvent être joints. Dans l’archive téléchargée au début de ce chapitre, vous avez extrait un fichier intitulé moyennes.RData
que vous avez placé dans le répertoire Data
de votre projet. Ce fichier contient deux tableaux de données :
moyennes_L1
: les moyennes à l’année de L1, sur 20, pour les élèves ;moyennes_L2
: les moyennes à l’année de L2, sur 20, pour les élèves.
Chargez dans R les données contenues dans le fichier moyennes.RData
La plupart des élèves de L1 sont aussi en L2 et vice-versa, mais certaines personnes étaient en L1 et n’ont pas été en L2, tandis que d’autres sont arrivées en L2 mais sont absentes du tableau concernant la L1.
Admettons que l’on souhaite mettre en commun les deux tableaux. Ils diposent tous deux d’une colonne indiquant les noms, une autre indiquant les prénoms, une autre indiquant l’identifiant, et enfin une dernière indiquant la moyenne annuelle. Cependant, le nom des colonnes de noms et prénoms diffère d’une année à l’autre : la colonne nom
du tableau moyennes_L1
s’appelle last_name
dans le tableau moyennes_L2
et la colonne prenom
dans moyennes_L1
est désignée par first_name
dans moyennes_L2
:
## # A tibble: 32 × 4
## nom prenom id moyenne_L1
## <chr> <chr> <dbl> <dbl>
## 1 Amsberry Evan 1 6.93
## 2 Basurto Anthony 2 6.36
## 3 Begaye Kai 3 13.4
## 4 Brack Michael 4 5
## 5 Burgess Jamie 5 9.36
## 6 Christian Colton 6 10.3
## 7 Cly Jesse 7 5.29
## 8 Coberley Rebecca 8 9.5
## 9 De Venecia Madison 9 4.07
## 10 Gurule Elliott 12 7.71
## # ℹ 22 more rows
## # A tibble: 31 × 4
## last_name first_name id moyenne_L2
## <chr> <chr> <dbl> <dbl>
## 1 Amsberry Evan 1 4.21
## 2 Basurto Anthony 2 8.21
## 3 Begaye Kai 3 15.6
## 4 Brack Michael 4 6.36
## 5 Burgess Jamie 5 9.21
## 6 Christian Colton 6 10.2
## 7 Coberley Rebecca 8 10.9
## 8 De Venecia Madison 9 5.79
## 9 Dewitt Amelia 10 6.93
## 10 Eisenberg Kelly 11 12.1
## # ℹ 21 more rows
Si l’on souhaite réaliser une jointure entre les deux tableaux, une multitude de fonctions sont disponibles. Elles partagent une syntaxe commune :
xx_join(x, y, by = NULL, copy = FALSE, ...)
,
où x
et y
sont les tableaux à joindre, by
est un vecteur de chaînes de caractères contenant les noms des variables permettant la jointure (si la valeur est NULL
– par défaut – la jointure se fera à l’aide des variables portant le même nom dans les deux tables).
Si la jointure s’effectue à l’aide de deux colonnes ou plus, on donner au paramètre by
de la fonction de jointure un vecteur comportant plusieurs éléments, chaque élément indiquant la correspondance entre les noms de colonnes dans les deux tableaux.
La syntaxe est la suivante, si la colonne nom_colonne_1_x
du tableau x
correspond à la colonne nom_colonne_1_y
du tableau y
, et si la colonne nom_colonne_2_x
du tableau x
correspond à la colonne nom_colonne_2_y
du tableau y
.
Pour illustrer les différentes jointures, travaillons sur un plus petit jeu de données. Vous aurez l’occasion de vous exercer sur le jeu complet par la suite.
moy_l1 <- tibble(
nom = c("Fuentes Gomez", "Kohyann", "Zagoury", "Souvestre"),
prenom = c("Sofia", "Hugo", "David", "Pierre"),
id = c(1, 2, 3, 4),
moyenne_L1 = c(12, 14, 12, 12),
groupe_TD = c("A", "B", "A", "A")
)
moy_l2 <- tibble(
last_name = c("Fuentes Gomez", "Kohyann", "Lang", "Souvestre"),
first_name = c("Sofia", "Hugo", "Lea", "Pierre"),
id = c(1, 2, 5, 4),
moyenne_L2 = c(12, 14, 16, 13),
groupe_TD = c("A", "A", "B", "B")
)
moy_l1
## # A tibble: 4 × 5
## nom prenom id moyenne_L1 groupe_TD
## <chr> <chr> <dbl> <dbl> <chr>
## 1 Fuentes Gomez Sofia 1 12 A
## 2 Kohyann Hugo 2 14 B
## 3 Zagoury David 3 12 A
## 4 Souvestre Pierre 4 12 A
## # A tibble: 4 × 5
## last_name first_name id moyenne_L2 groupe_TD
## <chr> <chr> <dbl> <dbl> <chr>
## 1 Fuentes Gomez Sofia 1 12 A
## 2 Kohyann Hugo 2 14 A
## 3 Lang Lea 5 16 B
## 4 Souvestre Pierre 4 13 B
Les différentes fonctions de jointure sont les suivantes :
inner_join()
: toutes les lignes dex
pour lesquelles il y a des valeurs correspondantes dansy
, et toutes les colonnes dex
ety
. S’il y a plusieurs correspondances dans les noms entrex
ety
, toutes les combinaisons possibles sont retournées ;
## # A tibble: 3 × 7
## nom prenom id moyenne_L1 groupe_TD.x moyenne_L2 groupe_TD.y
## <chr> <chr> <dbl> <dbl> <chr> <dbl> <chr>
## 1 Fuentes Gomez Sofia 1 12 A 12 A
## 2 Kohyann Hugo 2 14 B 14 A
## 3 Souvestre Pierre 4 12 A 13 B
La colonne id
est présente à la fois dans moy_l1
et dans moy_l2
. Il est donc possible de ne pas écrire "id" = "id"
dans le vecteur donné à l’argument by
. Nénamoins, ce n’est pas une obligation, nous pouvons très bien écrire l’instruction suivante et obtenir le même résultat que précédemment.
left_join()
: toutes les lignes dex
, et toutes les colonnes dex
ety
. Les lignes dansx
pour lesquelles il n’y a pas de correspondance dans y auront des valeursNA
dans les nouvelles colonnes. S’il y a plusieurs correspondances dans les noms entrex
ety
, toutes les combinaisons sont retournées ;
## # A tibble: 4 × 7
## nom prenom id moyenne_L1 groupe_TD.x moyenne_L2 groupe_TD.y
## <chr> <chr> <dbl> <dbl> <chr> <dbl> <chr>
## 1 Fuentes Gomez Sofia 1 12 A 12 A
## 2 Kohyann Hugo 2 14 B 14 A
## 3 Zagoury David 3 12 A NA <NA>
## 4 Souvestre Pierre 4 12 A 13 B
right_join()
: toutes les lignes dey
, et toutes les colonnes dex
ety
. Les lignes dansy
pour lesquelles il n’y a pas de correspondance dansx
auront des valeursNA
dans les nouvelles colonnes. S’il y a plusieurs correspondances dans les noms entrex
ety
, toutes les combinaisons sont retournées ;
## # A tibble: 4 × 7
## nom prenom id moyenne_L1 groupe_TD.x moyenne_L2 groupe_TD.y
## <chr> <chr> <dbl> <dbl> <chr> <dbl> <chr>
## 1 Fuentes Gomez Sofia 1 12 A 12 A
## 2 Kohyann Hugo 2 14 B 14 A
## 3 Souvestre Pierre 4 12 A 13 B
## 4 Lang Lea 5 NA <NA> 16 B
semi_join()
: toutes les lignes dex
pour lesquelles il y a des valeurs correspondantes dansy
, en ne conservant uniquement les colonnes dex
;
## # A tibble: 3 × 5
## nom prenom id moyenne_L1 groupe_TD
## <chr> <chr> <dbl> <dbl> <chr>
## 1 Fuentes Gomez Sofia 1 12 A
## 2 Kohyann Hugo 2 14 B
## 3 Souvestre Pierre 4 12 A
anti_join()
: toutes les lignes dex
pour lesquelles il n’y a pas de correspondances dansy
, en ne conservant que les colonnes dex
.
## # A tibble: 1 × 5
## nom prenom id moyenne_L1 groupe_TD
## <chr> <chr> <dbl> <dbl> <chr>
## 1 Zagoury David 3 12 A
full_join()
: toutes les lignes et toutes les colonnes dex
et dey
. Les lignes dansx
pour lesquelles il n’y a pas de correspondance dansy
auront des valeursNA
dans les colonnes dey
. Les lignes dansy
pour lesquelles il n’y a pas de correspondance dansx
auront des valeursNA
dans les colonnes dex
. S’il y a plusieurs correspondances dans les noms entrex
ety
, toutes les combinaisons sont retournées ;
## # A tibble: 5 × 7
## nom prenom id moyenne_L1 groupe_TD.x moyenne_L2 groupe_TD.y
## <chr> <chr> <dbl> <dbl> <chr> <dbl> <chr>
## 1 Fuentes Gomez Sofia 1 12 A 12 A
## 2 Kohyann Hugo 2 14 B 14 A
## 3 Zagoury David 3 12 A NA <NA>
## 4 Souvestre Pierre 4 12 A 13 B
## 5 Lang Lea 5 NA <NA> 16 B
Exercice
- À partir des tableaux
moyennes_L1
etmoyennes_L2
(qui sont importés dans R en chargeant le fichiermoyennes.RData
que vous avez placé dans le répertoireData
de votre projet), effectuez une jointure permettant d’avoir dans un même tableau l’ensemble des élèves (ayant suivi ou non les deux années) et leur moyenne en L1 et en L2. - Identifiez à l’aide d’une jointure des tableaux
moyennes_L1
etmoyennes_L2
les élèves présents en L1 mais pas en L2. - Identifiez à l’aide d’une jointure des tableaux
moyennes_L1
etmoyennes_L2
les élèves présents en L2 mais pas en L1.