Analyse de données d'enquêtes avec R
Thèmes abordés
Analyse de données d'enquêtes avec R
Thèmes abordés
Joseph Larmarange
21 février 2024
Table des matières
Préface 15
Remerciements . . . . . . . . . . . . . . . . . . . . . . 17
Licence . . . . . . . . . . . . . . . . . . . . . . . . . . 17
I Bases du langage 18
1 Packages 19
1.1 Installation (CRAN) . . . . . . . . . . . . . . . . 20
1.2 Chargement . . . . . . . . . . . . . . . . . . . . . 20
1.3 Mise à jour . . . . . . . . . . . . . . . . . . . . . 21
1.4 Installation depuis GitHub . . . . . . . . . . . . . 22
1.5 Le tidyverse . . . . . . . . . . . . . . . . . . . . . 23
2 Vecteurs 26
2.1 Types et classes . . . . . . . . . . . . . . . . . . . 26
2.2 Création d’un vecteur . . . . . . . . . . . . . . . 27
2.3 Longueur d’un vecteur . . . . . . . . . . . . . . . 30
2.4 Combiner des vecteurs . . . . . . . . . . . . . . . 31
2.5 Vecteurs nommés . . . . . . . . . . . . . . . . . . 31
2.6 Indexation par position . . . . . . . . . . . . . . 33
2.7 Indexation par nom . . . . . . . . . . . . . . . . 34
2.8 Indexation par condition . . . . . . . . . . . . . . 35
2.9 Assignation par indexation . . . . . . . . . . . . 39
2.10 En résumé . . . . . . . . . . . . . . . . . . . . . . 40
2.11 webin-R . . . . . . . . . . . . . . . . . . . . . . . 41
3 Listes 42
3.1 Propriétés et création . . . . . . . . . . . . . . . 42
3.2 Indexation . . . . . . . . . . . . . . . . . . . . . . 45
3.3 En résumé . . . . . . . . . . . . . . . . . . . . . . 49
3.4 webin-R . . . . . . . . . . . . . . . . . . . . . . . 49
2
4 Tableaux de données 50
4.1 Propriétés et création . . . . . . . . . . . . . . . 50
4.2 Indexation . . . . . . . . . . . . . . . . . . . . . . 52
4.3 Afficher les données . . . . . . . . . . . . . . . . . 56
4.4 En résumé . . . . . . . . . . . . . . . . . . . . . . 65
4.5 webin-R . . . . . . . . . . . . . . . . . . . . . . . 65
5 Tibbles 66
5.1 Le concept de tidy data . . . . . . . . . . . . . . 66
5.2 tibbles : des tableaux de données améliorés . . . 66
5.3 Données et tableaux imbriqués . . . . . . . . . . 71
6 Attributs 74
II Manipulation de données 77
7 Le pipe 78
7.1 Le pipe natif de R : |> . . . . . . . . . . . . . . . 79
7.2 Le pipe du tidyverse : %>% . . . . . . . . . . . . . 80
7.3 Vaut-il mieux utiliser |> ou %>% ? . . . . . . . . . 81
7.4 Accéder à un élément avec purrr::pluck() et
purrr::chuck() . . . . . . . . . . . . . . . . . . 82
8 dplyr 85
8.1 Opérations sur les lignes . . . . . . . . . . . . . . 86
8.1.1 filter() . . . . . . . . . . . . . . . . . . . . 86
8.1.2 slice() . . . . . . . . . . . . . . . . . . . . 91
8.1.3 arrange() . . . . . . . . . . . . . . . . . . 92
8.1.4 slice_sample() . . . . . . . . . . . . . . . 94
8.1.5 distinct() . . . . . . . . . . . . . . . . . . 95
8.2 Opérations sur les colonnes . . . . . . . . . . . . 97
8.2.1 select() . . . . . . . . . . . . . . . . . . . 97
8.2.2 relocate() . . . . . . . . . . . . . . . . . . 102
8.2.3 rename() . . . . . . . . . . . . . . . . . . 103
8.2.4 rename_with() . . . . . . . . . . . . . . . 104
8.2.5 pull() . . . . . . . . . . . . . . . . . . . . 105
8.2.6 mutate() . . . . . . . . . . . . . . . . . . . 105
8.3 Opérations groupées . . . . . . . . . . . . . . . . 106
8.3.1 group_by() . . . . . . . . . . . . . . . . . 106
8.3.2 summarise() . . . . . . . . . . . . . . . . . 111
8.3.3 count() . . . . . . . . . . . . . . . . . . . 113
3
8.3.4 Grouper selon plusieurs variables . . . . . 114
8.4 Cheatsheet . . . . . . . . . . . . . . . . . . . . . 119
8.5 webin-R . . . . . . . . . . . . . . . . . . . . . . . 119
4
13.2.3 Conversion . . . . . . . . . . . . . . . . . 184
5
16.3 Palettes de couleurs . . . . . . . . . . . . . . . . 211
16.3.1 Color Brewer . . . . . . . . . . . . . . . . 211
16.3.2 Palettes de Paul Tol . . . . . . . . . . . . 213
16.3.3 Interface unifiée avec {paletteer} . . . . 215
6
19 Statistique bivariée & Tests de comparaison 275
19.1 Deux variables catégorielles . . . . . . . . . . . . 275
19.1.1 Tableau croisé avec gtsummary . . . . . . 275
19.1.2 Représentations graphiques . . . . . . . . 278
19.1.3 Calcul manuel . . . . . . . . . . . . . . . 285
19.1.4 Test du Chi² et dérivés . . . . . . . . . . . 288
19.1.5 Comparaison de deux proportions . . . . 290
19.2 Une variable continue selon une variable catégo-
rielle . . . . . . . . . . . . . . . . . . . . . . . . . 294
19.2.1 Tableau comparatif avec gtsummary . . . 294
19.2.2 Représentations graphiques . . . . . . . . 296
19.2.3 Calcul manuel . . . . . . . . . . . . . . . 302
19.2.4 Tests de comparaison . . . . . . . . . . . 303
19.2.5 Différence de deux moyennes . . . . . . . 306
19.3 Deux variables continues . . . . . . . . . . . . . . 307
19.3.1 Représentations graphiques . . . . . . . . 307
19.3.2 Tester la relation entre les deux variables 314
19.4 Matrice de corrélations . . . . . . . . . . . . . . . 315
19.5 webin-R . . . . . . . . . . . . . . . . . . . . . . . 317
7
22.9 Régressions logistiques univariées . . . . . . . . . 365
22.10Présenter l’ensemble des résultats dans un même
tableau . . . . . . . . . . . . . . . . . . . . . . . 367
22.11webin-R . . . . . . . . . . . . . . . . . . . . . . . 369
8
25.2 Contrastes de type somme . . . . . . . . . . . . . 444
25.2.1 Exemple 1 : un modèle linéaire avec une
variable catégorielle . . . . . . . . . . . . 444
25.2.2 Exemple 2 : une régression logistique avec
deux variables catégorielles . . . . . . . . 448
25.3 Contrastes par différences successives . . . . . . . 450
25.3.1 Exemple 1 : un modèle linéaire avec une
variable catégorielle . . . . . . . . . . . . 451
25.3.2 Exemple 2 : une régression logistique avec
deux variables catégorielles . . . . . . . . 452
25.4 Autres types de contrastes . . . . . . . . . . . . . 455
25.4.1 Contrastes de type Helmert . . . . . . . . 455
25.4.2 Contrastes polynomiaux . . . . . . . . . . 457
25.5 Lectures additionnelles . . . . . . . . . . . . . . . 458
26 Interactions 459
26.1 Données d’illustration . . . . . . . . . . . . . . . 459
26.2 Modèle sans interaction . . . . . . . . . . . . . . 460
26.3 Définition d’une interaction . . . . . . . . . . . . 462
26.4 Significativité de l’interaction . . . . . . . . . . . 464
26.5 Interprétation des coefficients . . . . . . . . . . . 466
26.6 Définition alternative de l’interaction . . . . . . . 471
26.7 Identifier les interactions pertinentes . . . . . . . 475
26.8 Pour aller plus loin . . . . . . . . . . . . . . . . . 477
26.9 webin-R . . . . . . . . . . . . . . . . . . . . . . . 478
27 Multicolinéarité 479
27.1 Définition . . . . . . . . . . . . . . . . . . . . . . 479
27.2 Mesure de la colinéarité . . . . . . . . . . . . . . 481
27.3 La multicolinéarité est-elle toujours un problème ?487
27.4 webin-R . . . . . . . . . . . . . . . . . . . . . . . 489
9
29 Manipulation de données pondérées 502
29.1 Utilisation de {srvyr} . . . . . . . . . . . . . . . 503
29.2 Lister / Rechercher des variables . . . . . . . . . 505
29.3 Extraire un sous-échantillon . . . . . . . . . . . . 506
10
34.3 Durées, périodes, intervalles & Arithmétique . . . 567
34.3.1 Durées (Duration) . . . . . . . . . . . . . 567
34.3.2 Périodes (Period) . . . . . . . . . . . . . . 570
34.3.3 Intervalles (Interval) . . . . . . . . . . . . 573
34.4 Calcul d’un âge . . . . . . . . . . . . . . . . . . . 576
34.5 Fuseaux horaires . . . . . . . . . . . . . . . . . . 577
34.6 Pour aller plus loin . . . . . . . . . . . . . . . . . 580
11
37 Conditions logiques 615
37.1 Opérateurs de comparaison . . . . . . . . . . . . 615
37.2 Comparaison et valeurs manquantes . . . . . . . 618
37.3 Opérateurs logiques (algèbre booléenne) . . . . . 620
37.3.1 Opérations logiques et Valeurs manquantes622
37.3.2 L’opérateur %in% . . . . . . . . . . . . . . 623
37.4 Aggrégation . . . . . . . . . . . . . . . . . . . . . 623
37.5 Programmation . . . . . . . . . . . . . . . . . . . 624
12
39.6 Lectures additionnelles . . . . . . . . . . . . . . . 668
13
43 Modèles de comptage (Poisson & apparentés) 736
43.1 Modèle de Poisson . . . . . . . . . . . . . . . . . 736
43.1.1 Préparation des données du premier
exemple . . . . . . . . . . . . . . . . . . . 737
43.1.2 Calcul & Interprétation du modèle de
Poisson . . . . . . . . . . . . . . . . . . . 739
43.1.3 Évaluation de la surdispersion . . . . . . . 743
43.2 Modèle de quasi-Poisson . . . . . . . . . . . . . . 747
43.3 Modèle binomial négatif . . . . . . . . . . . . . . 750
43.4 Exemple avec une plus grande surdispersion . . . 754
43.5 Modèles de comptage avec une variable binaire . 758
43.6 Données pondérées et plan d’échantillonnage . . 766
43.7 Lectures complémentaires . . . . . . . . . . . . . 768
14
Préface
15
de ces dernières, bien qu’un peu ardue de prime abord, permet
de comprendre le sens des commandes que l’on utilise et de
pleinement exploiter la puissance que R offre en matière de
manipulation de données.
R disposent de nombreuses extensions ou packages (plus de
16 000) et il existe souvent plusieurs manières de procéder pour
arriver au même résultat. En particulier, en matière de mani-
pulation de données, on oppose1 souvent base R qui repose sur 1
Une comparaison des deux syntaxes
les fonctions disponibles en standard dans R, la majorité étant est illustrée par une vignette dédiée
de dplyr.
fournies dans les packages {base}, {utils} ou encore {stats},
qui sont toujours chargés par défaut, et le {tidyverse} qui est
une collection de packages comprenant, entre autres, {dplyr},
{tibble}, {tidyr}, {forcats} ou encore {ggplot2}. Il y a un
débat ouvert, parfois passionné, sur le fait de privilégier l’une ou
l’autre approche, et les avantages et inconvénients de chacune
dépendent de nombreux facteurs, comme la lisibilité du code ou
bien les performances en temps de calcul. Dans ce guide, nous
avons adopté un point de vue pragmatique et utiliserons, le plus
souvent mais pas exclusivement, les fonctions du {tidyverse},
de même que nous avons privilégié d’autres packages, comme
{gtsummary} ou {ggstats} par exemple pour la statistique des-
criptive. Cela ne signifie pas, pour chaque point abordé, qu’il
s’agit de l’unique manière de procéder. Dans certains cas, il
s’agit simplement de préférences personnelles.
Bien qu’il en reprenne de nombreux contenus, ce guide ne se
substitue pas au site analyse-R. Il s’agit plutôt d’une version
complémentaire qui a vocation à être plus structurée et parfois
plus sélective dans les contenus présentés.
En complément, on pourra également se référer aux webin-R,
une série de vidéos avec partage d’écran, librement accessibles
sur YouTube : [Link]
Cette version du guide a utilisé r [Link]()[["[Link]"]].
Ce document est généré avec quarto et le code source est dis-
ponible sur GitHub. Pour toute suggestion ou correction, vous
pouvez ouvrir un ticket GitHub. Pour d’autres questions, vous
pouvez utiliser les forums de discussion disponibles en bas de
chaque page sur la version web du guide. Ce document est
régulièrement mis à jour. La dernière version est consultable
sur [Link]
16
Remerciements
Licence
17
partie I
Bases du langage
18
1 Packages
19
1.1 Installation (CRAN)
[Link]("gtsummary")
remotes::install_cran("gtsummary")
Ĺ Note
1.2 Chargement
library(gtsummary)
20
À partir de là, on peut utiliser les fonctions de l’extension,
consulter leur page d’aide en ligne, accéder aux jeux de don-
nées qu’elle contient, etc.
Alternativement, pour accéder à un objet ou une fonction d’un
package sans avoir à le charger en mémoire, on pourra avoir re-
cours à l’opérateur ::. Ainsi, l’écriture p::f() signifie la fonc-
tion f() du package p. Cette écriture sera notamment utilisée
tout au long de ce guide pour indiquer à quel package appar-
tient telle fonction : remotes::install_cran() indique que la
fonction install_cran() provient du packages {remotes}.
ĺ Important
[Link]()
[Link]("gtsummary")
21
Ď Installer / Mettre à jour les packages utilisés par un
projet
renv::dependencies() |>
purrr::pluck("Package") |>
unique() |>
remotes::install_cran()
22
Á Sous Windows
remotes::install_github("larmarange/labelled")
1.5 Le tidyverse
• visualisation ({ggplot2})
• manipulation des tableaux de données ({dplyr},
{tidyr})
• import/export de données ({readr}, {readxl}, {haven})
• manipulation de variables ({forcats}, {stringr},
{lubridate})
23
• programmation ({purrr}, {magrittr}, {glue})
[Link]("tidyverse")
24
Figure 1.1: Packages chargés avec library(tidyverse)
25
2 Vecteurs
26
La fonction class() renvoie la nature d’un vecteur tandis que
la fonction typeof() indique la manière dont un vecteur est
stocké de manière interne par R.
x class(x) typeof(x)
3L integer integer
5.3 numeric double
TRUE logical logical
"abc" character character
factor("a") factor integer
[Link]("2020-01-01") Date double
Ď Astuce
27
sexe <- c("h", "f", "h", "f", "f", "f")
sexe
Nous l’avons vu, toutes les valeurs d’un vecteur doivent obliga-
toirement être du même type. Dès lors, si on essaie de combiner
des valeurs de différents types, R essaiera de les convertir au
mieux. Par exemple :
class(x)
[1] "character"
rep(2, 10)
[1] 2 2 2 2 2 2 2 2 2 2
28
rep(c("a", "b"), 3)
seq(1, 10)
[1] 1 2 3 4 5 6 7 8 9 10
seq(5, 17, by = 2)
[1] 5 7 9 11 13 15 17
seq(10, 0)
[1] 10 9 8 7 6 5 4 3 2 1 0
[1] 100 90 80 70 60 50 40 30 20 10
[1] 1.23 1.56 1.89 2.22 2.55 2.88 3.21 3.54 3.87 4.20 4.53 4.86 5.19 5.52
29
1:5
[1] 1 2 3 4 5
24:32
[1] 24 25 26 27 28 29 30 31 32
55:43
[1] 55 54 53 52 51 50 49 48 47 46 45 44 43
length(taille)
[1] 6
length(c("a", "b"))
[1] 2
length(NULL)
[1] 0
30
2.4 Combiner des vecteurs
x <- c(2, 1, 3, 4)
length(x)
[1] 4
y <- c(9, 1, 2, 6, 3, 0)
length(y)
[1] 6
z <- c(x, y)
z
[1] 2 1 3 4 9 1 2 6 3 0
length(z)
[1] 10
sexe <- c(
Michel = "h", Anne = "f",
Dominique = NA, Jean = "h",
31
Claude = NA, Marie = "f"
)
sexe
names(sexe)
32
2.6 Indexation par position
taille
taille[1]
[1] 1.88
taille[1:3]
taille[c(2, 5, 6)]
33
taille[length(taille)]
[1] 1.72
taille[c(5, 1, 4, 3)]
taille[c(-1, -5)]
taille[23:25]
[1] NA NA NA
sexe["Anna"]
Anna
"f"
34
sexe[c("Mary", "Michael", "John")]
sexe[names(sexe) != "Dom"]
sexe
Michael John
"h" "h"
35
urbain <- c(TRUE, TRUE, FALSE, FALSE, FALSE, TRUE)
poids <- c(80, 63, 75, 87, 82, 67)
sexe[urbain]
poids >= 80
36
est remplie et FALSE dans les autres cas. Nous pouvons alors
utiliser ce vecteur logique pour obtenir la taille des participants
pesant 80 kilogrammes ou plus :
37
de cette condition n’est pas toujours TRUE ou FALSE, il
peut aussi être à son tour une valeur manquante.
taille
taille
poids
[1] 80 63 75 87 82 67
38
[1] 80 75 NA
[1] 80 75
v <- 1:5
v
[1] 1 2 3 4 5
v[1] <- 3
v
[1] 3 2 3 4 5
39
Enfin on peut modifier plusieurs éléments d’un seul coup soit en
fournissant un vecteur, soit en profitant du mécanisme de recy-
clage. Les deux commandes suivantes sont ainsi rigoureusement
équivalentes :
length(sexe)
[1] 6
length(sexe)
[1] 7
2.10 En résumé
40
• Les valeurs manquantes sont représentées avec NA.
• Un vecteur peut être nommé, c’est-à-dire qu’un nom tex-
tuel a été associé à chaque élément. Cela peut se faire lors
de sa création ou avec la fonction names().
• L’indexation consiste à extraire certains éléments d’un
vecteur. Pour cela, on indique ce qu’on souhaite extraire
entre crochets ([]) juste après le nom du vecteur. Le type
d’indexation dépend du type d’information transmise.
• S’il s’agit de nombres entiers, c’est l’indexation par posi-
tion : les nombres représentent la position dans le vecteur
des éléments qu’on souhaite extraire. Un nombre négatif
s’interprète comme tous les éléments sauf celui-là.
• Si on indique des chaînes de caractères, c’est l’indexation
par nom : on indique le nom des éléments qu’on souhaite
extraire. Cette forme d’indexation ne fonctionne que si le
vecteur est nommé.
• Si on transmet des valeurs logiques, le plus souvent sous
la forme d’une condition, c’est l’indexation par condition :
TRUE indique les éléments à extraire et FALSE les éléments
à exclure. Il faut être vigilant aux valeurs manquantes (NA)
dans ce cas précis.
• Enfin, il est possible de ne modifier que certains éléments
d’un vecteur en ayant recours à la fois à l’indexation ([])
et à l’assignation (<-).
2.11 webin-R
41
3 Listes
[[1]]
[1] 1 2 3 4 5
[[2]]
[1] "abc"
length(l1)
[1] 2
42
Comme les vecteurs, une liste peut être nommée et les noms
des éléments d’une liste sont accessibles avec names() :
l2 <- list(
minuscules = letters,
majuscules = LETTERS,
mois = [Link]
)
l2
$minuscules
[1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s"
[20] "t" "u" "v" "w" "x" "y" "z"
$majuscules
[1] "A" "B" "C" "D" "E" "F" "G" "H" "I" "J" "K" "L" "M" "N" "O" "P" "Q" "R" "S"
[20] "T" "U" "V" "W" "X" "Y" "Z"
$mois
[1] "January" "February" "March" "April" "May" "June"
[7] "July" "August" "September" "October" "November" "December"
length(l2)
[1] 3
names(l2)
43
length(l)
[1] 2
Eh bien non ! Elle est de longueur 2 car nous avons créé une
liste composée de deux éléments qui sont eux-mêmes des listes.
Cela est plus lisible si on fait appel à la fonction str() qui
permet de visualiser la structure d’un objet.
str(l)
List of 2
$ :List of 2
..$ : int [1:5] 1 2 3 4 5
..$ : chr "abc"
$ :List of 3
..$ minuscules: chr [1:26] "a" "b" "c" "d" ...
..$ majuscules: chr [1:26] "A" "B" "C" "D" ...
..$ mois : chr [1:12] "January" "February" "March" "April" ...
[1] 5
str(l)
List of 5
$ : int [1:5] 1 2 3 4 5
$ : chr "abc"
$ minuscules: chr [1:26] "a" "b" "c" "d" ...
$ majuscules: chr [1:26] "A" "B" "C" "D" ...
$ mois : chr [1:12] "January" "February" "March" "April" ...
44
Ĺ Note
3.2 Indexation
[[1]]
[1] 1 2 3 4 5
[[2]]
[1] "abc"
$minuscules
[1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s"
[20] "t" "u" "v" "w" "x" "y" "z"
$majuscules
[1] "A" "B" "C" "D" "E" "F" "G" "H" "I" "J" "K" "L" "M" "N" "O" "P" "Q" "R" "S"
[20] "T" "U" "V" "W" "X" "Y" "Z"
$mois
[1] "January" "February" "March" "April" "May" "June"
[7] "July" "August" "September" "October" "November" "December"
l[c(1,3,4)]
[[1]]
[1] 1 2 3 4 5
$minuscules
45
[1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s"
[20] "t" "u" "v" "w" "x" "y" "z"
$majuscules
[1] "A" "B" "C" "D" "E" "F" "G" "H" "I" "J" "K" "L" "M" "N" "O" "P" "Q" "R" "S"
[20] "T" "U" "V" "W" "X" "Y" "Z"
l[c("majuscules", "minuscules")]
$majuscules
[1] "A" "B" "C" "D" "E" "F" "G" "H" "I" "J" "K" "L" "M" "N" "O" "P" "Q" "R" "S"
[20] "T" "U" "V" "W" "X" "Y" "Z"
$minuscules
[1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s"
[20] "t" "u" "v" "w" "x" "y" "z"
[[1]]
[1] 1 2 3 4 5
[[2]]
[1] "abc"
$mois
[1] "January" "February" "March" "April" "May" "June"
[7] "July" "August" "September" "October" "November" "December"
str(l[1])
List of 1
$ : int [1:5] 1 2 3 4 5
46
Supposons que je souhaite calculer la moyenne des valeurs du
premier élément de ma liste. Essayons la commande suivante :
mean(l[1])
[1] NA
str(l[1])
List of 1
$ : int [1:5] 1 2 3 4 5
str(l[[1]])
int [1:5] 1 2 3 4 5
mean(l[[1]])
[1] 3
47
l[["mois"]]
l$mois
l$1
[[1]]
[1] 1 2 3 4 5
[[2]]
[[2]][[1]]
[1] "un" "vecteur" "textuel"
48
$minuscules
[1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s"
[20] "t" "u" "v" "w" "x" "y" "z"
$majuscules
[1] "A" "B" "C" "D" "E" "F" "G" "H" "I" "J" "K" "L" "M" "N" "O" "P" "Q" "R" "S"
[20] "T" "U" "V" "W" "X" "Y" "Z"
$mois
[1] "Janvier" "Février" "Mars"
3.3 En résumé
3.4 webin-R
49
4 Tableaux de données
df <- [Link](
sexe = c("f", "f", "h", "h"),
age = c(52, 31, 29, 35),
blond = c(FALSE, TRUE, TRUE, FALSE)
)
df
50
2 f 31 TRUE
3 h 29 TRUE
4 h 35 FALSE
str(df)
length(df)
[1] 3
names(df)
nrow(df)
[1] 4
ncol(df)
[1] 3
51
dim(df)
[1] 4 3
De plus, tout comme les colonnes ont un nom, il est aussi pos-
sible de nommer les lignes avec [Link]() :
4.2 Indexation
df[1]
sexe
Anna f
Mary-Ann f
Michael h
John h
df[[1]]
52
df$sexe
df
df[3, 2]
[1] 29
df["Michael", "age"]
[1] 29
[1] 29
53
df[3, "age"]
[1] 29
df["Michael", 2]
[1] 29
df[1:2,]
df[,c("sexe", "blond")]
sexe blond
Anna f FALSE
Mary-Ann f TRUE
Michael h TRUE
John h FALSE
Á Avertissement
54
df[2, ]
df[, 2]
[1] 52 31 29 35
df[2]
age
Anna 52
Mary-Ann 31
Michael 29
John 35
Ĺ Note
str(df[2, ])
str(df[, 2])
num [1:4] 52 31 29 35
str(df[2])
55
str(df[[2]])
num [1:4] 52 31 29 35
library(questionr)
data(hdv2003)
56
View(hdv2003)
head(hdv2003)
57
3 Ni croyance ni appartenance Aussi important que le reste Equilibre
4 Appartenance sans pratique Moins important que le reste Satisfaction
5 Pratiquant regulier <NA> <NA>
6 Ni croyance ni appartenance Le plus important Equilibre
[Link] [Link] [Link] cuisine bricol cinema sport [Link]
1 Non Non Non Oui Non Non Non 0
2 Non Non Non Non Non Oui Oui 1
3 Non Non Non Non Non Non Oui 0
4 Non Non Non Oui Oui Oui Oui 2
5 Non Non Non Non Non Non Non 3
6 Non Non Non Non Non Oui Oui 2
tail(hdv2003, 2)
library(dplyr)
glimpse(hdv2003)
Rows: 2,000
Columns: 20
$ id <int> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 1~
58
$ age <int> 28, 23, 59, 34, 71, 35, 60, 47, 20, 28, 65, 47, 63, 67, ~
$ sexe <fct> Femme, Femme, Homme, Homme, Femme, Femme, Femme, Homme, ~
$ nivetud <fct> "Enseignement superieur y compris technique superieur", ~
$ poids <dbl> 2634.3982, 9738.3958, 3994.1025, 5731.6615, 4329.0940, 8~
$ occup <fct> "Exerce une profession", "Etudiant, eleve", "Exerce une ~
$ qualif <fct> Employe, NA, Technicien, Technicien, Employe, Employe, O~
$ [Link] <int> 8, 2, 2, 1, 0, 5, 1, 5, 4, 2, 3, 4, 1, 5, 2, 3, 4, 0, 2,~
$ clso <fct> Oui, Oui, Non, Non, Oui, Non, Oui, Non, Oui, Non, Oui, O~
$ relig <fct> Ni croyance ni appartenance, Ni croyance ni appartenance~
$ [Link] <fct> Peu important, NA, Aussi important que le reste, Moins i~
$ [Link] <fct> Insatisfaction, NA, Equilibre, Satisfaction, NA, Equilib~
$ [Link] <fct> Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, N~
$ [Link] <fct> Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, Non, N~
$ [Link] <fct> Non, Non, Non, Non, Non, Non, Oui, Oui, Non, Non, Non, N~
$ cuisine <fct> Oui, Non, Non, Oui, Non, Non, Oui, Oui, Non, Non, Oui, N~
$ bricol <fct> Non, Non, Non, Oui, Non, Non, Non, Oui, Non, Non, Oui, O~
$ cinema <fct> Non, Oui, Non, Oui, Non, Oui, Non, Non, Oui, Oui, Oui, N~
$ sport <fct> Non, Oui, Oui, Oui, Non, Oui, Non, Non, Non, Oui, Non, O~
$ [Link] <dbl> 0.0, 1.0, 0.0, 2.0, 3.0, 2.0, 2.9, 1.0, 2.0, 2.0, 1.0, 0~
library(labelled)
look_for(hdv2003)
59
5 poids — dbl 0
6 occup — fct 0
8 [Link] — int 0
9 clso — fct 0
10 relig — fct 0
13 [Link] — fct 0
14 [Link] — fct 0
15 [Link] — fct 0
16 cuisine — fct 0
17 bricol — fct 0
60
18 cinema — fct 0
19 sport — fct 0
20 [Link] — dbl 5
values
Homme
Femme
N'a jamais fait d'etudes
A arrete ses etudes, avant la derniere ann~
Derniere annee d'etudes primaires
1er cycle
2eme cycle
Enseignement technique ou professionnel co~
Enseignement technique ou professionnel lo~
Enseignement superieur y compris technique~
Oui
Non
Ne sait pas
Pratiquant regulier
Pratiquant occasionnel
Appartenance sans pratique
61
Ni croyance ni appartenance
Rejet
NSP ou NVPR
Le plus important
Aussi important que le reste
Moins important que le reste
Peu important
Satisfaction
Insatisfaction
Equilibre
Non
Oui
Non
Oui
Non
Oui
Non
Oui
Non
Oui
Non
Oui
Non
Oui
look_for(hdv2003, "trav")
62
Equilibre
summary(hdv2003)
id age sexe
Min. : 1.0 Min. :18.00 Homme: 899
1st Qu.: 500.8 1st Qu.:35.00 Femme:1101
Median :1000.5 Median :48.00
Mean :1000.5 Mean :48.16
3rd Qu.:1500.2 3rd Qu.:60.00
Max. :2000.0 Max. :97.00
nivetud poids
Enseignement technique ou professionnel court :463 Min. : 78.08
Enseignement superieur y compris technique superieur:441 1st Qu.: 2221.82
Derniere annee d'etudes primaires :341 Median : 4631.19
1er cycle :204 Mean : 5535.61
2eme cycle :183 3rd Qu.: 7626.53
(Other) :256 Max. :31092.14
NA's :112
occup qualif [Link]
Exerce une profession:1049 Employe :594 Min. : 0.000
Chomeur : 134 Ouvrier qualifie :292 1st Qu.: 1.000
Etudiant, eleve : 94 Cadre :260 Median : 2.000
Retraite : 392 Ouvrier specialise :203 Mean : 3.283
Retire des affaires : 77 Profession intermediaire:160 3rd Qu.: 5.000
Au foyer : 171 (Other) :144 Max. :22.000
Autre inactif : 83 NA's :347
clso relig
Oui : 936 Pratiquant regulier :266
Non :1037 Pratiquant occasionnel :442
63
Ne sait pas: 27 Appartenance sans pratique :760
Ni croyance ni appartenance:399
Rejet : 93
NSP ou NVPR : 40
summary(hdv2003$sexe)
Homme Femme
899 1101
summary(hdv2003$age)
64
4.4 En résumé
4.5 webin-R
65
5 Tibbles
66
fonctions des extensions du tidyverse acceptent des [Link]
en entrée, mais retournent un tibble.
Contrairement aux data frames, les tibbles :
library(tidyverse)
tibble(
x = c(1.2345, 12.345, 123.45, 1234.5, 12345),
y = c("a", "b", "c", "d", "e")
)
# A tibble: 5 x 2
x y
<dbl> <chr>
1 1.23 a
2 12.3 b
3 123. c
4 1234. d
5 12345 e
67
d <- as_tibble(mtcars)
d
# A tibble: 32 x 11
mpg cyl disp hp drat wt qsec vs am gear carb
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 21 6 160 110 3.9 2.62 16.5 0 1 4 4
2 21 6 160 110 3.9 2.88 17.0 0 1 4 4
3 22.8 4 108 93 3.85 2.32 18.6 1 1 4 1
4 21.4 6 258 110 3.08 3.22 19.4 1 0 3 1
5 18.7 8 360 175 3.15 3.44 17.0 0 0 3 2
6 18.1 6 225 105 2.76 3.46 20.2 1 0 3 1
7 14.3 8 360 245 3.21 3.57 15.8 0 0 3 4
8 24.4 4 147. 62 3.69 3.19 20 1 0 4 2
9 22.8 4 141. 95 3.92 3.15 22.9 1 0 4 2
10 19.2 6 168. 123 3.92 3.44 18.3 1 0 4 4
# i 22 more rows
class(d)
d <- as_tibble(rownames_to_column(mtcars))
d
# A tibble: 32 x 12
rowname mpg cyl disp hp drat wt qsec vs am gear carb
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 Mazda RX4 21 6 160 110 3.9 2.62 16.5 0 1 4 4
2 Mazda RX4 ~ 21 6 160 110 3.9 2.88 17.0 0 1 4 4
68
3 Datsun 710 22.8 4 108 93 3.85 2.32 18.6 1 1 4 1
4 Hornet 4 D~ 21.4 6 258 110 3.08 3.22 19.4 1 0 3 1
5 Hornet Spo~ 18.7 8 360 175 3.15 3.44 17.0 0 0 3 2
6 Valiant 18.1 6 225 105 2.76 3.46 20.2 1 0 3 1
7 Duster 360 14.3 8 360 245 3.21 3.57 15.8 0 0 3 4
8 Merc 240D 24.4 4 147. 62 3.69 3.19 20 1 0 4 2
9 Merc 230 22.8 4 141. 95 3.92 3.15 22.9 1 0 4 2
10 Merc 280 19.2 6 168. 123 3.92 3.44 18.3 1 0 4 4
# i 22 more rows
[Link](d)
69
25 Pontiac Firebird 19.2 8 400.0 175 3.08 3.845 17.05 0 0 3 2
26 Fiat X1-9 27.3 4 79.0 66 4.08 1.935 18.90 1 1 4 1
27 Porsche 914-2 26.0 4 120.3 91 4.43 2.140 16.70 0 1 5 2
28 Lotus Europa 30.4 4 95.1 113 3.77 1.513 16.90 1 1 5 2
29 Ford Pantera L 15.8 8 351.0 264 4.22 3.170 14.50 0 1 5 4
30 Ferrari Dino 19.7 6 145.0 175 3.62 2.770 15.50 0 1 5 6
31 Maserati Bora 15.0 8 301.0 335 3.54 3.570 14.60 0 1 5 8
32 Volvo 142E 21.4 4 121.0 109 4.11 2.780 18.60 1 1 4 2
column_to_rownames([Link](d))
70
Fiat X1-9 27.3 4 79.0 66 4.08 1.935 18.90 1 1 4 1
Porsche 914-2 26.0 4 120.3 91 4.43 2.140 16.70 0 1 5 2
Lotus Europa 30.4 4 95.1 113 3.77 1.513 16.90 1 1 5 2
Ford Pantera L 15.8 8 351.0 264 4.22 3.170 14.50 0 1 5 4
Ferrari Dino 19.7 6 145.0 175 3.62 2.770 15.50 0 1 5 6
Maserati Bora 15.0 8 301.0 335 3.54 3.570 14.60 0 1 5 8
Volvo 142E 21.4 4 121.0 109 4.11 2.780 18.60 1 1 4 2
Ĺ Note
d <- tibble(
g = c(1, 2, 3),
data = list(
tibble(x = 1, y = 2),
tibble(x = 4:5, y = 6:7),
tibble(x = 10)
)
)
d
# A tibble: 3 x 2
g data
<dbl> <list>
1 1 <tibble [1 x 2]>
2 2 <tibble [2 x 2]>
3 3 <tibble [1 x 1]>
71
d$data[[2]]
# A tibble: 2 x 2
x y
<int> <int>
1 4 6
2 5 7
reg <-
iris |>
group_by(Species) |>
nest() |>
mutate(
model = map(
data,
~ lm([Link] ~ [Link] + [Link], data = .)
),
tbl = map(model, gtsummary::tbl_regression)
)
reg
# A tibble: 3 x 4
# Groups: Species [3]
Species data model tbl
<fct> <list> <list> <list>
72
1 setosa <tibble [50 x 4]> <lm> <tbl_rgrs>
2 versicolor <tibble [50 x 4]> <lm> <tbl_rgrs>
3 virginica <tibble [50 x 4]> <lm> <tbl_rgrs>
gtsummary::tbl_merge(
reg$tbl,
tab_spanner = paste0("**", reg$Species, "**")
)
73
6 Attributs
attributes(iris)
$names
[1] "[Link]" "[Link]" "[Link]" "[Link]" "Species"
$class
[1] "[Link]"
$[Link]
[1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
[19] 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
[37] 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
[55] 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
[73] 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
[91] 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
74
[109] 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
[127] 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
[145] 145 146 147 148 149 150
class(iris)
[1] "[Link]"
names(iris)
$names
[1] "[Link]" "[Link]" "[Link]" "[Link]" "Species"
$class
[1] "[Link]"
75
$[Link]
[1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
[19] 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
[37] 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
[55] 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
[73] 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
[91] 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
[109] 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
[127] 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
[145] 145 146 147 148 149 150
$perso
[1] "Des notes personnelles"
attr(iris, "perso")
76
partie II
Manipulation de données
77
7 Le pipe
78
Nous obtenons bien le même résultat, mais la lecture de cette
ligne de code est assez difficile et il n’est pas aisé de bien iden-
tifier à quelle fonction est rattaché chaque argument.
Une amélioration possible serait d’effectuer des retours à la
ligne avec une indentation adéquate pour rendre cela plus li-
sible.
message(
paste0(
"La moyenne est de ",
format(
round(
mean(v),
digits = 1),
[Link] = ","
),
"."
)
)
79
placeholder doit impérativement être transmis à un argument
nommé !
Tout cela semble encore un peu abstrait ? Reprenons notre
exemple précédent et réécrivons le code avec le pipe.
v |>
mean() |>
round(digits = 1) |>
format([Link] = ",") |>
paste0("La moyenne est de ", m = _, ".") |>
message()
80
library(magrittr)
v %>%
mean() %>%
round(digits = 1) %>%
format([Link] = ",") %>%
paste0("La moyenne est de ", ., ".") %>%
message()
81
7.4 Accéder à un élément avec
purrr::pluck() et purrr::chuck()
iris |>
purrr::pluck("[Link]") |>
mean()
[1] 1.199333
mean(iris$[Link])
[1] 1.199333
[1] "b"
82
v[2]
[1] "b"
iris |>
purrr::pluck("[Link]", 3)
[1] 3.2
iris |>
purrr::pluck("[Link]") |>
purrr::pluck(3)
[1] 3.2
iris[["[Link]"]][3]
[1] 3.2
NULL
Error in `purrr::chuck()`:
! Can't find name `inconnu` in vector.
83
v |> purrr::pluck(10)
NULL
v |> purrr::chuck(10)
Error in `purrr::chuck()`:
! Index 1 exceeds the length of plucked object (10 > 4).
84
8 dplyr
library(nycflights13)
## Chargement des trois tables du jeu de données
data(flights)
data(airports)
85
data(airlines)
8.1.1 filter()
filter(flights, month == 1)
# A tibble: 27,004 x 19
year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
<int> <int> <int> <int> <int> <dbl> <int> <int>
1 2013 1 1 517 515 2 830 819
2 2013 1 1 533 529 4 850 830
3 2013 1 1 542 540 2 923 850
4 2013 1 1 544 545 -1 1004 1022
5 2013 1 1 554 600 -6 812 837
6 2013 1 1 554 558 -4 740 728
7 2013 1 1 555 600 -5 913 854
8 2013 1 1 557 600 -3 709 723
9 2013 1 1 557 600 -3 838 846
10 2013 1 1 558 600 -2 753 745
# i 26,994 more rows
# i 11 more variables: arr_delay <dbl>, carrier <chr>, flight <int>,
# tailnum <chr>, origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>,
# hour <dbl>, minute <dbl>, time_hour <dttm>
86
flights |> filter(month == 1)
# A tibble: 27,004 x 19
year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
<int> <int> <int> <int> <int> <dbl> <int> <int>
1 2013 1 1 517 515 2 830 819
2 2013 1 1 533 529 4 850 830
3 2013 1 1 542 540 2 923 850
4 2013 1 1 544 545 -1 1004 1022
5 2013 1 1 554 600 -6 812 837
6 2013 1 1 554 558 -4 740 728
7 2013 1 1 555 600 -5 913 854
8 2013 1 1 557 600 -3 709 723
9 2013 1 1 557 600 -3 838 846
10 2013 1 1 558 600 -2 753 745
# i 26,994 more rows
# i 11 more variables: arr_delay <dbl>, carrier <chr>, flight <int>,
# tailnum <chr>, origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>,
# hour <dbl>, minute <dbl>, time_hour <dttm>
flights |>
filter(dep_delay >= 10 & dep_delay <= 15)
# A tibble: 14,919 x 19
year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
<int> <int> <int> <int> <int> <dbl> <int> <int>
1 2013 1 1 611 600 11 945 931
2 2013 1 1 623 610 13 920 915
3 2013 1 1 743 730 13 1107 1100
4 2013 1 1 743 730 13 1059 1056
5 2013 1 1 851 840 11 1215 1206
6 2013 1 1 912 900 12 1241 1220
7 2013 1 1 914 900 14 1058 1043
8 2013 1 1 920 905 15 1039 1025
9 2013 1 1 1011 1001 10 1133 1128
10 2013 1 1 1112 1100 12 1440 1438
87
# i 14,909 more rows
# i 11 more variables: arr_delay <dbl>, carrier <chr>, flight <int>,
# tailnum <chr>, origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>,
# hour <dbl>, minute <dbl>, time_hour <dttm>
flights |>
filter(dep_delay >= 10, dep_delay <= 15)
flights |>
filter(distance == max(distance))
# A tibble: 342 x 19
year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
<int> <int> <int> <int> <int> <dbl> <int> <int>
1 2013 1 1 857 900 -3 1516 1530
2 2013 1 2 909 900 9 1525 1530
3 2013 1 3 914 900 14 1504 1530
4 2013 1 4 900 900 0 1516 1530
5 2013 1 5 858 900 -2 1519 1530
6 2013 1 6 1019 900 79 1558 1530
7 2013 1 7 1042 900 102 1620 1530
8 2013 1 8 901 900 1 1504 1530
9 2013 1 9 641 900 1301 1242 1530
10 2013 1 10 859 900 -1 1449 1530
# i 332 more rows
# i 11 more variables: arr_delay <dbl>, carrier <chr>, flight <int>,
# tailnum <chr>, origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>,
# hour <dbl>, minute <dbl>, time_hour <dttm>
88
Ď Évaluation contextuelle
m <- 2
flights |>
filter(month == m)
# A tibble: 24,951 x 19
year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
<int> <int> <int> <int> <int> <dbl> <int> <int>
1 2013 2 1 456 500 -4 652 648
2 2013 2 1 520 525 -5 816 820
3 2013 2 1 527 530 -3 837 829
4 2013 2 1 532 540 -8 1007 1017
5 2013 2 1 540 540 0 859 850
6 2013 2 1 552 600 -8 714 715
7 2013 2 1 552 600 -8 919 910
8 2013 2 1 552 600 -8 655 709
9 2013 2 1 553 600 -7 833 815
10 2013 2 1 553 600 -7 821 825
# i 24,941 more rows
# i 11 more variables: arr_delay <dbl>, carrier <chr>, flight <int>,
# tailnum <chr>, origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>,
# hour <dbl>, minute <dbl>, time_hour <dttm>
89
priorité sur les objets du même nom dans l’environnement.
Dans l’exemple ci-dessous, le résultat obtenu n’est pas ce-
lui voulu. Il est interprété comme sélectionner toutes les
lignes où la colonne mois est égale à elle-même et donc
cela sélectionne toutes les lignes du tableau.
month <- 3
flights |>
filter(month == month)
# A tibble: 336,776 x 19
year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
<int> <int> <int> <int> <int> <dbl> <int> <int>
1 2013 1 1 517 515 2 830 819
2 2013 1 1 533 529 4 850 830
3 2013 1 1 542 540 2 923 850
4 2013 1 1 544 545 -1 1004 1022
5 2013 1 1 554 600 -6 812 837
6 2013 1 1 554 558 -4 740 728
7 2013 1 1 555 600 -5 913 854
8 2013 1 1 557 600 -3 709 723
9 2013 1 1 557 600 -3 838 846
10 2013 1 1 558 600 -2 753 745
# i 336,766 more rows
# i 11 more variables: arr_delay <dbl>, carrier <chr>, flight <int>,
# tailnum <chr>, origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>,
# hour <dbl>, minute <dbl>, time_hour <dttm>
month <- 3
flights |>
filter(.data$month == .env$month)
# A tibble: 28,834 x 19
year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
<int> <int> <int> <int> <int> <dbl> <int> <int>
90
1 2013 3 1 4 2159 125 318 56
2 2013 3 1 50 2358 52 526 438
3 2013 3 1 117 2245 152 223 2354
4 2013 3 1 454 500 -6 633 648
5 2013 3 1 505 515 -10 746 810
6 2013 3 1 521 530 -9 813 827
7 2013 3 1 537 540 -3 856 850
8 2013 3 1 541 545 -4 1014 1023
9 2013 3 1 549 600 -11 639 703
10 2013 3 1 550 600 -10 747 801
# i 28,824 more rows
# i 11 more variables: arr_delay <dbl>, carrier <chr>, flight <int>,
# tailnum <chr>, origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>,
# hour <dbl>, minute <dbl>, time_hour <dttm>
8.1.2 slice()
airports |>
slice(345)
# A tibble: 1 x 8
faa name lat lon alt tz dst tzone
<chr> <chr> <dbl> <dbl> <dbl> <dbl> <chr> <chr>
1 CYF Chefornak Airport 60.1 -164. 40 -9 A America/Anchorage
airports |>
slice(1:5)
# A tibble: 5 x 8
91
faa name lat lon alt tz dst tzone
<chr> <chr> <dbl> <dbl> <dbl> <dbl> <chr> <chr>
1 04G Lansdowne Airport 41.1 -80.6 1044 -5 A America/New~
2 06A Moton Field Municipal Airport 32.5 -85.7 264 -6 A America/Chi~
3 06C Schaumburg Regional 42.0 -88.1 801 -6 A America/Chi~
4 06N Randall Airport 41.4 -74.4 523 -5 A America/New~
5 09J Jekyll Island Airport 31.1 -81.4 11 -5 A America/New~
8.1.3 arrange()
flights |>
arrange(dep_delay)
# A tibble: 336,776 x 19
year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
<int> <int> <int> <int> <int> <dbl> <int> <int>
1 2013 12 7 2040 2123 -43 40 2352
2 2013 2 3 2022 2055 -33 2240 2338
3 2013 11 10 1408 1440 -32 1549 1559
4 2013 1 11 1900 1930 -30 2233 2243
5 2013 1 29 1703 1730 -27 1947 1957
6 2013 8 9 729 755 -26 1002 955
7 2013 10 23 1907 1932 -25 2143 2143
8 2013 3 30 2030 2055 -25 2213 2250
9 2013 3 2 1431 1455 -24 1601 1631
10 2013 5 5 934 958 -24 1225 1309
# i 336,766 more rows
# i 11 more variables: arr_delay <dbl>, carrier <chr>, flight <int>,
# tailnum <chr>, origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>,
# hour <dbl>, minute <dbl>, time_hour <dttm>
92
flights |>
arrange(month, dep_delay)
# A tibble: 336,776 x 19
year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
<int> <int> <int> <int> <int> <dbl> <int> <int>
1 2013 1 11 1900 1930 -30 2233 2243
2 2013 1 29 1703 1730 -27 1947 1957
3 2013 1 12 1354 1416 -22 1606 1650
4 2013 1 21 2137 2159 -22 2232 2316
5 2013 1 20 704 725 -21 1025 1035
6 2013 1 12 2050 2110 -20 2310 2355
7 2013 1 12 2134 2154 -20 4 50
8 2013 1 14 2050 2110 -20 2329 2355
9 2013 1 4 2140 2159 -19 2241 2316
10 2013 1 11 1947 2005 -18 2209 2230
# i 336,766 more rows
# i 11 more variables: arr_delay <dbl>, carrier <chr>, flight <int>,
# tailnum <chr>, origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>,
# hour <dbl>, minute <dbl>, time_hour <dttm>
flights |>
arrange(desc(dep_delay))
# A tibble: 336,776 x 19
year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
<int> <int> <int> <int> <int> <dbl> <int> <int>
1 2013 1 9 641 900 1301 1242 1530
2 2013 6 15 1432 1935 1137 1607 2120
3 2013 1 10 1121 1635 1126 1239 1810
4 2013 9 20 1139 1845 1014 1457 2210
5 2013 7 22 845 1600 1005 1044 1815
6 2013 4 10 1100 1900 960 1342 2211
7 2013 3 17 2321 810 911 135 1020
8 2013 6 27 959 1900 899 1236 2226
9 2013 7 22 2257 759 898 121 1026
93
10 2013 12 5 756 1700 896 1058 2020
# i 336,766 more rows
# i 11 more variables: arr_delay <dbl>, carrier <chr>, flight <int>,
# tailnum <chr>, origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>,
# hour <dbl>, minute <dbl>, time_hour <dttm>
flights |>
arrange(desc(dep_delay)) |>
slice(1:3)
# A tibble: 3 x 19
year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
<int> <int> <int> <int> <int> <dbl> <int> <int>
1 2013 1 9 641 900 1301 1242 1530
2 2013 6 15 1432 1935 1137 1607 2120
3 2013 1 10 1121 1635 1126 1239 1810
# i 11 more variables: arr_delay <dbl>, carrier <chr>, flight <int>,
# tailnum <chr>, origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>,
# hour <dbl>, minute <dbl>, time_hour <dttm>
8.1.4 slice_sample()
airports |>
slice_sample(n = 5)
# A tibble: 5 x 8
faa name lat lon alt tz dst tzone
<chr> <chr> <dbl> <dbl> <dbl> <dbl> <chr> <chr>
1 EGV Eagle River 45.9 -89.3 1642 -6 A America/Chica~
94
2 RID Richmond Municipal Airport 39.8 -84.8 1140 -5 U America/New_Y~
3 EGA Eagle County Airport 39.6 -107. 6548 -7 U America/Denver
4 YKN Chan Gurney 42.9 -97.4 1200 -6 A America/Chica~
5 FWA Fort Wayne 41.0 -85.2 815 -5 A America/New_Y~
flights |>
slice_sample(prop = .1)
# A tibble: 33,677 x 19
year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
<int> <int> <int> <int> <int> <dbl> <int> <int>
1 2013 1 13 1828 1705 83 2037 1905
2 2013 12 9 1013 1000 13 1320 1242
3 2013 6 8 1738 1655 43 2023 2005
4 2013 12 24 1518 1520 -2 1648 1700
5 2013 11 21 625 635 -10 808 812
6 2013 4 24 1858 1844 14 2205 2114
7 2013 7 6 654 659 -5 852 909
8 2013 9 15 1922 1925 -3 2212 2248
9 2013 6 17 935 930 5 1036 1042
10 2013 5 28 1356 1359 -3 1542 1554
# i 33,667 more rows
# i 11 more variables: arr_delay <dbl>, carrier <chr>, flight <int>,
# tailnum <chr>, origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>,
# hour <dbl>, minute <dbl>, time_hour <dttm>
8.1.5 distinct()
95
flights |>
select(day, month) |>
distinct()
# A tibble: 365 x 2
day month
<int> <int>
1 1 1
2 2 1
3 3 1
4 4 1
5 5 1
6 6 1
7 7 1
8 8 1
9 9 1
10 10 1
# i 355 more rows
flights |>
distinct(month, day)
# A tibble: 365 x 2
month day
<int> <int>
1 1 1
2 1 2
3 1 3
4 1 4
5 1 5
6 1 6
7 1 7
8 1 8
9 1 9
96
10 1 10
# i 355 more rows
flights |>
distinct(month, day, .keep_all = TRUE)
# A tibble: 365 x 19
year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
<int> <int> <int> <int> <int> <dbl> <int> <int>
1 2013 1 1 517 515 2 830 819
2 2013 1 2 42 2359 43 518 442
3 2013 1 3 32 2359 33 504 442
4 2013 1 4 25 2359 26 505 442
5 2013 1 5 14 2359 15 503 445
6 2013 1 6 16 2359 17 451 442
7 2013 1 7 49 2359 50 531 444
8 2013 1 8 454 500 -6 625 648
9 2013 1 9 2 2359 3 432 444
10 2013 1 10 3 2359 4 426 437
# i 355 more rows
# i 11 more variables: arr_delay <dbl>, carrier <chr>, flight <int>,
# tailnum <chr>, origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>,
# hour <dbl>, minute <dbl>, time_hour <dttm>
8.2.1 select()
airports |>
select(lat, lon)
97
# A tibble: 1,458 x 2
lat lon
<dbl> <dbl>
1 41.1 -80.6
2 32.5 -85.7
3 42.0 -88.1
4 41.4 -74.4
5 31.1 -81.4
6 36.4 -82.2
7 41.5 -84.5
8 42.9 -76.8
9 39.8 -76.6
10 48.1 -123.
# i 1,448 more rows
airports |>
select(-lat, -lon)
# A tibble: 1,458 x 6
faa name alt tz dst tzone
<chr> <chr> <dbl> <dbl> <chr> <chr>
1 04G Lansdowne Airport 1044 -5 A America/New_York
2 06A Moton Field Municipal Airport 264 -6 A America/Chicago
3 06C Schaumburg Regional 801 -6 A America/Chicago
4 06N Randall Airport 523 -5 A America/New_York
5 09J Jekyll Island Airport 11 -5 A America/New_York
6 0A9 Elizabethton Municipal Airport 1593 -5 A America/New_York
7 0G6 Williams County Airport 730 -5 A America/New_York
8 0G7 Finger Lakes Regional Airport 492 -5 A America/New_York
9 0P2 Shoestring Aviation Airfield 1000 -5 U America/New_York
10 0S9 Jefferson County Intl 108 -8 A America/Los_Angeles
# i 1,448 more rows
98
dplyr::contains() ou dplyr::matches() permettent
d’exprimer des conditions sur les noms de variables :
flights |>
select(starts_with("dep_"))
# A tibble: 336,776 x 2
dep_time dep_delay
<int> <dbl>
1 517 2
2 533 4
3 542 2
4 544 -1
5 554 -6
6 554 -4
7 555 -5
8 557 -3
9 557 -3
10 558 -2
# i 336,766 more rows
# A tibble: 336,776 x 3
year month day
<int> <int> <int>
1 2013 1 1
2 2013 1 1
3 2013 1 1
4 2013 1 1
5 2013 1 1
6 2013 1 1
7 2013 1 1
8 2013 1 1
9 2013 1 1
99
10 2013 1 1
# i 336,766 more rows
flights |>
select(all_of(c("year", "month", "day")))
# A tibble: 336,776 x 3
year month day
<int> <int> <int>
1 2013 1 1
2 2013 1 1
3 2013 1 1
4 2013 1 1
5 2013 1 1
6 2013 1 1
7 2013 1 1
8 2013 1 1
9 2013 1 1
10 2013 1 1
# i 336,766 more rows
flights |>
select(all_of(c("century", "year", "month", "day")))
Error in `all_of()`:
! Can't subset columns that don't exist.
x Column `century` doesn't exist.
100
flights |>
select(any_of(c("century", "year", "month", "day")))
# A tibble: 336,776 x 3
year month day
<int> <int> <int>
1 2013 1 1
2 2013 1 1
3 2013 1 1
4 2013 1 1
5 2013 1 1
6 2013 1 1
7 2013 1 1
8 2013 1 1
9 2013 1 1
10 2013 1 1
# i 336,766 more rows
flights |>
select(where([Link]))
# A tibble: 336,776 x 4
carrier tailnum origin dest
<chr> <chr> <chr> <chr>
1 UA N14228 EWR IAH
2 UA N24211 LGA IAH
3 AA N619AA JFK MIA
4 B6 N804JB JFK BQN
5 DL N668DN LGA ATL
6 UA N39463 EWR ORD
7 B6 N516JB EWR FLL
8 EV N829AS LGA IAD
9 B6 N593JB JFK MCO
10 AA N3ALAA LGA ORD
# i 336,766 more rows
101
dplyr::select() peut être utilisée pour réordonner les co-
lonnes d’une table en utilisant la fonction dplyr::everything(),
qui sélectionne l’ensemble des colonnes non encore sélection-
nées. Ainsi, si l’on souhaite faire passer la colonne name en
première position de la table airports, on peut faire :
airports |>
select(name, everything())
# A tibble: 1,458 x 8
name faa lat lon alt tz dst tzone
<chr> <chr> <dbl> <dbl> <dbl> <dbl> <chr> <chr>
1 Lansdowne Airport 04G 41.1 -80.6 1044 -5 A America/~
2 Moton Field Municipal Airport 06A 32.5 -85.7 264 -6 A America/~
3 Schaumburg Regional 06C 42.0 -88.1 801 -6 A America/~
4 Randall Airport 06N 41.4 -74.4 523 -5 A America/~
5 Jekyll Island Airport 09J 31.1 -81.4 11 -5 A America/~
6 Elizabethton Municipal Airport 0A9 36.4 -82.2 1593 -5 A America/~
7 Williams County Airport 0G6 41.5 -84.5 730 -5 A America/~
8 Finger Lakes Regional Airport 0G7 42.9 -76.8 492 -5 A America/~
9 Shoestring Aviation Airfield 0P2 39.8 -76.6 1000 -5 U America/~
10 Jefferson County Intl 0S9 48.1 -123. 108 -8 A America/~
# i 1,448 more rows
8.2.2 relocate()
airports |>
relocate(lon, lat, name)
# A tibble: 1,458 x 8
lon lat name faa alt tz dst tzone
<dbl> <dbl> <chr> <chr> <dbl> <dbl> <chr> <chr>
1 -80.6 41.1 Lansdowne Airport 04G 1044 -5 A America/~
2 -85.7 32.5 Moton Field Municipal Airport 06A 264 -6 A America/~
102
3 -88.1 42.0 Schaumburg Regional 06C 801 -6 A America/~
4 -74.4 41.4 Randall Airport 06N 523 -5 A America/~
5 -81.4 31.1 Jekyll Island Airport 09J 11 -5 A America/~
6 -82.2 36.4 Elizabethton Municipal Airport 0A9 1593 -5 A America/~
7 -84.5 41.5 Williams County Airport 0G6 730 -5 A America/~
8 -76.8 42.9 Finger Lakes Regional Airport 0G7 492 -5 A America/~
9 -76.6 39.8 Shoestring Aviation Airfield 0P2 1000 -5 U America/~
10 -123. 48.1 Jefferson County Intl 0S9 108 -8 A America/~
# i 1,448 more rows
8.2.3 rename()
airports |>
rename(longitude = lon, latitude = lat)
# A tibble: 1,458 x 8
faa name latitude longitude alt tz dst tzone
<chr> <chr> <dbl> <dbl> <dbl> <dbl> <chr> <chr>
1 04G Lansdowne Airport 41.1 -80.6 1044 -5 A Amer~
2 06A Moton Field Municipal Airpo~ 32.5 -85.7 264 -6 A Amer~
3 06C Schaumburg Regional 42.0 -88.1 801 -6 A Amer~
4 06N Randall Airport 41.4 -74.4 523 -5 A Amer~
5 09J Jekyll Island Airport 31.1 -81.4 11 -5 A Amer~
6 0A9 Elizabethton Municipal Airp~ 36.4 -82.2 1593 -5 A Amer~
7 0G6 Williams County Airport 41.5 -84.5 730 -5 A Amer~
8 0G7 Finger Lakes Regional Airpo~ 42.9 -76.8 492 -5 A Amer~
9 0P2 Shoestring Aviation Airfield 39.8 -76.6 1000 -5 U Amer~
10 0S9 Jefferson County Intl 48.1 -123. 108 -8 A Amer~
# i 1,448 more rows
103
flights |>
rename(
"retard départ" = dep_delay,
"retard arrivée" = arr_delay
) |>
select(`retard départ`, `retard arrivée`)
# A tibble: 336,776 x 2
`retard départ` `retard arrivée`
<dbl> <dbl>
1 2 11
2 4 20
3 2 33
4 -1 -18
5 -6 -25
6 -4 12
7 -5 19
8 -3 -14
9 -3 -8
10 -2 8
# i 336,766 more rows
8.2.4 rename_with()
airports |>
rename_with(toupper)
# A tibble: 1,458 x 8
FAA NAME LAT LON ALT TZ DST TZONE
<chr> <chr> <dbl> <dbl> <dbl> <dbl> <chr> <chr>
1 04G Lansdowne Airport 41.1 -80.6 1044 -5 A America/~
2 06A Moton Field Municipal Airport 32.5 -85.7 264 -6 A America/~
3 06C Schaumburg Regional 42.0 -88.1 801 -6 A America/~
104
4 06N Randall Airport 41.4 -74.4 523 -5 A America/~
5 09J Jekyll Island Airport 31.1 -81.4 11 -5 A America/~
6 0A9 Elizabethton Municipal Airport 36.4 -82.2 1593 -5 A America/~
7 0G6 Williams County Airport 41.5 -84.5 730 -5 A America/~
8 0G7 Finger Lakes Regional Airport 42.9 -76.8 492 -5 A America/~
9 0P2 Shoestring Aviation Airfield 39.8 -76.6 1000 -5 U America/~
10 0S9 Jefferson County Intl 48.1 -123. 108 -8 A America/~
# i 1,448 more rows
airports |>
pull(alt) |>
mean()
[1] 1001.416
Ĺ Note
8.2.6 mutate()
105
Par exemple, la table airports contient l’altitude de l’aéroport
en pieds. Si l’on veut créer une nouvelle variable alt_m avec
l’altitude en mètres, on peut faire :
airports <-
airports |>
mutate(alt_m = alt / 3.2808)
flights <-
flights |>
mutate(
distance_km = distance / 0.62137,
vitesse = distance_km / air_time * 60
)
8.3.1 group_by()
flights |>
group_by(month)
# A tibble: 336,776 x 21
# Groups: month [12]
year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
<int> <int> <int> <int> <int> <dbl> <int> <int>
1 2013 1 1 517 515 2 830 819
106
2 2013 1 1 533 529 4 850 830
3 2013 1 1 542 540 2 923 850
4 2013 1 1 544 545 -1 1004 1022
5 2013 1 1 554 600 -6 812 837
6 2013 1 1 554 558 -4 740 728
7 2013 1 1 555 600 -5 913 854
8 2013 1 1 557 600 -3 709 723
9 2013 1 1 557 600 -3 838 846
10 2013 1 1 558 600 -2 753 745
# i 336,766 more rows
# i 13 more variables: arr_delay <dbl>, carrier <chr>, flight <int>,
# tailnum <chr>, origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>,
# hour <dbl>, minute <dbl>, time_hour <dttm>, distance_km <dbl>,
# vitesse <dbl>
flights |>
group_by(month) |>
slice(1)
# A tibble: 12 x 21
# Groups: month [12]
year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
<int> <int> <int> <int> <int> <dbl> <int> <int>
1 2013 1 1 517 515 2 830 819
2 2013 2 1 456 500 -4 652 648
3 2013 3 1 4 2159 125 318 56
4 2013 4 1 454 500 -6 636 640
5 2013 5 1 9 1655 434 308 2020
107
6 2013 6 1 2 2359 3 341 350
7 2013 7 1 1 2029 212 236 2359
8 2013 8 1 12 2130 162 257 14
9 2013 9 1 9 2359 10 343 340
10 2013 10 1 447 500 -13 614 648
11 2013 11 1 5 2359 6 352 345
12 2013 12 1 13 2359 14 446 445
# i 13 more variables: arr_delay <dbl>, carrier <chr>, flight <int>,
# tailnum <chr>, origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>,
# hour <dbl>, minute <dbl>, time_hour <dttm>, distance_km <dbl>,
# vitesse <dbl>
flights |>
group_by(month) |>
mutate(mean_delay_month = mean(dep_delay, [Link] = TRUE))
# A tibble: 336,776 x 22
# Groups: month [12]
year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
<int> <int> <int> <int> <int> <dbl> <int> <int>
1 2013 1 1 517 515 2 830 819
2 2013 1 1 533 529 4 850 830
3 2013 1 1 542 540 2 923 850
4 2013 1 1 544 545 -1 1004 1022
5 2013 1 1 554 600 -6 812 837
6 2013 1 1 554 558 -4 740 728
7 2013 1 1 555 600 -5 913 854
8 2013 1 1 557 600 -3 709 723
9 2013 1 1 557 600 -3 838 846
10 2013 1 1 558 600 -2 753 745
# i 336,766 more rows
# i 14 more variables: arr_delay <dbl>, carrier <chr>, flight <int>,
# tailnum <chr>, origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>,
# hour <dbl>, minute <dbl>, time_hour <dttm>, distance_km <dbl>,
108
# vitesse <dbl>, mean_delay_month <dbl>
flights |>
group_by(month) |>
filter(dep_delay == max(dep_delay, [Link] = TRUE))
# A tibble: 12 x 21
# Groups: month [12]
year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
<int> <int> <int> <int> <int> <dbl> <int> <int>
1 2013 1 9 641 900 1301 1242 1530
2 2013 10 14 2042 900 702 2255 1127
3 2013 11 3 603 1645 798 829 1913
4 2013 12 5 756 1700 896 1058 2020
5 2013 2 10 2243 830 853 100 1106
6 2013 3 17 2321 810 911 135 1020
7 2013 4 10 1100 1900 960 1342 2211
8 2013 5 3 1133 2055 878 1250 2215
9 2013 6 15 1432 1935 1137 1607 2120
10 2013 7 22 845 1600 1005 1044 1815
11 2013 8 8 2334 1454 520 120 1710
12 2013 9 20 1139 1845 1014 1457 2210
# i 13 more variables: arr_delay <dbl>, carrier <chr>, flight <int>,
# tailnum <chr>, origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>,
# hour <dbl>, minute <dbl>, time_hour <dttm>, distance_km <dbl>,
# vitesse <dbl>
109
On peut voir la différence en comparant les deux résultats sui-
vants :
flights |>
group_by(month) |>
arrange(desc(dep_delay))
# A tibble: 336,776 x 21
# Groups: month [12]
year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
<int> <int> <int> <int> <int> <dbl> <int> <int>
1 2013 1 9 641 900 1301 1242 1530
2 2013 6 15 1432 1935 1137 1607 2120
3 2013 1 10 1121 1635 1126 1239 1810
4 2013 9 20 1139 1845 1014 1457 2210
5 2013 7 22 845 1600 1005 1044 1815
6 2013 4 10 1100 1900 960 1342 2211
7 2013 3 17 2321 810 911 135 1020
8 2013 6 27 959 1900 899 1236 2226
9 2013 7 22 2257 759 898 121 1026
10 2013 12 5 756 1700 896 1058 2020
# i 336,766 more rows
# i 13 more variables: arr_delay <dbl>, carrier <chr>, flight <int>,
# tailnum <chr>, origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>,
# hour <dbl>, minute <dbl>, time_hour <dttm>, distance_km <dbl>,
# vitesse <dbl>
flights |>
group_by(month) |>
arrange(desc(dep_delay), .by_group = TRUE)
# A tibble: 336,776 x 21
# Groups: month [12]
year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
<int> <int> <int> <int> <int> <dbl> <int> <int>
1 2013 1 9 641 900 1301 1242 1530
2 2013 1 10 1121 1635 1126 1239 1810
3 2013 1 1 848 1835 853 1001 1950
4 2013 1 13 1809 810 599 2054 1042
110
5 2013 1 16 1622 800 502 1911 1054
6 2013 1 23 1551 753 478 1812 1006
7 2013 1 10 1525 900 385 1713 1039
8 2013 1 1 2343 1724 379 314 1938
9 2013 1 2 2131 1512 379 2340 1741
10 2013 1 7 2021 1415 366 2332 1724
# i 336,766 more rows
# i 13 more variables: arr_delay <dbl>, carrier <chr>, flight <int>,
# tailnum <chr>, origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>,
# hour <dbl>, minute <dbl>, time_hour <dttm>, distance_km <dbl>,
# vitesse <dbl>
8.3.2 summarise()
flights |>
summarise(
retard_dep = mean(dep_delay, [Link]=TRUE),
retard_arr = mean(arr_delay, [Link]=TRUE)
)
# A tibble: 1 x 2
retard_dep retard_arr
<dbl> <dbl>
1 12.6 6.90
111
flights |>
group_by(month) |>
summarise(
max_delay = max(dep_delay, [Link]=TRUE),
min_delay = min(dep_delay, [Link]=TRUE),
mean_delay = mean(dep_delay, [Link]=TRUE)
)
# A tibble: 12 x 4
month max_delay min_delay mean_delay
<int> <dbl> <dbl> <dbl>
1 1 1301 -30 10.0
2 2 853 -33 10.8
3 3 911 -25 13.2
4 4 960 -21 13.9
5 5 878 -24 13.0
6 6 1137 -21 20.8
7 7 1005 -22 21.7
8 8 520 -26 12.6
9 9 1014 -24 6.72
10 10 702 -25 6.24
11 11 798 -32 5.44
12 12 896 -43 16.6
flights |>
group_by(dest) |>
summarise(n = n())
# A tibble: 105 x 2
dest n
<chr> <int>
1 ABQ 254
2 ACK 265
3 ALB 439
112
4 ANC 8
5 ATL 17215
6 AUS 2439
7 AVL 275
8 BDL 443
9 BGR 375
10 BHM 297
# i 95 more rows
8.3.3 count()
flights |>
count(dest)
# A tibble: 105 x 2
dest n
<chr> <int>
1 ABQ 254
2 ACK 265
3 ALB 439
4 ANC 8
5 ATL 17215
6 AUS 2439
7 AVL 275
8 BDL 443
9 BGR 375
10 BHM 297
# i 95 more rows
113
8.3.4 Grouper selon plusieurs variables
flights |>
group_by(month, dest) |>
summarise(nb = n()) |>
arrange(desc(nb))
`summarise()` has grouped output by 'month'. You can override using the
`.groups` argument.
# A tibble: 1,113 x 3
# Groups: month [12]
month dest nb
<int> <chr> <int>
1 8 ORD 1604
2 10 ORD 1604
3 5 ORD 1582
4 9 ORD 1582
5 7 ORD 1573
6 6 ORD 1547
7 7 ATL 1511
8 8 ATL 1507
9 8 LAX 1505
10 7 LAX 1500
# i 1,103 more rows
flights |>
count(origin, dest) |>
arrange(desc(n))
# A tibble: 224 x 3
origin dest n
<chr> <chr> <int>
114
1 JFK LAX 11262
2 LGA ATL 10263
3 LGA ORD 8857
4 JFK SFO 8204
5 LGA CLT 6168
6 EWR ORD 6100
7 JFK BOS 5898
8 LGA MIA 5781
9 JFK MCO 5464
10 EWR BOS 5327
# i 214 more rows
flights |>
group_by(month, origin, dest) |>
summarise(nb = n()) |>
group_by(month) |>
filter(nb == max(nb))
`summarise()` has grouped output by 'month', 'origin'. You can override using
the `.groups` argument.
# A tibble: 12 x 4
# Groups: month [12]
month origin dest nb
<int> <chr> <chr> <int>
1 1 JFK LAX 937
2 2 JFK LAX 834
3 3 JFK LAX 960
115
4 4 JFK LAX 935
5 5 JFK LAX 960
6 6 JFK LAX 928
7 7 JFK LAX 985
8 8 JFK LAX 979
9 9 JFK LAX 925
10 10 JFK LAX 965
11 11 JFK LAX 907
12 12 JFK LAX 947
`summarise()` has grouped output by 'month', 'origin'. You can override using
the `.groups` argument.
# A tibble: 2,313 x 4
# Groups: month, origin [36]
month origin dest nb
<int> <chr> <chr> <int>
1 1 EWR ALB 64
2 1 EWR ATL 362
3 1 EWR AUS 51
4 1 EWR AVL 2
5 1 EWR BDL 37
6 1 EWR BNA 111
7 1 EWR BOS 430
8 1 EWR BQN 31
9 1 EWR BTV 100
10 1 EWR BUF 119
# i 2,303 more rows
116
Cela peut permettre d’enchaîner les opérations groupées. Dans
l’exemple suivant, on calcule le pourcentage des trajets pour
chaque destination par rapport à tous les trajets du mois :
flights |>
group_by(month, dest) |>
summarise(nb = n()) |>
mutate(pourcentage = nb / sum(nb) * 100)
`summarise()` has grouped output by 'month'. You can override using the
`.groups` argument.
# A tibble: 1,113 x 4
# Groups: month [12]
month dest nb pourcentage
<int> <chr> <int> <dbl>
1 1 ALB 64 0.237
2 1 ATL 1396 5.17
3 1 AUS 169 0.626
4 1 AVL 2 0.00741
5 1 BDL 37 0.137
6 1 BHM 25 0.0926
7 1 BNA 399 1.48
8 1 BOS 1245 4.61
9 1 BQN 93 0.344
10 1 BTV 223 0.826
# i 1,103 more rows
flights |>
group_by(month, dest) |>
summarise(nb = n()) |>
ungroup() |>
mutate(pourcentage = nb / sum(nb) * 100)
117
`summarise()` has grouped output by 'month'. You can override using the
`.groups` argument.
# A tibble: 1,113 x 4
month dest nb pourcentage
<int> <chr> <int> <dbl>
1 1 ALB 64 0.0190
2 1 ATL 1396 0.415
3 1 AUS 169 0.0502
4 1 AVL 2 0.000594
5 1 BDL 37 0.0110
6 1 BHM 25 0.00742
7 1 BNA 399 0.118
8 1 BOS 1245 0.370
9 1 BQN 93 0.0276
10 1 BTV 223 0.0662
# i 1,103 more rows
flights |>
count(month, dest)
# A tibble: 1,113 x 3
month dest n
<int> <chr> <int>
1 1 ALB 64
2 1 ATL 1396
3 1 AUS 169
4 1 AVL 2
5 1 BDL 37
6 1 BHM 25
7 1 BNA 399
8 1 BOS 1245
9 1 BQN 93
10 1 BTV 223
# i 1,103 more rows
118
8.4 Cheatsheet
8.5 webin-R
119
9 Facteurs et forcats
Ĺ Note
120
[1] nord sud sud est est est
Levels: est nord sud
x |>
factor(levels = c("nord", "est", "sud", "ouest"))
Si une valeur observée dans les données n’est pas indiqué dans
levels, elle sera silencieusement convertie en valeur manquante
(NA).
x |>
factor(levels = c("nord", "sud"))
x |>
readr::parse_factor(levels = c("nord", "sud"))
121
[1] nord sud sud <NA> <NA> <NA>
attr(,"problems")
# A tibble: 3 x 4
row col expected actual
<int> <int> <chr> <chr>
1 4 NA value in level set est
2 5 NA value in level set est
3 6 NA value in level set est
Levels: nord sud
f <- factor(x)
levels(f)
class(f)
[1] "factor"
122
typeof(f)
[1] "integer"
[Link](f)
[1] 2 3 3 1 1 1
[Link](f)
library(tidyverse)
data("hdv2003", package = "questionr")
hdv2003$qualif |>
levels()
123
hdv2003$qualif |>
questionr::freq()
n % val%
Ouvrier specialise 203 10.2 12.3
Ouvrier qualifie 292 14.6 17.7
Technicien 86 4.3 5.2
Profession intermediaire 160 8.0 9.7
Cadre 260 13.0 15.7
Employe 594 29.7 35.9
Autre 58 2.9 3.5
NA 347 17.3 NA
hdv2003$qualif |>
fct_rev() |>
questionr::freq()
n % val%
Autre 58 2.9 3.5
Employe 594 29.7 35.9
Cadre 260 13.0 15.7
Profession intermediaire 160 8.0 9.7
Technicien 86 4.3 5.2
Ouvrier qualifie 292 14.6 17.7
Ouvrier specialise 203 10.2 12.3
NA 347 17.3 NA
124
hdv2003$qualif |>
fct_relevel("Cadre", "Autre", "Technicien", "Employe") |>
questionr::freq()
n % val%
Cadre 260 13.0 15.7
Autre 58 2.9 3.5
Technicien 86 4.3 5.2
Employe 594 29.7 35.9
Ouvrier specialise 203 10.2 12.3
Ouvrier qualifie 292 14.6 17.7
Profession intermediaire 160 8.0 9.7
NA 347 17.3 NA
hdv2003$qualif |>
fct_infreq() |>
questionr::freq()
n % val%
Employe 594 29.7 35.9
Ouvrier qualifie 292 14.6 17.7
Cadre 260 13.0 15.7
Ouvrier specialise 203 10.2 12.3
Profession intermediaire 160 8.0 9.7
Technicien 86 4.3 5.2
Autre 58 2.9 3.5
NA 347 17.3 NA
hdv2003$qualif |>
fct_infreq() |>
fct_rev() |>
125
questionr::freq()
n % val%
Autre 58 2.9 3.5
Technicien 86 4.3 5.2
Profession intermediaire 160 8.0 9.7
Ouvrier specialise 203 10.2 12.3
Cadre 260 13.0 15.7
Ouvrier qualifie 292 14.6 17.7
Employe 594 29.7 35.9
NA 347 17.3 NA
[1] c a d b a c
Levels: a b c d
fct_inorder(v)
[1] c a d b a c
Levels: c a d b
hdv2003$qualif_tri_age <-
hdv2003$qualif |>
fct_reorder(hdv2003$age, .fun = mean)
hdv2003 |>
dplyr::group_by(qualif_tri_age) |>
126
dplyr::summarise(age_moyen = mean(age))
# A tibble: 8 x 2
qualif_tri_age age_moyen
<fct> <dbl>
1 Technicien 45.9
2 Employe 46.7
3 Autre 47.0
4 Ouvrier specialise 48.9
5 Profession intermediaire 49.1
6 Cadre 49.7
7 Ouvrier qualifie 50.0
8 <NA> 47.9
Ď Astuce
127
Une démonstration en vidéo de cet add-in est disponible
dans le webin-R #05 (recoder des variables) sur [You-
Tube]([Link]
[Link]
hdv2003$sexe |>
questionr::freq()
n % val%
Homme 899 45 45
Femme 1101 55 55
hdv2003$sexe <-
hdv2003$sexe |>
fct_recode(f = "Femme", m = "Homme")
hdv2003$sexe |>
questionr::freq()
n % val%
m 899 45 45
f 1101 55 55
hdv2003$nivetud |>
questionr::freq()
128
n % val%
N'a jamais fait d'etudes 39 2.0 2.1
A arrete ses etudes, avant la derniere annee d'etudes primaires 86 4.3 4.6
Derniere annee d'etudes primaires 341 17.0 18.1
1er cycle 204 10.2 10.8
2eme cycle 183 9.2 9.7
Enseignement technique ou professionnel court 463 23.2 24.5
Enseignement technique ou professionnel long 131 6.6 6.9
Enseignement superieur y compris technique superieur 441 22.0 23.4
NA 112 5.6 NA
hdv2003$instruction <-
hdv2003$nivetud |>
fct_recode(
"primaire" = "N'a jamais fait d'etudes",
"primaire" = "A arrete ses etudes, avant la derniere annee d'etudes primaires",
"primaire" = "Derniere annee d'etudes primaires",
"secondaire" = "1er cycle",
"secondaire" = "2eme cycle",
"technique/professionnel" = "Enseignement technique ou professionnel court",
"technique/professionnel" = "Enseignement technique ou professionnel long",
"supérieur" = "Enseignement superieur y compris technique superieur"
)
hdv2003$instruction |>
questionr::freq()
n % val%
primaire 466 23.3 24.7
secondaire 387 19.4 20.5
technique/professionnel 594 29.7 31.5
supérieur 441 22.0 23.4
NA 112 5.6 NA
Ď Interface graphique
129
générer ensuite le code R correspondant au recodage indi-
qué.
Pour utiliser cette interface, sous RStudio vous pouvez
aller dans le menu Addins (présent dans la barre d’outils
principale) puis choisir Levels recoding. Sinon, vous pouvez
lancer dans la console la fonction questionr::irec() en
lui passant comme paramètre la variable à recoder.
Ď Astuce
130
hdv2003$instruction <-
hdv2003$nivetud |>
fct_collapse(
"primaire" = c(
"N'a jamais fait d'etudes",
"A arrete ses etudes, avant la derniere annee d'etudes primaires",
"Derniere annee d'etudes primaires"
),
"secondaire" = c(
"1er cycle",
"2eme cycle"
),
"technique/professionnel" = c(
"Enseignement technique ou professionnel court",
"Enseignement technique ou professionnel long"
),
"supérieur" = "Enseignement superieur y compris technique superieur"
)
n % val%
primaire 466 23.3 23.3
secondaire 387 19.4 19.4
technique/professionnel 594 29.7 29.7
supérieur 441 22.0 22.0
(manquant) 112 5.6 5.6
131
hdv2003$qualif |>
questionr::freq()
n % val%
Ouvrier specialise 203 10.2 12.3
Ouvrier qualifie 292 14.6 17.7
Technicien 86 4.3 5.2
Profession intermediaire 160 8.0 9.7
Cadre 260 13.0 15.7
Employe 594 29.7 35.9
Autre 58 2.9 3.5
NA 347 17.3 NA
hdv2003$qualif |>
fct_other(keep = c("Technicien", "Cadre", "Employe")) |>
questionr::freq()
n % val%
Technicien 86 4.3 5.2
Cadre 260 13.0 15.7
Employe 594 29.7 35.9
Other 713 35.6 43.1
NA 347 17.3 NA
hdv2003$qualif |>
fct_lump_n(n = 4, other_level = "Autres") |>
questionr::freq()
n % val%
Ouvrier specialise 203 10.2 12.3
Ouvrier qualifie 292 14.6 17.7
Cadre 260 13.0 15.7
Employe 594 29.7 35.9
132
Autres 304 15.2 18.4
NA 347 17.3 NA
hdv2003$qualif |>
fct_lump_min(min = 200, other_level = "Autres") |>
questionr::freq()
n % val%
Ouvrier specialise 203 10.2 12.3
Ouvrier qualifie 292 14.6 17.7
Cadre 260 13.0 15.7
Employe 594 29.7 35.9
Autres 304 15.2 18.4
NA 347 17.3 NA
v <- factor(
c("a", "a", "b", "a"),
levels = c("a", "b", "c")
)
questionr::freq(v)
n % val%
a 3 75 75
b 1 25 25
c 0 0 0
133
[1] a a b a
Levels: a b c
v |> fct_drop()
[1] a a b a
Levels: a b
[1] a a b a
Levels: a b c
[1] a a b a
Levels: a b c d e
134
• [Link] et right influent sur la manière dont
les valeurs situées à la frontière des classes seront inclues
ou exclues ;
• [Link] indique le nombre de chiffres après la virgule à
conserver dans les noms de modalités.
hdv2003 <-
hdv2003 |>
mutate(groupe_ages = cut(age, 5))
hdv2003$groupe_ages |> questionr::freq()
n % val%
(17.9,33.8] 454 22.7 22.7
(33.8,49.6] 628 31.4 31.4
(49.6,65.4] 556 27.8 27.8
(65.4,81.2] 319 16.0 16.0
(81.2,97.1] 43 2.1 2.1
hdv2003 <-
hdv2003 |>
mutate(groupe_ages = cut(age, c(18, 20, 40, 60, 80, 97)))
hdv2003$groupe_ages |> questionr::freq()
n % val%
(18,20] 55 2.8 2.8
(20,40] 660 33.0 33.3
(40,60] 780 39.0 39.3
(60,80] 436 21.8 22.0
(80,97] 52 2.6 2.6
135
NA 17 0.9 NA
Les symboles dans les noms attribués aux classes ont leur im-
portance : ( signifie que la frontière de la classe est exclue,
tandis que [ signifie qu’elle est incluse. Ainsi, (20,40] signifie
« strictement supérieur à 20 et inférieur ou égal à 40 ».
On remarque que du coup, dans notre exemple précédent, la va-
leur minimale, 18, est exclue de notre première classe, et qu’une
observation est donc absente de ce découpage. Pour résoudre
ce problème on peut soit faire commencer la première classe à
17, soit utiliser l’option [Link]=TRUE :
hdv2003 <-
hdv2003 |>
mutate(groupe_ages = cut(
age,
c(18, 20, 40, 60, 80, 97),
[Link] = TRUE
))
hdv2003$groupe_ages |> questionr::freq()
n % val%
[18,20] 72 3.6 3.6
(20,40] 660 33.0 33.0
(40,60] 780 39.0 39.0
(60,80] 436 21.8 21.8
(80,97] 52 2.6 2.6
hdv2003 <-
hdv2003 |>
mutate(groupe_ages = cut(
age,
c(18, 20, 40, 60, 80, 97),
[Link] = TRUE,
right = FALSE
))
136
hdv2003$groupe_ages |> questionr::freq()
n % val%
[18,20) 48 2.4 2.4
[20,40) 643 32.1 32.1
[40,60) 793 39.6 39.6
[60,80) 454 22.7 22.7
[80,97] 62 3.1 3.1
Ď Interface graphique
137
Une démonstration en vidéo de cet add-in est disponible
dans le webin-R #05 (recoder des variables) sur [You-
Tube]([Link]
[Link]
138
10 Combiner plusieurs
variables
library(tidyverse)
data("hdv2003", package = "questionr")
10.1 if_else()
139
hdv2003 <-
hdv2003 |>
mutate(
statut = if_else(
sexe == "Homme" & age > 60,
"Homme de plus de 60 ans",
"Autre"
)
)
hdv2003 |>
pull(statut) |>
questionr::freq()
n % val%
Autre 1778 88.9 88.9
Homme de plus de 60 ans 222 11.1 11.1
df <- tibble(
sexe = c("f", "f", "h", "h"),
pref_f = c("a", "b", NA, NA),
pref_h = c(NA, NA, "c", "d"),
mesure = c(1.2, 4.1, 3.8, 2.7)
)
df
# A tibble: 4 x 4
sexe pref_f pref_h mesure
140
<chr> <chr> <chr> <dbl>
1 f a <NA> 1.2
2 f b <NA> 4.1
3 h <NA> c 3.8
4 h <NA> d 2.7
df <-
df |>
mutate(
pref = if_else(sexe == "f", pref_f, pref_h),
indicateur = if_else(sexe == "h", mesure - 0.4, mesure - 0.6)
)
df
# A tibble: 4 x 6
sexe pref_f pref_h mesure pref indicateur
<chr> <chr> <chr> <dbl> <chr> <dbl>
1 f a <NA> 1.2 a 0.6
2 f b <NA> 4.1 b 3.5
3 h <NA> c 3.8 c 3.4
4 h <NA> d 2.7 d 2.3
ĺ if_else() et ifelse()
141
10.2 case_when()
hdv2003 <-
hdv2003 |>
mutate(
statut = case_when(
age >= 60 & sexe == "Homme" ~ "Homme, 60 et plus",
age >= 60 & sexe == "Femme" ~ "Femme, 60 et plus",
TRUE ~ "Autre"
)
)
hdv2003 |>
pull(statut) |>
questionr::freq()
n % val%
Autre 1484 74.2 74.2
Femme, 60 et plus 278 13.9 13.9
Homme, 60 et plus 238 11.9 11.9
142
ĺ Important
hdv2003 <-
hdv2003 |>
mutate(
statut = case_when(
sexe == "Homme" ~ "Homme",
age >= 60 & sexe == "Homme" ~ "Homme, 60 et plus",
TRUE ~ "Autre"
)
)
hdv2003 |>
pull(statut) |>
questionr::freq()
n % val%
Autre 1101 55 55
Homme 899 45 45
143
hdv2003 <-
hdv2003 |>
mutate(
statut = case_when(
age >= 60 & sexe == "Homme" ~ "Homme, 60 et plus",
sexe == "Homme" ~ "Homme",
TRUE ~ "Autre"
)
)
hdv2003 |>
pull(statut) |>
questionr::freq()
n % val%
Autre 1101 55.0 55.0
Homme 661 33.1 33.1
Homme, 60 et plus 238 11.9 11.9
10.3 recode_if()
df <- tibble(
pref = factor(c("bleu", "rouge", "autre", "rouge", "autre")),
autre_details = c(NA, NA, "bleu ciel", NA, "jaune")
)
df
# A tibble: 5 x 2
pref autre_details
<fct> <chr>
1 bleu <NA>
144
2 rouge <NA>
3 autre bleu ciel
4 rouge <NA>
5 autre jaune
df |>
mutate(pref = if_else(autre_details == "bleu ciel", "bleu", pref))
# A tibble: 5 x 2
pref autre_details
<chr> <chr>
1 <NA> <NA>
2 <NA> <NA>
3 bleu bleu ciel
4 <NA> <NA>
5 autre jaune
df |>
mutate(pref = if_else(autre_details == "bleu ciel", factor("bleu"), pref))
145
# A tibble: 5 x 2
pref autre_details
<fct> <chr>
1 <NA> <NA>
2 <NA> <NA>
3 bleu bleu ciel
4 <NA> <NA>
5 autre jaune
df |>
mutate(pref = if_else(
autre_details != "bleu ciel",
pref,
factor("bleu")
))
# A tibble: 5 x 2
pref autre_details
<fct> <chr>
1 <NA> <NA>
2 <NA> <NA>
3 bleu bleu ciel
4 <NA> <NA>
5 autre jaune
146
Dès lors, il nous faut soit définir l’argument missing de
dplyr::if_else(), soit être plus précis dans notre test.
df |>
mutate(pref = if_else(
autre_details != "bleu ciel",
pref,
factor("bleu"),
missing = pref
))
# A tibble: 5 x 2
pref autre_details
<fct> <chr>
1 bleu <NA>
2 rouge <NA>
3 bleu bleu ciel
4 rouge <NA>
5 autre jaune
df |>
mutate(pref = if_else(
autre_details != "bleu ciel" | [Link](autre_details),
pref,
factor("bleu")
))
# A tibble: 5 x 2
pref autre_details
<fct> <chr>
1 bleu <NA>
2 rouge <NA>
3 bleu bleu ciel
4 rouge <NA>
5 autre jaune
147
en base R fonctionne très bien, mais ne peut pas être intégrée
à un enchaînement d’opérations utilisant le pipe.
Dans ce genre de situation, on pourra être intéressé par la
fonction labelled::recode_if() disponible dans le package
{labelled}. Elle permet de ne modifier que certaines observa-
tions d’un vecteur en fonction d’une condition. Si la condition
vaut FALSE ou NA, les observations concernées restent inchan-
gées. Voyons comment cela s’écrit :
df <-
df |>
mutate(
pref = pref |>
labelled::recode_if(autre_details == "bleu ciel", "bleu")
)
df
# A tibble: 5 x 2
pref autre_details
<fct> <chr>
1 bleu <NA>
2 rouge <NA>
3 bleu bleu ciel
4 rouge <NA>
5 autre jaune
148
11 Étiquettes de variables
11.1 Principe
149
Figure 11.1: Présentation du tableau gtsummary::trial dans
la visionneuse de RStudio
library(labelled)
gtsummary::trial |>
look_for()
gtsummary::trial |>
look_for("months")
150
pos variable label col_type missing values
8 ttdeath Months to Death/Censor dbl 0
Ď Astuce
gtsummary::trial |>
look_for() |>
dplyr::as_tibble()
# A tibble: 8 x 7
pos variable label col_type missing levels value_labels
<int> <chr> <chr> <chr> <int> <named li> <named list>
1 1 trt Chemotherapy Treatment chr 0 <NULL> <NULL>
2 2 age Age dbl 11 <NULL> <NULL>
3 3 marker Marker Level (ng/mL) dbl 10 <NULL> <NULL>
4 4 stage T Stage fct 0 <chr [4]> <NULL>
5 5 grade Grade fct 0 <chr [3]> <NULL>
6 6 response Tumor Response int 7 <NULL> <NULL>
7 7 death Patient Died int 0 <NULL> <NULL>
8 8 ttdeath Months to Death/Censor dbl 0 <NULL> <NULL>
151
de variable à n’importe quel type de variable, qu’elle soit nu-
mérique, textuelle, un facteur ou encore des dates.
v <- c(1, 5, 2, 4, 1)
v |> var_label()
NULL
str(v)
num [1:5] 1 5 2 4 1
- attr(*, "label")= chr "Mon étiquette"
str(v)
num [1:5] 1 5 2 4 1
- attr(*, "label")= chr "Une autre étiquette"
152
num [1:5] 1 5 2 4 1
iris <-
iris |>
set_variable_labels(
Species = NULL,
[Link] = "Longeur du sépale"
)
iris |>
look_for()
153
3 [Link] Longueur du pétale dbl 0
4 [Link] Largeur du pétale dbl 0
5 Species — fct 0 setosa
versicolor
virginica
iris |>
look_for()
iris |>
subset(Species == "setosa") |>
look_for()
154
On pourra, dans ce cas précis, préférer la fonction
dplyr::filter() qui préserve les attributs et donc les
étiquettes de variables.
iris |>
dplyr::filter(Species == "setosa") |>
look_for()
iris |>
subset(Species == "setosa") |>
copy_labels_from(iris) |>
look_for()
155
12 Étiquettes de valeurs
156
ĺ Important
library(labelled)
v <- c(1, 2, 1, 9)
v
[1] 1 2 1 9
class(v)
[1] "numeric"
157
val_labels(v)
NULL
non oui
1 2
<labelled<double>[4]>
[1] 1 2 1 9
Labels:
value label
1 non
2 oui
class(v)
158
val_label(v, 1)
[1] "non"
val_label(v, 9)
NULL
<labelled<double>[4]>
[1] 1 2 1 9
Labels:
value label
1 non
9 (manquant)
[1] 1 2 1 9
class(v)
[1] "numeric"
159
¾ Mise en garde
v <- c(1, 2, 1, 2)
val_labels(v) <- c(non = 1, oui = 2)
mean(v)
[1] 1.5
[1] NA
df <- dplyr::tibble(
x = c(1, 2, 1, 2),
y = c(3, 9, 9, 3)
)
val_labels(df$x) <- c(non = 1, oui = 2)
val_label(df$y, 9) <- "(manquant)"
df
# A tibble: 4 x 2
x y
<dbl+lbl> <dbl+lbl>
1 1 [non] 3
160
2 2 [oui] 9 [(manquant)]
3 1 [non] 9 [(manquant)]
4 2 [oui] 3
df |>
look_for()
df |>
look_for()
161
df <- df |>
set_value_labels(
x = c(yes = 2),
y = c("a répondu" = 3, "refus de répondre" = 9)
)
df |>
look_for()
df <- df |>
add_value_labels(
x = c(no = 1)
) |>
remove_value_labels(
y = 9
)
df |>
look_for()
12.4 Conversion
162
Mais il faut noter que ces étiquettes de valeur n’indique pas
pour autant de manière systématique le type de variable (ca-
tégorielle ou continue). Les vecteurs labellisés n’ont donc pas
vocation à être utilisés pour l’analyse, notamment le calcul de
modèles statistiques. Ils doivent être convertis en facteurs (pour
les variables catégorielles) ou en vecteurs numériques (pour les
variables continues).
La question qui peut se poser est donc de choisir à quel moment
cette conversion doit avoir lieu dans un processus d’analyse. On
peut considérer deux approches principales.
163
l’approche A, il faudra prévoir une conversion des variables
labellisées au moment de l’analyse.
Á Avertissement
<labelled<double>[7]>
[1] 1 2 9 3 3 2 NA
Labels:
value label
1 oui
2 peut-être
3 non
9 ne sait pas
to_factor(v)
164
Il possible d’indiquer si l’on souhaite, comme étiquettes du fac-
teur, utiliser les étiquettes de valeur (par défaut), les valeurs
elles-mêmes, ou bien les étiquettes de valeurs préfixées par la
valeur d’origine indiquée entre crochets.
to_factor(v, 'l')
to_factor(v, 'v')
[1] 1 2 9 3 3 2 <NA>
Levels: 1 2 3 9
to_factor(v, 'p')
[1] [1] oui [2] peut-être [9] ne sait pas [3] non
[5] [3] non [2] peut-être <NA>
Levels: [1] oui [2] peut-être [3] non [9] ne sait pas
165
12.4.3 Convertir un vecteur labellisé en numérique ou
en texte
unclass(x)
[1] 1 2 9 3 3 2 NA
attr(,"labels")
oui peut-être non ne sait pas
1 2 3 9
unclass(y)
166
Une alternative est d’utiliser labelled::remove_labels() qui
supprimera toutes les étiquettes, y compris les étiquettes de va-
riable. Pour conserver les étiquettes de variables et ne suppri-
mer que les étiquettes de valeurs, on indiquera keep_var_label
= TRUE.
[1] 1 2 9 3 3 2 NA
[1] 1 2 9 3 3 2 NA
attr(,"label")
[1] "Etiquette de variable"
remove_labels(y)
to_character(x)
167
12.4.4 Conversion conditionnelle en facteurs
df <- dplyr::tibble(
a = c(1, 1, 2, 3),
b = c(1, 1, 2, 3),
c = c(1, 1, 2, 2),
d = c("a", "a", "b", "c"),
e = c(1, 9, 1, 2),
f = 1:4,
g = [Link](c(
"2020-01-01", "2020-02-01",
"2020-03-01", "2020-04-01"
))
) |>
set_value_labels(
a = c(No = 1, Yes = 2),
168
b = c(No = 1, Yes = 2, DK = 3),
c = c(No = 1, Yes = 2, DK = 3),
d = c(No = "a", Yes = "b"),
e = c(No = 1, Yes = 2)
)
df |> look_for()
169
5 e — fct 0 No
Yes
9
6 f — int 0
7 g — date 0
170
unlabelled(df, levels = "prefixed") |>
look_for()
171
13 Valeurs manquantes
172
uniquement sur les réponses valides, en fonction du besoin de
l’analyse et de ce que l’on cherche à montrer.
Afin d’éviter toute perte d’informations lors d’un import de
données depuis Stata, SAS et SPSS, le package {haven} pro-
pose une implémentation sous R des tagged NAs et des user
NAs. Le package {labelled} fournit quant à lui différentes
fonctions pour les manipuler aisément.
library(labelled)
[1] 1 2 3 NA NA NA
[Link](x)
173
Pour afficher les étiquettes associées à ces valeurs man-
quantes, il faut avoir recours à labelled::na_tag(),
labelled::print_tagged_na() ou encore labelled::format_tagged_na().
na_tag(x)
print_tagged_na(x)
format_tagged_na(x)
[1] " 1" " 2" " 3" "NA(a)" "NA(z)" " NA"
[Link](x)
is_regular_na(x)
is_tagged_na(x)
174
is_tagged_na(x, "a")
Ĺ Note
is_tagged_na(y)
format_tagged_na(y)
[1] "double"
format_tagged_na(z)
175
13.1.2 Valeurs uniques, doublons et tris
x |>
unique() |>
print_tagged_na()
[1] 1 2 NA(a)
x |>
unique_tagged_na() |>
print_tagged_na()
x |>
duplicated()
176
x |>
duplicated_tagged_na()
x |>
sort([Link] = TRUE) |>
print_tagged_na()
x |>
sort_tagged_na() |>
print_tagged_na()
x <- c(
1, 0,
1, tagged_na("r"),
0, tagged_na("d"),
tagged_na("z"), NA
)
val_labels(x) <- c(
no = 0,
yes = 1,
"don't know" = tagged_na("d"),
refusal = tagged_na("r")
)
x
177
<labelled<double>[8]>
[1] 1 0 1 NA(r) 0 NA(d) NA(z) NA
Labels:
value label
0 no
1 yes
NA(d) don't know
NA(r) refusal
x |> to_factor()
x |>
to_factor(explicit_tagged_na = TRUE)
x |>
to_factor(
levels = "prefixed",
explicit_tagged_na = TRUE
)
178
[1] [1] yes [0] no [1] yes [NA(r)] refusal
[5] [0] no [NA(d)] don't know [NA(z)] NA(z) <NA>
Levels: [0] no [1] yes [NA(d)] don't know [NA(r)] refusal [NA(z)] NA(z)
x |>
tagged_na_to_user_na()
<labelled_spss<double>[8]>
[1] 1 0 1 3 0 2 4 NA
Missing range: [2, 4]
Labels:
value label
0 no
1 yes
2 don't know
3 refusal
4 NA(z)
x |>
tagged_na_to_user_na(user_na_start = 10)
<labelled_spss<double>[8]>
[1] 1 0 1 11 0 10 12 NA
Missing range: [10, 12]
Labels:
value label
0 no
1 yes
10 don't know
11 refusal
12 NA(z)
179
La fonction labelled::tagged_na_to_regular_na() conver-
tit les tagged NAs en valeurs manquantes classiques (regular
NAs).
x |>
tagged_na_to_regular_na()
<labelled<double>[8]>
[1] 1 0 1 NA 0 NA NA NA
Labels:
value label
0 no
1 yes
x |>
tagged_na_to_regular_na() |>
is_tagged_na()
ĺ Important
180
Il convient de garder en mémoire que la très grande ma-
jorité des fonctions de R ne prendront pas en compte ces
métadonnées et traiteront donc ces valeurs comme des va-
leurs valides. C’est donc à l’utilisateur de convertir, au
besoin, ces les valeurs indiquées comme manquantes en
réelles valeurs manquantes (NA).
13.2.1 Création
<labelled_spss<double>[8]>
[1] 1 2 3 9 1 3 2 NA
Missing values: 9
Labels:
value label
1 faible
3 fort
9 ne sait pas
181
na_values(v) <- NULL
v
<labelled<double>[8]>
[1] 1 2 3 9 1 3 2 NA
Labels:
value label
1 faible
3 fort
9 ne sait pas
<labelled_spss<double>[8]>
[1] 1 2 3 9 1 3 2 NA
Missing range: [5, Inf]
Labels:
value label
1 faible
3 fort
9 ne sait pas
On peut noter que les user NAs peuvent cohabiter avec des
regular NAs ainsi qu’avec des étiquettes de valeurs (value labels,
cf. Chapitre 12).
Pour manipuler les variables d’un tableau de données, on peut
également avoir recours à labelled::set_na_values() et
labelled::set_na_range().
df <-
dplyr::tibble(
s1 = c("M", "M", "F", "F"),
s2 = c(1, 1, 2, 9)
) |>
182
set_na_values(s2 = 9)
df$s2
<labelled_spss<double>[4]>
[1] 1 1 2 9
Missing values: 9
df <-
df |>
set_na_values(s2 = NULL)
df$s2
<labelled<double>[4]>
[1] 1 1 2 9
13.2.2 Tests
<labelled_spss<double>[8]>
[1] 1 2 3 9 1 3 2 NA
Missing range: [5, Inf]
Labels:
value label
1 faible
3 fort
9 ne sait pas
v |> [Link]()
183
v |> is_user_na()
v |> is_regular_na()
13.2.3 Conversion
<labelled_spss<integer>[10]>
[1] 1 2 3 4 5 11 12 13 14 15
Missing range: [10, Inf]
mean(x)
[1] 8
x |>
user_na_to_na()
<labelled<integer>[10]>
[1] 1 2 3 4 5 NA NA NA NA NA
184
x |>
user_na_to_na() |>
mean([Link] = TRUE)
[1] 3
x |>
user_na_to_tagged_na() |>
print_tagged_na()
x |>
user_na_to_tagged_na() |>
mean([Link] = TRUE)
[1] 3
x |>
remove_user_na()
<labelled<integer>[10]>
[1] 1 2 3 4 5 11 12 13 14 15
185
x |>
remove_user_na() |>
mean()
[1] 8
x <- c(1, 2, 9, 2)
val_labels(x) <- c(oui = 1, non = 2, refus = 9)
na_values(x) <- 9
x |>
to_factor(user_na_to_na = TRUE)
x |>
to_factor(user_na_to_na = FALSE)
186
14 Import & Export de
données
187
• Pour les variables textuelles, y a-t-il des valeurs man-
quantes et si oui comment sont-elles indiquées ? Par
exemple, le texte NA est parfois utilisé.
188
Vous pourrez remarquer que RStudio fait appel à l’extension
{readr} du tidyverse pour l’import des données via la fonction
readr::read_csv().
{readr} essaie de deviner le type de chacune des colonnes, en
se basant sur les premières observations. En cliquant sur le nom
d’une colonne, il est possible de modifier le type de la variable
importée. Il est également possible d’exclure une colonne de
l’import (skip).
library(readr)
d <- read_delim(
"[Link]
delim = "\t",
quote = "'"
)
189
Dans des manuels ou des exemples en ligne, vous trou-
verez parfois mention des fonctions utils::[Link](),
utils::[Link](), utils::read.csv2(), utils::[Link]()
ou encore utils::read.delim2(). Il s’agit des fonctions na-
tives et historiques de R (extension {utils}) dédiées à
l’import de fichiers textes. Elles sont similaires à celles de
{readr} dans l’idée générale mais diffèrent dans leurs détails
et les traitements effectués sur les données (pas de détection
des dates par exemple). Pour plus d’information, vous pouvez
vous référer à la page d’aide de ces fonctions.
library(readxl)
donnees <- read_excel("data/[Link]")
190
on pourra indiquer le type souhaité de chaque colonne avec
col_types.
RStudio propose également pour les fichiers Excel un assis-
tant d’importation, similaire à celui pour les fichiers texte, per-
mettant de faciliter l’import.
14.3.1 SPSS
Les fichiers générés par SPSS sont de deux types : les fichiers
SPSS natifs (extension .sav) et les fichiers au format SPSS
export (extension .por).
Dans les deux cas, on aura recours à la fonction haven::read_spss() :
library(haven)
donnees <- read_spss("data/[Link]", user_na = TRUE)
191
Ď Valeurs manquantes
14.3.2 SAS
library(haven)
donnees <- read_sas("data/fichier.sas7bdat")
library(haven)
donnees <- read_sas(
"data/fichier.sas7bdat",
catalog_file = "data/fichier.sas7bcat"
)
Ĺ Note
192
library(foreign)
donnees <- [Link]("data/[Link]")
14.3.3 Stata
library(haven)
donnees <- read_dta("data/[Link]")
ĺ Important
14.3.4 dBase
library(foreign)
donnees <- [Link]("data/[Link]")
193
un même fichier. L’usage est d’utiliser l’extension .RData pour
les fichiers de données R. La fonction à utiliser s’appelle tout
simplement save().
Par exemple, si l’on souhaite sauvegarder son tableau de don-
nées d ainsi que les objets tailles et poids dans un fichier
[Link] :
load("[Link]")
¾ Mise en garde
[Link]()
194
donnees <- readRDS("mes_donnees.rds")
195
15 Mettre en forme des
nombres
library(scales)
x <- c(0.0023, .123, 4.567, 874.44, 8957845)
number(x)
f <- label_number()
f(x)
label_number()(x)
196
[1] "0.00" "0.12" "4.57" "874.44" "8 957 845.00"
15.1 label_number()
label_number(accuracy = NULL)(x)
label_number(accuracy = .1)(x)
label_number(accuracy = .25)(x)
197
label_number(accuracy = 10)(x)
198
label_number(accuracy = 10^-9, [Link] = "|", [Link] = 3)(x)
label_number(style_negative = "parens")(y)
[1] "4.5 µg" "12.4 mg" "2.3 g" "47.6 kg" "789.5 Mg"
15.2.1 label_comma()
199
label_comma()(x)
15.2.2 label_percent()
label_percent()(x)
15.2.3 label_dollar()
label_dollar()(x)
label_dollar(prefix = "", suffix = " €", accuracy = .01, [Link] = " ")(x)
200
[1] "0.00 €" "0.12 €" "4.57 €" "874.44 €"
[5] "8 957 845.00 €"
15.2.4 label_pvalue()
15.2.5 label_scientific()
201
15.2.6 label_bytes()
label_bytes(units = "auto_binary")(b)
15.2.7 label_ordinal()
label_ordinal()(1:5)
label_ordinal(rules = ordinal_french())(1:5)
202
15.2.8 label_date(), label_date_short() &
label_time()
scales::label_date(), scales::label_date_short() et
scales::label_time() peuvent être utilisées pour la mise en
forme de dates.
label_date()([Link]("2020-02-14"))
[1] "2020-02-14"
label_date(format = "%d/%m/%Y")([Link]("2020-02-14"))
[1] "14/02/2020"
label_date_short()([Link]("2020-02-14"))
[1] "14\nfévr.\n2020"
15.2.9 label_wrap()
x <- "Ceci est un texte assez long et que l'on souhaiterait afficher sur plusieurs lignes. C
label_wrap(80)(x)
[1] "Ceci est un texte assez long et que l'on souhaiterait afficher sur plusieurs\nlignes. Cepe
203
label_wrap(80)(x) |> message()
Ceci est un texte assez long et que l'on souhaiterait afficher sur plusieurs
lignes. Cependant, on souhaite éviter que des coupures apparaissent au milieu
d'un mot.
15.3.1 style_number()
library(gtsummary)
x <- c(0.123, 0.9, 1.1234, 12.345, -0.123, -0.9, -1.1234, -132.345)
style_number(x, digits = 1)
204
[1] "0.1" "0.9" "1.1" "12.3" "-0.1" "-0.9" "-1.1" "-132.3"
Ď Astuce
¾ Mise en garde
15.3.2 style_sigfig()
205
style_sigfig(x)
style_sigfig(x, digits = 3)
15.3.3 style_percent()
style_percent(v)
style_percent(v, digits = 1)
206
15.3.4 style_pvalue()
style_pvalue(p)
15.3.5 style_ratio()
r <- c(0.123, 0.9, 1.1234, 12.345, 101.234, -0.123, -0.9, -1.1234, -12.345, -101.234)
style_ratio(r)
[1] "0.12" "0.90" "1.12" "12.3" "101" "-0.12" "-0.90" "-1.12" "-12.3"
[10] "-101"
207
15.4 Bonus : signif_stars() de {ggstats}
15.5
208
16 Couleurs & Palettes
library(tidyverse)
ggplot(iris) +
aes(x = [Link]) +
geom_histogram(colour = "red", fill = "blue")
209
20
count
10
0
2 4 6
[Link]
ggplot(iris) +
aes(x = [Link]) +
geom_histogram(colour = "#666666", fill = "#FF0000")
210
20
count
10
0
2 4 6
[Link]
[1] "#FF0000"
211
YlOrRd
YlOrBr
YlGnBu
YlGn
Reds
RdPu
Purples
PuRd
PuBuGn
PuBu
OrRd
Oranges
Greys
Greens
GnBu
BuPu
BuGn
Blues
Set3
Set2
Set1
Pastel2
Pastel1
Paired
Dark2
Accent
Spectral
RdYlGn
RdYlBu
RdGy
RdBu
PuOr
PRGn
PiYG
BrBG
¾ Mise en garde
212
16.3.2 Palettes de Paul Tol
library(khroma)
plot_scheme(colour("bright")(7), colours = TRUE)
ggplot(mpg) +
aes(x = displ, y = hwy, colour = class) +
geom_point() +
khroma::scale_colour_bright()
213
40
class
2seater
compact
30 midsize
hwy
minivan
pickup
subcompact
20
suv
2 3 4 5 6 7
displ
214
#762A83 #C2A5CF #F7F7F7 #ACD39E #1B7837
#9970AB #E7D4E8 #D9F0D3 #5AAE61 #FFEE99
gt::info_paletteer()
215
paletteer::scale_color_paletteer_d() et paletteer::scale_fill_paletteer_d()
permettront d’utiliser une palette donnée avec {ggplot2}.
library(paletteer)
paletteer_d("khroma::bright", n = 5)
<colors>
#4477AAFF #EE6677FF #228833FF #CCBB44FF #66CCEEFF
ggplot(mpg) +
aes(x = displ, y = hwy, colour = class) +
geom_point() +
scale_color_paletteer_d("khroma::bright")
40
class
2seater
compact
30 midsize
hwy
minivan
pickup
subcompact
20
suv
2 3 4 5 6 7
displ
paletteer_c("viridis::viridis", n = 6)
<colors>
#440154FF #414487FF #2A788EFF #22A884FF #7AD151FF #FDE725FF
216
ggplot(iris) +
aes(x = [Link], y = [Link], colour = [Link]) +
geom_point() +
scale_colour_paletteer_c("viridis::viridis", direction = -1)
4.5
4.0
[Link]
[Link]
3.5 6
5
4
3.0
3
2
1
2.5
2.0
5 6 7 8
[Link]
217
partie III
Analyses
218
17 Graphiques avec ggplot2
17.1 Ressources
219
tidy, c’est-à-dire avec une ligne par observation et les différentes
valeurs à représenter sous forme de variables du tableau.
220
des points, ggplot2::geom_line() pour des lignes,
ggplot2::geom_bar() pour des barres ou encore ggplot2::geom_area()
pour des aires. Il existe de nombreuses géométries différentes21 , 21
On trouvera une liste dans la cheat
chacune prenant en compte certaines esthétiques, certaines sheet de {ggplot2}, voir Section 17.3.
étant requises pour cette géométrie et d’autres optionnelles.
La liste des esthétiques prises en compte par chaque géométrie
est indiquée dans l’aide en ligne de cette dernière.
Voici un exemple minimal de graphique avec {ggplot2} :
library(ggplot2)
p <-
ggplot(iris) +
aes(
x = [Link],
y = [Link],
colour = Species
) +
geom_point()
p
2.5
2.0
Species
[Link]
1.5
setosa
versicolor
1.0 virginica
0.5
0.0
2 4 6
[Link]
221
ĺ Syntaxe additive
p +
labs(
x = "Longueur du pétale",
y = "Largeur du pétale",
colour = "Espèce"
) +
ggtitle(
"Relation entre longueur et largeur des pétales",
subtitle = "Jeu de données Iris"
) +
scale_x_continuous(breaks = 1:7) +
scale_y_continuous(
222
labels = scales::label_number([Link] = ",")
) +
coord_equal() +
facet_grid(cols = vars(Species)) +
guides(
color = guide_legend(nrow = 2)
) +
theme_light() +
theme(
[Link] = "bottom",
[Link] = element_text(face = "bold")
)
setosa virginica
Espèce
versicolor
223
Figure 17.4: Cheatsheet ggplot2
17.3 Cheatsheet
224
Figure 17.6: Import de données au lancement d’esquisse
225
modifier les échelles de couleurs et l’apparence du graphique,
et de filtrer les observations inclues dans le graphique.
Le menu Code permet de récupérer le code correspondant au
graphique afin de pouvoir le copier/coller dans un script.
17.5 webin-R
226
17.6 Combiner plusieurs graphiques
p1 <- ggplot(mtcars) +
aes(x = wt, y = mpg) +
geom_point()
p2 <- ggplot(mtcars) +
aes(x = factor(cyl)) +
geom_bar()
p3 <- ggplot(mtcars) +
aes(x = factor(cyl), y = mpg) +
geom_violin() +
theme([Link] = element_text(size = 20))
p4 <- ggplot(mtcars) +
aes(x = factor(cyl), y = mpg) +
geom_boxplot() +
ylab(NULL)
library(patchwork)
p1 + p2 + p3 + p4
227
35
30
10
count
25
mpg
20 5
15
10 0
2 3 4 5 4 6 8
wt factor(cyl)
35 35
30 30
mpg
25 25
20 20
15 15
10 10
4 6 8 4 6 8
factor(cyl) factor(cyl)
p1 | p2 | p3
35 35
30 30
10
25 25
mpg
count
mpg
20 20
5
15 15
10 0 10
2 3 4 5 4 6 8 4 6 8
wt factor(cyl) factor(cyl)
p1 / p2
228
35
30
25
mpg
20
15
10
2 3 4 5
wt
10
count
0
4 6 8
factor(cyl)
(p1 + p2) / p3
35
30
10
count
25
mpg
20 5
15
10 0
2 3 4 5 4 6 8
wt factor(cyl)
35
30
mpg
25
20
15
10
4 6 8
factor(cyl)
(p1 + p2) | p3
229
35 35
30 30
10
25 25
mpg
count
mpg
20 20
5
15 15
10 0 10
2 3 4 5 4 6 8 4 6 8
wt factor(cyl) factor(cyl)
35
30
10
count
25
mpg
20 5
15
10 0
2 3 4 5 4 6 8
wt factor(cyl)
35 35
30 30
mpg
25 25
20 20
15 15
10 10
4 6 8 4 6 8
factor(cyl) factor(cyl)
230
p1 + p2 + p3 + p4 + plot_layout(widths = c(2, 1))
35
30
10
count
25
mpg
20 5
15
10 0
2 3 4 5 4 6 8
wt factor(cyl)
35 35
30 30
mpg
25 25
20 20
15 15
10 10
4 6 8 4 6 8
factor(cyl) factor(cyl)
p1 + p2 + p3 + p4 +
plot_annotation(
title = "Titre du graphique",
subtitle = "sous-titre",
caption = "notes additionelles",
tag_levels = "a",
tag_suffix = "."
)
231
Titre du graphique
sous−titre
a. 35
b.
30
count
10
mpg
25
20 5
15
10 0
2 3 4 5 4 6 8
wt factor(cyl)
c. 35
d. 35
mpg
30 30
25 25
20 20
15 15
10 10
4 6 8 4 6 8
factor(cyl) factor(cyl)
notes additionelles
232
18 Statistique univariée &
Intervalles de confiance
library(ggplot2)
ggplot(iris) +
aes(x = [Link]) +
geom_histogram()
233
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
20
count
10
0
2 4 6
[Link]
Ď Astuce
234
On peut personnaliser la couleur de remplissage des rectangles
en indiquant une valeur fixe pour l’esthétique fill dans
l’appel de ggplot2::geom_histogram() (et non via la fonc-
tion ggplot2::aes() puisqu’il ne s’agit pas d’une variable du
tableau de données). L’esthétique colour permet de spécifier la
couleur du trait des rectangles. Enfin, le paramètre binwidth
permet de spécifier la largeur des barres.
ggplot(iris) +
aes(x = [Link]) +
geom_histogram(
fill ="lightblue",
colour = "black",
binwidth = 1
) +
xlab("Longeur du pétale") +
ylab("Effectifs")
30
Effectifs
20
10
0
2 4 6
Longeur du pétale
235
ggplot(iris) +
aes(x = [Link]) +
geom_histogram(bins = 10, colour = "black")
40
30
count
20
10
0
2 4 6
[Link]
ggplot(iris) +
aes(x = [Link]) +
geom_density(adjust = .5)
236
0.4
0.3
density
0.2
0.1
0.0
2 4 6
[Link]
237
1000
750
count
500
250
0
Exerce une profession
ChomeurEtudiant, eleve RetraiteRetire des affairesAu foyer Autre inactif
occup
Ď Astuce
library(ggstats)
ggplot(hdv2003) +
238
aes(x = occup, y = after_stat(prop), by = 1) +
geom_bar(stat = "prop") +
scale_y_continuous(labels = scales::label_percent())
50%
40%
30%
prop
20%
10%
0%
Exerce une profession
ChomeurEtudiant, eleve RetraiteRetire des affairesAu foyer Autre inactif
occup
ggplot(hdv2003) +
aes(x = forcats::fct_infreq(occup),
y = after_stat(prop), by = 1) +
geom_bar(stat = "prop",
fill = "#4477AA", colour = "black") +
geom_text(
aes(label = after_stat(prop) |>
scales::percent(accuracy = .1)),
stat = "prop",
nudge_y = .02
) +
theme_minimal() +
239
theme(
[Link] = element_blank(),
[Link].y = element_blank()
) +
xlab(NULL) + ylab(NULL) +
ggtitle("Occupation des personnes enquêtées")
19.6%
8.6%
6.7%
4.7% 4.2% 3.8%
240
n’indique rien, toutes les variables du tableau de données
sont considérées). Il faut noter que l’argument include de
gtsummary::tbl_summary() utilise la même syntaxe dite
tidy select que dplyr::select() (cf. Section 8.2.1). On
peut indiquer tout autant des variables catégorielles que des
variables continues.
library(gtsummary)
#Uighur
hdv2003 |>
tbl_summary(include = c(age, occup))
Characteristic N = 2,000
age 48 (35, 60)
occup
Exerce une profession 1,049 (52%)
Chomeur 134 (6.7%)
Etudiant, eleve 94 (4.7%)
Retraite 392 (20%)
Retire des affaires 77 (3.9%)
Au foyer 171 (8.6%)
Autre inactif 83 (4.2%)
241
Par défaut, {gtsummary} considère qu’une variable est ca-
tégorielle s’il s’agit d’un facteur, d’une variable textuelle
ou d’une variable numérique ayant moins de 10 valeurs
différentes.
Une variable sera considérée comme dichotomique (va-
riable catégorielle à seulement deux modalités) s’il s’agit
d’un vecteur logique (TRUE/FALSE), d’une variable tex-
tuelle codée yes/no ou d’une variable numérique codée
0/1.
Dans les autres cas, une variable numérique sera considé-
rée comme continue.
Si vous utilisez des vecteurs labellisés (cf. Cha-
pitre 12), vous devez les convertir, en amont, en
facteurs ou en variables numériques. Voir l’extension
{labelled} et les fonctions labelled::to_factor(),
labelled::unlabelled() et unclass().
Au besoin, il est possible de forcer le type d’une variable
avec l’argument type de gtsummary::tbl_summary().
{gtsummary} fournit des sélecteurs qui peuvent être utili-
sés dans les options des différentes fonctions, en particulier
gtsummary::all_continuous() pour les variables conti-
nues, gtsummary::all_dichotolous() pour les variables
dichotomiques et gtsummary::all_categorical() pour
les variables catégorielles. Cela inclue les variables dicho-
tomiques. Il faut utiliser all_categorical(dichotomous
= FALSE) pour sélectionner les variables catégorielles en
excluant les variables dichotomiques.
242
La fonction gtsummary::theme_gtsummary_language() per-
met de modifier la langue utilisée par défaut dans les tableaux.
Les options [Link] et [Link] permettent de définir
respectivement le séparateur de décimales et le séparateur des
milliers. Ainsi, pour présenter un tableau en français, on appli-
quera en début de script :
theme_gtsummary_language(
language = "fr",
[Link] = ",",
[Link] = " "
)
hdv2003 |>
tbl_summary(include = c(age, occup))
Caractéristique N = 2 000
age 48 (35 – 60)
occup
Exerce une profession 1 049 (52%)
Chomeur 134 (6,7%)
Etudiant, eleve 94 (4,7%)
Retraite 392 (20%)
Retire des affaires 77 (3,9%)
Au foyer 171 (8,6%)
Autre inactif 83 (4,2%)
243
18.2.2 Étiquettes des variables
hdv2003 |>
labelled::set_variable_labels(
occup = "Occupation actuelle"
) |>
tbl_summary(
include = c(age, occup, [Link]),
label = list(age ~ "Âge médian")
)
Caractéristique N = 2 000
Âge médian 48 (35 – 60)
Occupation actuelle
Exerce une profession 1 049 (52%)
Chomeur 134 (6,7%)
Etudiant, eleve 94 (4,7%)
Retraite 392 (20%)
Retire des affaires 77 (3,9%)
Au foyer 171 (8,6%)
Autre inactif 83 (4,2%)
[Link] 2,00 (1,00 – 3,00)
Manquant 5
244
Pour modifier les modalités d’une variable catégorielle, il faut
modifier en amont les niveaux du facteur correspondant.
trial |>
tbl_summary(label = age ~ "Âge")
trial |>
tbl_summary(label = list(age ~ "Âge", trt ~ "Traitement"))
trial |>
tbl_summary(label = age ~ "Âge")
trial |>
tbl_summary(label = "age" ~ "Âge")
v <- "age"
trial |>
tbl_summary(label = v ~ "Âge")
245
trial |>
tbl_summary(label = c("age", "trt") ~ "Une même étiquette")
trial |>
tbl_summary(label = c(age, trt) ~ "Une même étiquette")
trial |>
tbl_summary(
label = everything() ~ "Une même étiquette"
)
trial |>
tbl_summary(
label = starts_with("a") ~ "Une même étiquette"
)
trial |>
tbl_summary(
label = c(everything(), -age, -trt) ~ "Une même étiquette"
)
trial |>
tbl_summary(
label = age:trt ~ "Une même étiquette"
)
246
trial |>
tbl_summary(
label = all_continuous() ~ "Une même étiquette"
)
trial |>
tbl_summary(
label = list(
all_continuous() ~ "Variable continue",
all_dichotomous() ~ "Variable dichotomique",
all_categorical(dichotomous = FALSE) ~ "Variable catégorielle"
)
)
trial |>
tbl_summary(label = ~ "Une même étiquette")
trial |>
tbl_summary(
label = everything() ~ "Une même étiquette"
)
247
hdv2003 |>
tbl_summary(
include = c(age, [Link]),
statistic =
all_continuous() ~ "Moy. : {mean} [min-max : {min} - {max}]"
)
Caractéristique N = 2 000
age Moy. : 48 [min-max : 18 - 97]
[Link] Moy. : 2,25 [min-max : 0,00 - 12,00]
Manquant 5
hdv2003 |>
tbl_summary(
include = c(age, [Link]),
statistic = list(
age ~ "Méd. : {median} [{p25} - {p75}]",
[Link] ~ "Moy. : {mean} ({sd})"
)
)
248
Table 18.5: statistiques personnalisées pour une variable conti-
nue (2)
Caractéristique N = 2 000
age Méd. : 48 [35 - 60]
[Link] Moy. : 2,25 (1,78)
Manquant 5
Caractéristique N = 2 000
[Link] MC : 8,20
Manquant 5
249
hdv2003 |>
tbl_summary(
include = occup,
statistic = all_categorical() ~ "{p} % ({n}/{N})"
)
Caractéristique N = 2 000
occup
Exerce une profession 52 % (1 049/2 000)
Chomeur 6,7 % (134/2 000)
Etudiant, eleve 4,7 % (94/2 000)
Retraite 20 % (392/2 000)
Retire des affaires 3,9 % (77/2 000)
Au foyer 8,6 % (171/2 000)
Autre inactif 4,2 % (83/2 000)
hdv2003 |>
tbl_summary(
include = occup,
sort = all_categorical() ~ "frequency"
)
250
Table 18.8: variable catégorielle triée par fréquence
Caractéristique N = 2 000
occup
Exerce une profession 1 049 (52%)
Retraite 392 (20%)
Au foyer 171 (8,6%)
Chomeur 134 (6,7%)
Etudiant, eleve 94 (4,7%)
Autre inactif 83 (4,2%)
Retire des affaires 77 (3,9%)
251
Table printed with `knitr::kable()`, not {gt}. Learn why at
[Link]
To suppress this message, include `message = FALSE` in code chunk header.
Caractéristique N = 2 000
age 48 (17)
[Link] 2,00 [1,00 - 3,00]
Manquant 5
occup
Exerce une profession 1 049 (52%)
Chomeur 134 (6,7%)
Etudiant, eleve 94 (4,7%)
Retraite 392 (20%)
Retire des affaires 77 (3,9%)
Au foyer 171 (8,6%)
Autre inactif 83 (4,2%)
tbl |>
add_stat_label()
Caractéristique N = 2 000
age, Moyenne (ET) 48 (17)
[Link], Médiane [EI] 2,00 [1,00 - 3,00]
Manquant 5
252
Caractéristique N = 2 000
occup, n (%)
Exerce une profession 1 049 (52%)
Chomeur 134 (6,7%)
Etudiant, eleve 94 (4,7%)
Retraite 392 (20%)
Retire des affaires 77 (3,9%)
Au foyer 171 (8,6%)
Autre inactif 83 (4,2%)
tbl |>
add_stat_label(location = "column")
253
du tableau de données trial est traitée comme variable conti-
nue, death comme dichotomique (seule la valeur 1 est affichée)
et grade comme variable catégorielle.
trial |>
tbl_summary(
include = c(grade, age, death)
)
Caractéristique N = 200
Grade
I 68 (34%)
II 68 (34%)
III 64 (32%)
Age 47 (38 – 57)
Manquant 11
Patient Died 112 (56%)
trial |>
tbl_summary(
include = c(grade, death),
type = list(
grade ~ "dichotomous",
death ~ "categorical"
),
value = grade ~ "III",
label = grade ~ "Grade III"
254
)
Caractéristique N = 200
Grade III 64 (32%)
Patient Died
0 88 (44%)
1 112 (56%)
Caractéristique N = 200
alea
1 50 (25%)
2 45 (23%)
3 42 (21%)
255
Caractéristique N = 200
4 63 (32%)
trial |>
tbl_summary(
include = alea,
type = alea ~ "continuous"
)
Caractéristique N = 200
alea 3 (2 – 4)
hdv2003 |>
tbl_summary(
include = c(age, [Link]),
type = age ~ "continuous2",
256
statistic =
all_continuous2() ~ c(
"{median} ({p25} - {p75})",
"{mean} ({sd})",
"{min} - {max}"
)
)
Caractéristique N = 2 000
age
Médiane (EI) 48 (35 - 60)
Moyenne (ET) 48 (17)
Étendue 18 - 97
[Link] 2,00 (1,00 – 3,00)
Manquant 5
hdv2003 |>
tbl_summary(
include = c(age, occup),
digits = list(
all_continuous() ~ 1,
257
all_categorical() ~ c(0, 1)
)
)
Caractéristique N = 2 000
age 48,0 (35,0 – 60,0)
occup
Exerce une profession 1 049 (52,5%)
Chomeur 134 (6,7%)
Etudiant, eleve 94 (4,7%)
Retraite 392 (19,6%)
Retire des affaires 77 (3,9%)
Au foyer 171 (8,6%)
Autre inactif 83 (4,2%)
258
hdv2003 |>
tbl_summary(
include = age,
digits =
all_continuous() ~ c(style_percent, style_sigfig, style_ratio)
)
Caractéristique N = 2 000
age 4 800 (35 – 60,0)
trial |>
tbl_summary(
include = marker,
statistic = ~ "{mean} pour 100",
digits = ~ function(x){style_percent(x, digits = 1)}
)
259
Table 18.19: passer une fonction personnalisée à digits (syntaxe
1)
Caractéristique N = 200
Marker Level (ng/mL) 91,6 pour 100
Manquant 10
trial |>
tbl_summary(
include = marker,
statistic = ~ "{mean} pour 100",
digits = ~ \(x){style_percent(x, digits = 1)}
)
Caractéristique N = 200
Marker Level (ng/mL) 91,6 pour 100
Manquant 10
trial |>
tbl_summary(
include = marker,
statistic = ~ "{mean} pour 100",
digits = ~ purrr::partial(style_percent, digits = 1)
260
)
Caractéristique N = 200
Marker Level (ng/mL) 91,6 pour 100
Manquant 10
trial |>
tbl_summary(
include = marker,
statistic = ~ "{mean}",
digits = ~ scales::label_number(
accuracy = .01,
suffix = " ng/mL",
[Link] = ","
)
)
261
[Link]
To suppress this message, include `message = FALSE` in code chunk header.
Caractéristique N = 200
Marker Level (ng/mL) 0,92 ng/mL
Manquant 10
hdv2003 |>
tbl_summary(
include = c(age, [Link]),
missing = "always",
missing_text = "Nbre observations manquantes"
)
Caractéristique N = 2 000
age 48 (35 – 60)
Nbre observations manquantes 0
[Link] 2,00 (1,00 – 3,00)
Nbre observations manquantes 5
262
Caractéristique N = 2 000
hdv2003 |>
dplyr::mutate(
[Link] = [Link] |>
forcats::fct_na_value_to_level("(non renseigné)")
) |>
tbl_summary(
include = c([Link], [Link])
)
Caractéristique N = 2 000
[Link]
Le plus important 29 (2,8%)
Aussi important que le reste 259 (25%)
Moins important que le reste 708 (68%)
Peu important 52 (5,0%)
Manquant 952
[Link]
Le plus important 29 (1,5%)
Aussi important que le reste 259 (13%)
Moins important que le reste 708 (35%)
Peu important 52 (2,6%)
(non renseigné) 952 (48%)
263
18.2.9 Ajouter les effectifs observés
hdv2003 |>
tbl_summary(
include = c([Link], [Link]),
missing = "no"
) |>
add_n()
Caractéristique N N = 2 000
[Link] 1 995 2,00 (1,00 – 3,00)
[Link] 1 048
Le plus important 29 (2,8%)
Aussi important que le reste 259 (25%)
Moins important que le reste 708 (68%)
Peu important 52 (5,0%)
264
• range() pour l’étendue
• median() pour la médiane
[1] NA
[1] 2.246566
[1] 1.775853
[1] 0
[1] 12
[1] 0 12
[1] 2
265
hdv2003$[Link] |> quantile([Link] = TRUE)
hdv2003$[Link] |>
quantile(
probs = c(.2, .4, .6, .8),
[Link] = TRUE
)
Les fonctions de base pour le calcul d’un tri à plat sont les
fonctions table() et xtabs(). Leur syntaxe est quelque peu
différente. On passe un vecteur entier à table() alors que la
syntaxe de xtabs() se rapproche de celle d’un modèle linéaire :
on décrit le tableau attendu à l’aide d’une formule et on indique
le tableau de données. Les deux fonctions renvoient le même
résultat.
266
[Link]
Le plus important Aussi important que le reste
29 259
Moins important que le reste Peu important
708 52
[Link](tbl)
[Link]
Le plus important Aussi important que le reste
0.02767176 0.24713740
Moins important que le reste Peu important
0.67557252 0.04961832
hdv2003$[Link] |>
questionr::freq(total = TRUE)
n % val%
Le plus important 29 1.5 2.8
Aussi important que le reste 259 13.0 24.7
Moins important que le reste 708 35.4 67.6
Peu important 52 2.6 5.0
NA 952 47.6 NA
Total 2000 100.0 100.0
267
18.4 Intervalles de confiance
Á Avertissement
hdv2003 |>
tbl_summary(
include = c(age, [Link], [Link]),
statistic = age ~ "{mean} ({sd})"
) |>
add_ci(
method = [Link] ~ "[Link]"
)
268
Table 18.26: ajouter les intervalles de confiance
hdv2003 |>
tbl_summary(
include = c(age, [Link]),
statistic = ~ "{mean}"
) |>
add_ci(
statistic = ~ "entre {[Link]} et {[Link]}",
[Link] = .9,
style_fun = ~ purrr::partial(style_number, digits = 1)
)
269
Caractéristique N = 2 000 90% CI
Manquant 5
data: hdv2003$age
t = 127.12, df = 1999, p-value < 2.2e-16
alternative hypothesis: true mean is not equal to 0
95 percent confidence interval:
47.41406 48.89994
sample estimates:
mean of x
48.157
List of 10
$ statistic : Named num 127
..- attr(*, "names")= chr "t"
$ parameter : Named num 1999
..- attr(*, "names")= chr "df"
$ [Link] : num 0
$ [Link] : num [1:2] 47.4 48.9
..- attr(*, "[Link]")= num 0.95
$ estimate : Named num 48.2
..- attr(*, "names")= chr "mean of x"
270
$ [Link] : Named num 0
..- attr(*, "names")= chr "mean"
$ stderr : num 0.379
$ alternative: chr "[Link]"
$ method : chr "One Sample t-test"
$ [Link] : chr "hdv2003$age"
- attr(*, "class")= chr "htest"
data: hdv2003$age
V = 2001000, p-value < 2.2e-16
alternative hypothesis: true location is not equal to 0
95 percent confidence interval:
47.00001 48.50007
sample estimates:
(pseudo)median
47.99996
hdv2003$age |>
[Link]([Link] = TRUE) |>
purrr::pluck("[Link]")
271
[1] 47.00001 48.50007
attr(,"[Link]")
[1] 0.95
272
Ď Astuce
273
18.5 webin-R
274
19 Statistique bivariée & Tests
de comparaison
library(gtsummary)
theme_gtsummary_language("fr", [Link] = ',')
trial |>
tbl_summary(
include = stage,
by = grade
)
275
Table printed with `knitr::kable()`, not {gt}. Learn why at
[Link]
To suppress this message, include `message = FALSE` in code chunk header.
library(gtsummary)
trial |>
tbl_summary(
include = c(stage, trt),
by = grade,
statistic = ~ "{p}% ({n}/{N})",
percent = "row"
) |>
add_overall(last = TRUE)
276
Table 19.2: un tableau croisé avec des pourcentages en ligne
ĺ Important
277
trial |>
tbl_cross(
row = stage,
col = grade,
percent = "row"
)
I II III Total
T Stage
T1 17 (32%) 23 (43%) 13 (25%) 53 (100%)
T2 18 (33%) 17 (31%) 19 (35%) 54 (100%)
T3 18 (42%) 11 (26%) 14 (33%) 43 (100%)
T4 15 (30%) 17 (34%) 18 (36%) 50 (100%)
Total 68 (34%) 68 (34%) 64 (32%) 200 (100%)
library(ggplot2)
ggplot(trial) +
aes(x = stage, fill = grade) +
geom_bar() +
labs(x = "T Stage", fill = "Grade", y = "Effectifs")
278
40
Grade
Effectifs
I
II
20 III
0
T1 T2 T3 T4
T Stage
library(ggplot2)
ggplot(trial) +
aes(x = stage, fill = grade) +
geom_bar(position = "dodge") +
labs(x = "T Stage", fill = "Grade", y = "Effectifs")
279
20
15 Grade
Effectifs
I
II
10
III
0
T1 T2 T3 T4
T Stage
library(ggplot2)
ggplot(trial) +
aes(x = stage, fill = grade) +
geom_bar(position = "fill") +
labs(x = "T Stage", fill = "Grade", y = "Proportion") +
scale_y_continuous(labels = scales::percent)
280
100%
75%
Grade
Proportion
I
50%
II
III
25%
0%
T1 T2 T3 T4
T Stage
281
ggplot(trial) +
aes(
x = stage, fill = grade,
label = after_stat(count)
) +
geom_bar() +
geom_text(
stat = "count",
position = position_stack(.5)
)
17 18
15
40
18 grade
count
I
17 17
23 II
20 11 III
19 18
13 14
0
T1 T2 T3 T4
stage
282
library(ggstats)
ggplot(trial) +
aes(
x = stage,
fill = grade,
by = stage,
label = scales::percent(after_stat(prop), accuracy = .1)
) +
geom_bar(position = "fill") +
geom_text(
stat = "prop",
position = position_fill(.5)
) +
scale_y_continuous(labels = scales::percent)
100%
grade
count
34.0% I
50% 31.5%
43.4% 25.6% II
III
25%
35.2% 32.6% 36.0%
24.5%
0%
T1 T2 T3 T4
stage
283
p <- ggplot(trial) +
aes(
x = stage,
y = after_stat(prop),
fill = grade,
by = grade,
label = scales::percent(after_stat(prop), accuracy = 1)
) +
geom_bar(
stat = "prop",
position = position_dodge(.9)
) +
geom_text(
aes(y = after_stat(prop) - 0.01),
stat = "prop",
position = position_dodge(.9),
vjust = "top"
) +
scale_y_continuous(labels = scales::percent)
p
34%
30%
30%
28%
26% 26%
25% 25% 25%
grade
20% 22% 22%
20% I
prop
II
16%
III
10%
0%
T1 T2 T3 T4
stage
284
p +
theme_light() +
xlab("") +
ylab("") +
labs(fill = "") +
ggtitle("Distribution selon le niveau, par grade") +
theme(
[Link] = element_blank(),
[Link] = element_blank(),
[Link].y = element_blank(),
[Link] = element_blank(),
[Link] = "top"
) +
scale_fill_brewer()
34%
30%
28%
26% 26%
25% 25% 25%
22% 22%
20%
16%
T1 T2 T3 T4
285
plus). Pour table(), on passera les deux vecteurs à croisés,
tandis que pour xtabs() on décrira le tableau attendu à l’aide
d’une formule.
table(trial$stage, trial$grade)
I II III
T1 17 23 13
T2 18 17 19
T3 18 11 14
T4 15 17 18
grade
stage I II III
T1 17 23 13
T2 18 17 19
T3 18 11 14
T4 15 17 18
grade
stage I II III Sum
T1 17 23 13 53
T2 18 17 19 54
T3 18 11 14 43
T4 15 17 18 50
Sum 68 68 64 200
286
Pour le calcul des pourcentages, le plus simple est d’avoir
recours au package {questionr} qui fournit les fonc-
tions questionr::cprop(), questionr::rprop() et
questionr::prop() qui permettent de calculer, respecti-
vement, les pourcentages en colonne, en ligne et totaux.
questionr::cprop(tab)
grade
stage I II III Ensemble
T1 25.0 33.8 20.3 26.5
T2 26.5 25.0 29.7 27.0
T3 26.5 16.2 21.9 21.5
T4 22.1 25.0 28.1 25.0
Total 100.0 100.0 100.0 100.0
questionr::rprop(tab)
grade
stage I II III Total
T1 32.1 43.4 24.5 100.0
T2 33.3 31.5 35.2 100.0
T3 41.9 25.6 32.6 100.0
T4 30.0 34.0 36.0 100.0
Ensemble 34.0 34.0 32.0 100.0
questionr::prop(tab)
grade
stage I II III Total
T1 8.5 11.5 6.5 26.5
T2 9.0 8.5 9.5 27.0
T3 9.0 5.5 7.0 21.5
T4 7.5 8.5 9.0 25.0
Total 34.0 34.0 32.0 100.0
287
19.1.4 Test du Chi² et dérivés
grade
stage I II III
T1 17 23 13
T2 18 17 19
T3 18 11 14
T4 15 17 18
[Link](tab)
data: tab
X-squared = 4.8049, df = 6, p-value = 0.5691
trial |>
tbl_summary(
include = stage,
by = grade
) |>
add_p()
288
Table printed with `knitr::kable()`, not {gt}. Learn why at
[Link]
To suppress this message, include `message = FALSE` in code chunk header.
II, N = III, N = p-
Caractéristique
I, N = 68 68 64 valeur
T Stage 0,6
T1 17 (25%) 23 (34%) 13 (20%)
T2 18 (26%) 17 (25%) 19 (30%)
T3 18 (26%) 11 (16%) 14 (22%)
T4 15 (22%) 17 (25%) 18 (28%)
data: tab
p-value = 0.5801
alternative hypothesis: [Link]
trial |>
tbl_summary(
include = stage,
by = grade
) |>
add_p(test = all_categorical() ~ "[Link]")
289
Table printed with `knitr::kable()`, not {gt}. Learn why at
[Link]
To suppress this message, include `message = FALSE` in code chunk header.
II, N = III, N = p-
Caractéristique
I, N = 68 68 64 valeur
T Stage 0,6
T1 17 (25%) 23 (34%) 13 (20%)
T2 18 (26%) 17 (25%) 19 (30%)
T3 18 (26%) 11 (16%) 14 (22%)
T4 15 (22%) 17 (25%) 18 (28%)
Ĺ Note
290
trt
I(stage == "T1") Drug A Drug B Ensemble
FALSE 71.4 75.5 73.5
TRUE 28.6 24.5 26.5
Total 100.0 100.0 100.0
data: tab
X-squared = 0.24047, df = 1, p-value = 0.6239
alternative hypothesis: [Link]
95 percent confidence interval:
-0.2217278 0.1175050
sample estimates:
prop 1 prop 2
0.4761905 0.5283019
[Link](tab)
data: tab
p-value = 0.5263
alternative hypothesis: true odds ratio is not equal to 1
95 percent confidence interval:
0.4115109 1.5973635
sample estimates:
odds ratio
0.8125409
291
Mais le plus simple reste encore d’avoir recours à {gtsummary}
et à sa fonction gtsummary::add_difference() que l’on peut
appliquer à un tableau où le paramètre by n’a que deux moda-
lités. Pour la différence de proportions, il faut que les variables
transmises à include soit dichotomiques.
trial |>
tbl_summary(
by = trt,
include = response
) |>
add_difference()
trial |>
tbl_summary(
by = trt,
include = grade
) |>
add_difference()
292
[Link]
To suppress this message, include `message = FALSE` in code chunk header.
trial |>
fastDummies::dummy_cols("grade") |>
tbl_summary(
by = trt,
include = starts_with("grade_"),
digits = ~ c(0, 1)
) |>
add_difference()
293
Table 19.8: différence entre proportions avec création de va-
riables dichotomiques
trial |>
tbl_summary(
include = age,
by = grade
)
294
Table 19.9: âge médian et intervalle interquartile selon le grade
trial |>
tbl_summary(
include = age,
by = grade
) |>
add_overall(last = TRUE) |>
modify_spanning_header(
all_stat_cols(stat_0 = FALSE) ~ "**Grade**"
)
295
trial |>
tbl_summary(
include = age,
by = grade,
statistic = all_continuous() ~ "{mean} ({sd})",
digits = all_continuous() ~ c(1, 1)
) |>
add_overall(last = TRUE)
ggplot(trial) +
aes(x = grade, y = age) +
geom_boxplot(fill = "lightblue") +
theme_light()
296
80
60
age
40
20
I II III
grade
Ď Astuce
ggplot(trial) +
aes(x = grade, y = age) +
geom_violin(fill = "lightblue") +
theme_light()
297
80
60
age
40
20
I II III
grade
ggplot(trial) +
aes(x = grade, y = age) +
geom_point(alpha = .25, colour = "blue") +
theme_light()
298
80
60
age
40
20
I II III
grade
ggplot(trial) +
aes(x = grade, y = age) +
geom_point(
alpha = .25,
colour = "blue",
position = position_jitter(height = 0, width = .2)
) +
theme_light()
299
80
60
age
40
20
I II III
grade
La statistique ggstats::stat_weighted_mean() de
{ggstats} permets de calculer à la volée la moyenne du
nuage de points.
ggplot(trial) +
aes(x = grade, y = age) +
geom_point(stat = "weighted_mean", colour = "blue") +
theme_light()
300
48.0
47.5
age
47.0
46.5
I II III
grade
ggplot(trial) +
aes(x = grade, y = age, colour = stage, group = stage) +
geom_line(stat = "weighted_mean") +
geom_point(stat = "weighted_mean") +
facet_grid(cols = vars(trt)) +
theme_light()
301
Drug A Drug B
55
stage
T1
50
age
T2
T3
T4
45
I II III I II III
grade
library(dplyr)
trial |>
group_by(grade) |>
summarise(
age_moy = mean(age, [Link] = TRUE),
age_med = median(age, [Link] = TRUE)
)
# A tibble: 3 x 3
grade age_moy age_med
<fct> <dbl> <dbl>
1 I 46.2 47
2 II 47.5 48.5
3 III 48.1 47
302
En base R, on peut avoir recours à tapply(). On lui indique
d’abord le vecteur sur lequel on souhaite réaliser le calcul, puis
un facteur qui indiquera les sous-groupes, puis une fonction
qui sera appliquée à chaque sous-groupe et enfin, optionnelle-
ment, des arguments additionnels qui seront transmis à cette
fonction.
I II III
46.15152 47.53226 48.11475
trial |>
tbl_summary(
include = age,
by = grade
) |>
add_p()
II, N = III, N = p-
Caractéristique
I, N = 68 68 64 valeur
Age 47 (37 – 49 (37 – 47 (38 – 0,8
56) 57) 58)
Manquant 2 6 3
303
Par défaut, pour les variables continues, un test de Kruskal-
Wallis calculé avec la fonction stats::[Link]() est uti-
lisé lorsqu’il y a trois groupes ou plus, et un test de Wilcoxon-
Mann-Whitney calculé avec stats::[Link]() (test de
comparaison des rangs) lorsqu’il n’y a que deux groupes. Au
sens strict, il ne s’agit pas de tests de comparaison des mé-
dianes mais de tests sur la somme des rangs26 . En pratique, ces 26
Si l’on a besoin spécifique-
tests sont appropriés lorsque l’on présente les médianes et les ment d’un test de comparaison
des médianes, il existe le test
intervalles inter-quartiles.
de Brown-Mood disponible dans
Si l’on affiche des moyennes, il serait plus juste d’utiliser un le package {coin} avec la fonc-
tion coin::median_test(). Atten-
test t de Student (test de comparaison des moyennes) calculé tion, il ne faut pas confondre ce
avec stats::[Link](), valable seulement si l’on compare deux test avec le test de dispersion de
moyennes. Pour tester si trois moyennes ou plus sont égales, on Mood implémenté dans la fonction
aura plutôt recours à stats::[Link](). stats::[Link]().
trial |>
tbl_summary(
include = age,
by = grade,
statistic = all_continuous() ~ "{mean} ({sd})"
) |>
add_p(
test = all_continuous() ~ "[Link]"
)
304
Table 19.13: test de comparaison des moyennes
II, N = III, N = p-
Caractéristique
I, N = 68 68 64 valeur
Age 46 (15) 48 (14) 48 (14) 0,7
Manquant 2 6 3
ĺ Précision statistique
305
trial |>
tbl_summary(
include = age,
by = trt,
statistic = all_continuous() ~ "{mean} ({sd})"
) |>
add_p(
test = all_continuous() ~ "[Link]",
[Link] = all_continuous() ~ list([Link] = TRUE)
)
Drug A, N Drug B, N p-
Caractéristique = 98 = 102 valeur
Age 47 (15) 47 (14) 0,8
Manquant 7 4
trial |>
tbl_summary(
include = age,
by = trt,
statistic = all_continuous() ~ "{mean} ({sd})"
) |>
add_difference()
306
Table printed with `knitr::kable()`, not {gt}. Learn why at
[Link]
To suppress this message, include `message = FALSE` in code chunk header.
ggplot(iris) +
aes(x = [Link], y = [Link]) +
geom_point(colour = "blue", alpha = .25) +
theme_light()
307
2.5
2.0
[Link]
1.5
1.0
0.5
0.0
2 4 6
[Link]
ggplot(iris) +
aes(x = [Link], y = [Link]) +
geom_smooth() +
geom_point(colour = "blue", alpha = .25) +
theme_light()
308
2.5
2.0
[Link]
1.5
1.0
0.5
0.0
2 4 6
[Link]
ggplot(iris) +
aes(x = [Link], y = [Link]) +
geom_smooth(method = "lm") +
geom_point(colour = "blue", alpha = .25) +
theme_light()
309
2
[Link]
2 4 6
[Link]
ggplot(iris) +
aes(x = [Link], y = [Link]) +
geom_smooth(method = "lm") +
geom_point(colour = "blue", alpha = .25) +
theme_light() +
expand_limits(x = 0, y = -0.5)
310
2
[Link]
0 2 4 6
[Link]
ggplot(iris) +
aes(x = [Link], y = [Link]) +
geom_smooth(method = "lm", fullrange = TRUE) +
geom_point(colour = "blue", alpha = .25) +
theme_light() +
expand_limits(x = 0, y = -0.5)
311
2
[Link]
0 2 4 6
[Link]
ggplot(iris) +
aes(x = [Link], y = [Link]) +
geom_smooth(
method = "lm",
xseq = seq(0, 1, by = .1),
linetype = "dotted",
se = FALSE
) +
geom_smooth(method = "lm") +
geom_point(colour = "blue", alpha = .25) +
theme_light() +
expand_limits(x = 0, y = -0.5)
312
2
[Link]
0 2 4 6
[Link]
ggplot(iris) +
aes(x = [Link], y = [Link]) +
geom_smooth(method = "lm") +
geom_point(colour = "blue", alpha = .25) +
geom_rug() +
theme_light()
313
2
[Link]
2 4 6
[Link]
cor(iris$[Link], iris$[Link])
[1] 0.9628654
Call:
lm(formula = [Link] ~ [Link], data = iris)
Residuals:
314
Min 1Q Median 3Q Max
-1.33542 -0.30347 -0.02955 0.25776 1.39453
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 1.08356 0.07297 14.85 <2e-16 ***
[Link] 2.22994 0.05140 43.39 <2e-16 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
m |>
tbl_regression() |>
add_glance_source_note()
315
entre plusieurs variables, tant quantitatives que qualitatives.
library(GGally)
ggpairs(iris)
[Link]
0.4
0.3 Corr: Corr: Corr:
0.2
0.1 −0.118 0.872*** 0.818***
0.0
[Link]
4.5
4.0 Corr: Corr:
3.5
3.0
2.5 −0.428*** −0.366***
2.0
[Link]
6
Corr:
4
2 0.963***
[Link] Species
2.5
2.0
1.5
1.0
0.5
0.0
7.5
5.0
2.5
0.0
7.5
5.0
2.5
0.0
7.5
5.0
2.5
0.0
5 6 7 8 [Link].54.04.5 2 4 6 [Link].52.02.5 setosa
versicolor
virginica
316
trt age marker stage grade response death ttdeath
100
75
trt
50
25
80
Corr: −0.003 Corr: 0.124. Corr: 0.076 Corr: −0.051
60
age
40
4
Corr: 0.123. Corr: −0.048 Corr: 0.083
3
marker
2 Drug A: 0.106 Drug A: 0.146 Drug A: −0.061
1
Drug B: 0.155 Drug B: −0.230* Drug B: 0.191.
0
30
20
10
0
30
20
10
stage
0
30
20
10
0
30
20
10
0
30
20
10
0
30
grade
20
10
0
30
20
10
0
1.00
Corr: −0.220** Corr: 0.204**
0.75
response
0.50
Drug A: −0.113 Drug A: 0.086
0.25
Drug B: −0.331*** Drug B: 0.317**
0.00
1.00
Corr: −0.737***
0.75
death
0.50
Drug A: −0.714***
0.25
Drug B: −0.759***
0.00
25
20
ttdeath
15
10
0 10 20 30 40 500 10 20 30 40 50 20 40 60 80 0 1 2 3 4 0 1020300 1020300 1020300 102030 0 102030 0 102030 0 102030 0.00 0.25 0.50 0.75 1.000.00 0.25 0.50 0.75 1.00 5 10 15 20 25
19.5 webin-R
317
20 Échelles de Likert
library(tidyverse)
318
library(labelled)
niveaux <- c(
"Pas du tout d'accord",
"Plutôt pas d'accord",
"Ni d'accord, ni pas d'accord",
"Plutôt d'accord",
"Tout à fait d'accord"
)
[Link](42)
df <-
tibble(
groupe = sample(c("A", "B"), 150, replace = TRUE),
q1 = sample(niveaux, 150, replace = TRUE),
q2 = sample(niveaux, 150, replace = TRUE, prob = 5:1),
q3 = sample(niveaux, 150, replace = TRUE, prob = 1:5),
q4 = sample(niveaux, 150, replace = TRUE, prob = 1:5),
q5 = sample(c(niveaux, NA), 150, replace = TRUE),
q6 = sample(niveaux, 150, replace = TRUE, prob = c(1, 0, 1, 1, 0))
) |>
mutate(across(q1:q6, ~ factor(.x, levels = niveaux))) |>
set_variable_labels(
q1 = "Première question",
q2 = "Seconde question",
q3 = "Troisième question",
q4 = "Quatrième question",
q5 = "Cinquième question",
q6 = "Sixième question"
)
library(gtsummary)
df |>
tbl_summary(include = q1:q6)
319
Table printed with `knitr::kable()`, not {gt}. Learn why at
[Link]
To suppress this message, include `message = FALSE` in code chunk header.
Characteristic N = 150
Première question
Pas du tout d’accord 39 (26%)
Plutôt pas d’accord 32 (21%)
Ni d’accord, ni pas d’accord 25 (17%)
Plutôt d’accord 30 (20%)
Tout à fait d’accord 24 (16%)
Seconde question
Pas du tout d’accord 56 (37%)
Plutôt pas d’accord 44 (29%)
Ni d’accord, ni pas d’accord 19 (13%)
Plutôt d’accord 26 (17%)
Tout à fait d’accord 5 (3.3%)
Troisième question
Pas du tout d’accord 8 (5.3%)
Plutôt pas d’accord 17 (11%)
Ni d’accord, ni pas d’accord 29 (19%)
Plutôt d’accord 43 (29%)
Tout à fait d’accord 53 (35%)
Quatrième question
Pas du tout d’accord 11 (7.3%)
Plutôt pas d’accord 19 (13%)
Ni d’accord, ni pas d’accord 31 (21%)
Plutôt d’accord 40 (27%)
Tout à fait d’accord 49 (33%)
Cinquième question
Pas du tout d’accord 33 (26%)
Plutôt pas d’accord 25 (20%)
Ni d’accord, ni pas d’accord 28 (22%)
Plutôt d’accord 25 (20%)
Tout à fait d’accord 16 (13%)
Unknown 23
Sixième question
Pas du tout d’accord 50 (33%)
Plutôt pas d’accord 0 (0%)
320
Characteristic N = 150
Ni d’accord, ni pas d’accord 50 (33%)
Plutôt d’accord 50 (33%)
Tout à fait d’accord 0 (0%)
ĺ Important
library(bstfun)
trial
df |>
tbl_likert(
include = q1:q6
)
321
Table printed with `knitr::kable()`, not {gt}. Learn why at
[Link]
To suppress this message, include `message = FALSE` in code chunk header.
Ni
Pas du Plutôt d’accord, Tout à
tout pas ni pas Plutôt fait
Characteristic
d’accord d’accord d’accord d’accordd’accord
Première 39 32 25 (17%) 30 24
ques- (26%) (21%) (20%) (16%)
tion
Seconde 56 44 19 (13%) 26 5 (3.3%)
ques- (37%) (29%) (17%)
tion
Troisième8 (5.3%) 17 29 (19%) 43 53
ques- (11%) (29%) (35%)
tion
Quatrième 11 19 31 (21%) 40 49
ques- (7.3%) (13%) (27%) (33%)
tion
Cinquième 33 25 28 (22%) 25 16
ques- (26%) (20%) (20%) (13%)
tion
Sixième 50 0 (0%) 50 (33%) 50 0 (0%)
ques- (33%) (33%)
tion
df |>
tbl_likert(
include = q1:q6,
statistic = ~ "{p}%"
) |>
add_n() |>
add_continuous_stat(score_values = -2:2)
322
Table printed with `knitr::kable()`, not {gt}. Learn why at
[Link]
To suppress this message, include `message = FALSE` in code chunk header.
Pas Ni
du Plutôt d’accord, Tout
tout pas ni pas Plutôt à fait
Characteristic
N d’accordd’accordd’accord d’accordd’accordMean
Première
150 26% 21% 17% 20% 16% -
ques- 0.21
tion
Seconde150 37% 29% 13% 17% 3.3% -
ques- 0.80
tion
Troisième
150 5.3% 11% 19% 29% 35% 0.77
ques-
tion
Quatrième
150 7.3% 13% 21% 27% 33% 0.65
ques-
tion
127 26%
Cinquième 20% 22% 20% 13% -
ques- 0.27
tion
Sixième150 33% 0% 33% 33% 0% -
ques- 0.33
tion
library(ggstats)
gglikert(df, include = q1:q6)
323
Première question 47% 26% 21% 17% 20% 16% 36%
50% 0% 50%
Pas du tout d'accord Plutôt pas d'accord Ni d'accord, ni pas d'accord Plutôt d'accord Tout à fait d'accord
df |>
gglikert(
include = q1:q6,
totals_include_center = TRUE,
sort = "ascending"
) +
guides(
fill = guide_legend(nrow = 2)
)
324
Seconde question 73% 37% 29% 13% 17% 27%
50% 0% 50%
df |>
gglikert(
include = q1:q6,
facet_cols = vars(groupe)
)
A B
Sixième question 28% 28% 29% 43% 43%38% 38% 37% 25% 25%
Pas du tout d'accord Plutôt pas d'accord Ni d'accord, ni pas d'accord Plutôt d'accord Tout à fait d'accord
325
df |>
gglikert(
include = q1:q6,
y = "groupe",
facet_rows = vars(.question),
facet_label_wrap = 15
)
PremièreSeconde
questionquestionquestionquestionquestionquestion
A 51% 30% 20% 20% 16% 13% 29%
B 44% 22% 22% 14% 23% 19% 42%
A 65% 29% 36% 14% 19% 20%
B 68% 44% 23% 11% 16% 21%
Troisième
A 10% 6% 17% 28% 45% 72%
B 22% 6% 16% 21% 30% 27% 57%
Quatrième
A 22% 7% 14% 22% 33% 23% 57%
B 19% 7%11% 20% 21% 41% 62%
Cinquième
A 41% 21% 21% 25% 19% 14% 33%
B 50% 31% 19% 19% 20% 11% 31%
Sixième
A 28% 28% 29% 43% 43%
B 38% 38% 37% 25% 25%
50% 0% 50%
Pas du tout d'accord Plutôt pas d'accord Ni d'accord, ni pas d'accord Plutôt d'accord Tout à fait d'accord
df |>
gglikert_stacked(
include = q1:q6,
sort = "ascending",
add_median_line = TRUE
)
326
Seconde question 37% 29% 13% 17%
Pas du tout d'accord Plutôt pas d'accord Ni d'accord, ni pas d'accord Plutôt d'accord Tout à fait d'accord
327
21 Régression linéaire
library(tidyverse)
ggplot(iris) +
aes(x = [Link], y = [Link]) +
geom_point(colour = "blue", alpha = .25) +
labs(x = "Longueur", y = "Largeur") +
theme_light()
328
2.5
2.0
1.5
Largeur
1.0
0.5
0.0
2 4 6
Longueur
ggplot(iris) +
aes(x = [Link], y = [Link]) +
geom_point(colour = "blue", alpha = .25) +
geom_smooth(method = "lm") +
labs(x = "Longueur", y = "Largeur") +
theme_light()
329
2
Largeur
2 4 6
Longueur
Call:
lm(formula = [Link] ~ [Link], data = iris)
Coefficients:
(Intercept) [Link]
-0.3631 0.4158
330
Le résultat comporte deux coefficients. Le premier, d’une valeur
de 0, 4158, est associé à la variable [Link] et indique la
pente de la courbe (on parle de slope en anglais). Le second,
d’une valeur de −0, 3631, représente l’ordonnée à l’origine (in-
tercept en anglais), c’est-à-dire la valeur estimée de [Link]
lorsque [Link] vaut 0. Nous pouvons rendre cela plus vi-
sible en élargissant notre graphique.
ggplot(iris) +
aes(x = [Link], y = [Link]) +
geom_point(colour = "blue", alpha = .25) +
geom_abline(
intercept = mod$coefficients[1],
slope = mod$coefficients[2],
linewidth = 1,
colour = "red"
) +
geom_vline(xintercept = 0, linewidth = 1, linetype = "dotted") +
labs(x = "Longueur", y = "Largeur") +
expand_limits(x = 0, y = -1) +
theme_light()
2
Largeur
−1
0 2 4 6
Longueur
331
Le modèle linéaire calculé estime donc que le relation entre nos
deux variables peut s’écrire sous la forme suivante :
Ď Astuce
332
modèle.
Call:
lm(formula = [Link] ~ [Link] - 1, data = iris)
Coefficients:
[Link]
0.3365
library(labelled)
iris %>% look_for("Species")
Call:
333
lm(formula = [Link] ~ Species, data = iris)
Coefficients:
(Intercept) Speciesversicolor Speciesvirginica
0.246 1.080 1.780
mod %>%
tbl_regression(intercept = TRUE)
iris %>%
group_by(Species) %>%
summarise(mean([Link]))
# A tibble: 3 x 2
Species `mean([Link])`
<fct> <dbl>
1 setosa 0.246
2 versicolor 1.33
3 virginica 2.03
334
Comme on le voit, l’intercept nous indique donc la moyenne
observée pour l’espèce de référence (0, 246).
Le coefficient associé à versicolor correspond à la différence
par rapport à la référence (ici +1, 080). Comme vous pouvez le
constater, il s’agit de la différence entre la moyenne observée
pour versicolor (1, 326) et celle de la référence setosa (0, 246) :
1, 326 − 0, 246 = 1, 080.
Ce coefficient est significativement différent de 0 (p<0,001), in-
diquant que la largeur des pétales diffère significativement entre
les deux espèces.
Ď Astuce
Call:
lm(formula = [Link] ~ Species - 1, data = iris)
Coefficients:
Speciessetosa Speciesversicolor Speciesvirginica
0.246 1.326 2.026
335
21.3 Modèle à plusieurs variables explicatives
Call:
lm(formula = [Link] ~ [Link] + [Link] + [Link] +
Species, data = iris)
Coefficients:
(Intercept) [Link] [Link] [Link]
-0.47314 0.24220 0.24220 -0.09293
Speciesversicolor Speciesvirginica
0.64811 1.04637
mod %>%
tbl_regression(intercept = TRUE)
336
Characteristic Beta 95% CI p-value
[Link] 0.24 0.15, 0.34 <0.001
[Link] -0.09 -0.18, 0.00 0.039
Species
setosa — —
versicolor 0.65 0.40, 0.89 <0.001
virginica 1.0 0.72, 1.4 <0.001
library(ggstats)
ggcoef_model(mod)
[Link]
(p<0.001***)
[Link]
(p<0.001***)
[Link]
(p=0.039*)
Species
setosa
versicolor (p<0.001***)
virginica (p<0.001***)
337
22 Régression logistique
binaire
338
d’heures passées à regarder la télévision par jour sur la proba-
bilité de pratiquer un sport.
En premier lieu, il importe de vérifier, par exemple avec
labelled::look_for(), que notre variable d’intérêt (ici
sport) est correctement codée, c’est-à-dire que la première
modalité correspondent à la référence (soit ne pas avoir vécu
l’évènement d’intérêt) et que la seconde modalité corresponde
au fait d’avoir vécu l’évènement.
library(labelled)
d |> look_for("sport")
339
tous les coefficients sont calculés par rapport à la modalité de
référence (cf. Section 21.2). Il importe donc de choisir une mo-
dalité de référence qui fasse sens afin de faciliter l’interprétation.
Par ailleurs, ce choix doit dépendre de la manière dont on sou-
haite présenter les résultats (le data storytelling est essentiel).
De manière générale on évitera de choisir comme référence une
modalité peu représentée dans l’échantillon ou bien une moda-
lité correspondant à une situation atypique.
Prenons l’exemple de la variable sexe. Souhaite-t-on connaitre
l’effet d’être une femme par rapport au fait d’être un homme
ou bien l’effet d’être un homme par rapport au fait d’être une
femme ? Si l’on opte pour le second, alors notre modalité de ré-
férence sera le sexe féminin. Comme est codée cette variable ?
d |> look_for("sexe")
library(tidyverse)
d <- d |>
mutate(sexe = sexe |> fct_relevel("Femme"))
n % val%
Femme 1101 55 55
Homme 899 45 45
Données labellisées
Si l’on utilise des données labellisées (voir Chapitre 12), nos
variables catégorielles seront stockées sous la forme d’un
340
vecteur numérique avec des étiquettes. Il sera donc nécessaire
de convertir ces variables en facteurs, tout simplement avec
labelled::to_factor() ou labelled::unlabelled().
Les variables age et [Link] sont des variables quantitatives.
Il importe de vérifier qu’elles sont bien enregistrées en tant que
variables numériques. En effet, il arrive parfois que dans le fi-
chier source les variables quantitatives soient renseignées sous
forme de valeur textuelle et non sous forme numérique.
d <- d |>
mutate(
groupe_ages = age |>
cut(
c(18, 25, 45, 65, 99),
right = FALSE,
[Link] = TRUE,
labels = c("18-24 ans", "25-44 ans",
"45-64 ans", "65 ans et plus")
)
)
d$groupe_ages |> questionr::freq()
n % val%
18-24 ans 169 8.5 8.5
341
25-44 ans 706 35.3 35.3
45-64 ans 745 37.2 37.2
65 ans et plus 380 19.0 19.0
n % val%
N'a jamais fait d'etudes 39 2.0 2.1
A arrete ses etudes, avant la derniere annee d'etudes primaires 86 4.3 4.6
Derniere annee d'etudes primaires 341 17.0 18.1
1er cycle 204 10.2 10.8
2eme cycle 183 9.2 9.7
Enseignement technique ou professionnel court 463 23.2 24.5
Enseignement technique ou professionnel long 131 6.6 6.9
Enseignement superieur y compris technique superieur 441 22.0 23.4
NA 112 5.6 NA
d <- d |>
mutate(
etudes = nivetud |>
fct_recode(
"Primaire" = "N'a jamais fait d'etudes",
"Primaire" = "A arrete ses etudes, avant la derniere annee d'etudes primaires",
"Primaire" = "Derniere annee d'etudes primaires",
"Secondaire" = "1er cycle",
"Secondaire" = "2eme cycle",
"Technique / Professionnel" = "Enseignement technique ou professionnel court",
"Technique / Professionnel" = "Enseignement technique ou professionnel long",
"Supérieur" = "Enseignement superieur y compris technique superieur"
)
)
342
d$etudes |> questionr::freq()
n % val%
Primaire 466 23.3 24.7
Secondaire 387 19.4 20.5
Technique / Professionnel 594 29.7 31.5
Supérieur 441 22.0 23.4
NA 112 5.6 NA
d <- d |>
set_variable_labels(
sport = "Pratique un sport ?",
sexe = "Sexe",
groupe_ages = "Groupe d'âges",
etudes = "Niveau d'études",
relig = "Rapport à la religion",
[Link] = "Heures de télévision / jour"
)
343
Ĺ Code récapitulatif (préparation des données)
344
22.2 Statistiques descriptives
library(gtsummary)
theme_gtsummary_language("fr", [Link] = ",", [Link] = " ")
d |>
tbl_summary(
by = sport,
include = c(sexe, groupe_ages, etudes, relig, [Link])
) |>
add_overall(last = TRUE) |>
add_p() |>
bold_labels() |>
modify_spanning_header(
update = all_stat_cols() ~ "**Pratique un sport ?**"
)
345
Non, N Oui, N Total, N p-
Caractéristique = 1 277 = 723 = 2 000 valeur
Groupe <0,001
d’âges
18-24 ans 58 (4,5%) 111 169
(15%) (8,5%)
25-44 ans 359 347 706 (35%)
(28%) (48%)
45-64 ans 541 204 745 (37%)
(42%) (28%)
65 ans et plus 319 61 (8,4%) 380 (19%)
(25%)
Niveau <0,001
d’études
Primaire 416 50 (6,9%) 466 (23%)
(33%)
Secondaire 270 117 387 (19%)
(21%) (16%)
Technique / 378 216 594 (30%)
Professionnel (30%) (30%)
Supérieur 186 255 441 (22%)
(15%) (35%)
Non 27 (2,1%) 85 (12%) 112
documenté (5,6%)
Rapport à la 0,14
religion
Pratiquant 182 84 (12%) 266 (13%)
regulier (14%)
Pratiquant 295 147 442 (22%)
occasionnel (23%) (20%)
Appartenance 473 287 760 (38%)
sans pratique (37%) (40%)
Ni croyance ni 239 160 399 (20%)
appartenance (19%) (22%)
Rejet 60 (4,7%) 33 (4,6%) 93 (4,7%)
NSP ou NVPR 28 (2,2%) 12 (1,7%) 40 (2,0%)
Heures de 2,00 (1,00 2,00 (1,00 2,00 (1,00 <0,001
télévision / – 3,00) – 3,00) – 3,00)
jour
Manquant 2 3 5
346
22.3 Calcul de la régression logistique binaire
mod |>
tbl_regression(intercept = TRUE) |>
bold_labels()
347
Caractéristique log(OR) 95% IC p-valeur
45-64 ans -1,1 -1,6 – -0,62 <0,001
65 ans et plus -1,4 -1,9 – -0,85 <0,001
Niveau d’études
Primaire — —
Secondaire 0,95 0,57 – 1,3 <0,001
Technique / 1,0 0,68 – 1,4 <0,001
Professionnel
Supérieur 1,9 1,5 – 2,3 <0,001
Non documenté 2,2 1,5 – 2,8 <0,001
Rapport à la
religion
Pratiquant regulier — —
Pratiquant occasionnel -0,02 -0,39 – >0,9
0,35
Appartenance sans -0,01 -0,35 – >0,9
pratique 0,34
Ni croyance ni -0,22 -0,59 – 0,3
appartenance 0,16
Rejet -0,38 -0,95 – 0,2
0,17
NSP ou NVPR -0,08 -0,92 – 0,8
0,70
Heures de télévision -0,12 -0,19 – <0,001
/ jour -0,06
348
selon l’échelle logit. Retraduisons cela en probabilité classique
avec la fonction logit inverse.
[1] 0.3100255
logit_inverse(-0.80 + 0.44)
[1] 0.4109596
[1] 0.3543437
349
individu3 <- d[1, ]
individu3$sexe[1] <- "Homme"
individu3$groupe_ages[1] <- "18-24 ans"
individu3$etudes[1] <- "Primaire"
individu3$relig[1] <- "Pratiquant regulier"
individu3$[Link][1] <- 2
library(breakDown)
logit <- function(x) exp(x) / (1 + exp(x))
plot(
broken(mod, individu3, [Link] = betas),
trans = logit
) +
scale_y_continuous(
labels = scales::label_percent(),
breaks = 0:5/5,
limits = c(0, 1)
)
final_prognosis −0.146
etudes = Primaire 0
[Link] = 2 −0.057
(Intercept) −0.19
350
22.5 La notion d’odds ratio
Ď Astuce
questionr::[Link](.75, 1/3)
[1] 6
L’odds ratio est donc égal à 1 si les deux côtes sont iden-
tiques, est supérieur à 1 si le cheval A une probabilité
supérieure à celle du cheval B, et inférieur à 1 si c’est
probabilité est inférieure.
351
On le voit, par construction, l’odds ratio de B par rapport
à A est l’inverse de celui de A par rapport à B : 𝑂𝑅𝐵/𝐴 =
1/𝑂𝑅𝐴/𝐵 .
mod |>
tbl_regression(exponentiate = TRUE) |>
bold_labels()
352
Caractéristique OR 95% IC p-valeur
Rejet 0,68 0,39 – 1,19 0,2
NSP ou NVPR 0,92 0,40 – 2,02 0,8
Heures de télévision / jour 0,89 0,83 – 0,95 <0,001
mod |>
ggstats::ggcoef_model(exponentiate = TRUE)
Sexe Femme
Homme (p<0.001***)
Groupe d'âges 18−24 ans
25−44 ans (p=0.065)
45−64 ans (p<0.001***)
65 ans et plus (p<0.001***)
Niveau d'études Primaire
Secondaire (p<0.001***)
Technique / Professionnel (p<0.001***)
Supérieur (p<0.001***)
Non documenté (p<0.001***)
Rapport à la religion Pratiquant regulier
Pratiquant occasionnel (p=0.908)
Appartenance sans pratique (p=0.969)
Ni croyance ni appartenance (p=0.265)
Rejet (p=0.180)
NSP ou NVPR (p=0.838)
Heures de télévision / jour (p<0.001***)
0.3 1.0 3.0 10.0
OR
mod |>
ggstats::ggcoef_table(exponentiate = TRUE)
353
OR
95% CIp
Sexe Femme 1.0
Homme 1.6
1.3,<0.001
1.9
Groupe d'âges 18−24 ans 1.0
25−44 ans 0.7
0.4, 0.065
1.0
45−64 ans 0.3
0.2,<0.001
0.5
65 ans et plus 0.3
0.1,<0.001
0.4
Niveau d'études Primaire 1.0
Secondaire 2.6
1.8,<0.001
3.8
Technique / Professionnel 2.9
2.0,<0.001
4.2
Supérieur 6.6
4.6,<0.001
9.8
Non documenté 8.6
4.5, <0.001
16.6
Rapport à la religion Pratiquant regulier 1.0
Pratiquant occasionnel 1.0
0.7, 0.908
1.4
Appartenance sans pratique 1.0
0.7, 0.969
1.4
Ni croyance ni appartenance 0.8
0.6, 0.265
1.2
Rejet 0.7
0.4, 0.180
1.2
NSP ou NVPR 0.9
0.4, 0.838
2.0
Heures de télévision / jour 0.9
0.8,<0.001
0.9
0.3 [Link]
OR
Ĺ Note
¾ Mise en garde
354
choses égales par ailleurs). Une telle formulation corres-
pond à un prevalence ratio (rapport des prévalences en
français) ou risk ratio (rapport des risques), à savoir divi-
ser la probabilité de faire du sport des hommes par celle
des femmes, 𝑝ℎ𝑜𝑚𝑚𝑒𝑠 /𝑝𝑓𝑒𝑚𝑚𝑒𝑠 . Or, cela ne correspond
pas à la formule de l’odds ratio, à savoir (𝑝ℎ𝑜𝑚𝑚𝑒𝑠 /(1 −
𝑝ℎ𝑜𝑚𝑚𝑒𝑠 ))/(𝑝𝑓𝑒𝑚𝑚𝑒𝑠 /(1 − 𝑝𝑓𝑒𝑚𝑚𝑒𝑠 )).
Lorsque le phénomène étudié est rare et donc que les pro-
babilités sont faibles (inférieures à quelques pour-cents),
alors il est vrai que les odds ratio sont approximativement
égaux aux prevalence ratios. Mais ceci n’est plus du tout
vrai pour des phénomènes plus fréquents.
355
bold_labels()
Caractéristique log(OR) ET
Sexe
Femme — —
Homme 0,44*** 0,106
Groupe d’âges
18-24 ans — —
25-44 ans -0,42 0,228
45-64 ans -1,1*** 0,238
65 ans et plus -1,4*** 0,274
Niveau d’études
Primaire — —
Secondaire 0,95*** 0,197
Technique / Professionnel 1,0*** 0,190
Supérieur 1,9*** 0,195
Non documenté 2,2*** 0,330
Rapport à la religion
Pratiquant regulier — —
Pratiquant occasionnel -0,02 0,189
Appartenance sans pratique -0,01 0,175
Ni croyance ni appartenance -0,22 0,193
Rejet -0,38 0,286
NSP ou NVPR -0,08 0,411
Heures de télévision / jour -0,12*** 0,034
356
modelsummary::modelsummary() n’affiche pas les modalités
de référence, ni les étiquettes de variable.
[Link]
religNSP ou NVPR
religRejet
religNi croyance ni appartenance
religAppartenance sans pratique
religPratiquant occasionnel
etudesNon documenté
etudesSupérieur
etudesTechnique / Professionnel
etudesSecondaire
groupe_ages65 ans et plus
groupe_ages45−64 ans
groupe_ages25−44 ans
sexeHomme
(Intercept)
−2 −1 0 1 2 3
Coefficient estimates and 95% confidence intervals
mod |>
modelsummary::modelplot(exponentiate = TRUE) +
ggplot2::scale_x_log10()
357
Table 22.5: Présentation des facteurs associés à la pratique d’un
sport avec modelsummary()
(1)
(Intercept) −0.798*
(0.324)
sexeHomme 0.440***
(0.106)
groupe_ages25-44 ans −0.420+
(0.228)
groupe_ages45-64 ans −1.085***
(0.238)
groupe_ages65 ans et plus −1.381***
(0.274)
etudesSecondaire 0.951***
(0.197)
etudesTechnique / Professionnel 1.049***
(0.190)
etudesSupérieur 1.892***
(0.195)
etudesNon documenté 2.150***
(0.330)
religPratiquant occasionnel −0.022
(0.189)
religAppartenance sans pratique −0.007
(0.175)
religNi croyance ni appartenance −0.215
(0.193)
religRejet −0.384
(0.286)
religNSP ou NVPR −0.084
(0.411)
[Link] −0.121***
(0.034)
[Link]. 1995
AIC 2236.2
BIC 2320.1
[Link]. −1103.086
F 21.691
RMSE 0.43
+ p < 0.1, * p < 0.05, ** p < 0.01, *** p < 0.001
358
[Link]
religNSP ou NVPR
religRejet
religNi croyance ni appartenance
religAppartenance sans pratique
religPratiquant occasionnel
etudesNon documenté
etudesSupérieur
etudesTechnique / Professionnel
etudesSecondaire
groupe_ages65 ans et plus
groupe_ages45−64 ans
groupe_ages25−44 ans
sexeHomme
(Intercept)
0.3 1.0 3.0 10.0
Coefficient estimates and 95% confidence intervals
mod |>
tbl_regression(
exponentiate = TRUE,
add_pairwise_contrasts = TRUE
) |>
bold_labels()
mod |>
ggstats::ggcoef_model(
exponentiate = TRUE,
add_pairwise_contrasts = TRUE,
pairwise_variables = c("groupe_ages", "etudes")
)
360
Table 22.6: Facteurs associés à la pratique d’un sport (pairwise
contrasts)
361
Femme
Sexe Homme (p<0.001***)
(25−44 ans) / (18−24 ans) (p=0.253)
Groupe d'âges (45−64 ans) / (18−24 ans) (p<0.001***)
(45−64 ans) / (25−44 ans) (p<0.001***)
65 ans et plus / (18−24 ans) (p<0.001***)
65 ans et plus / (25−44 ans) (p<0.001***)
65 ans et plus / (45−64 ans) (p=0.335)
Secondaire / Primaire (p<0.001***)
Niveau d'études (Technique / Professionnel) / Primaire (p<0.001***)
(Technique / Professionnel) / Secondaire (p=0.961)
Supérieur / Primaire (p<0.001***)
Supérieur / Secondaire (p<0.001***)
Supérieur / (Technique / Professionnel) (p<0.001***)
Non documenté / Primaire (p<0.001***)
Non documenté / Secondaire (p<0.001***)
Non documenté / (Technique / Professionnel) (p=0.001**)
Non documenté / Supérieur (p=0.905)
Pratiquant regulier
Rapport à la religion Pratiquant occasionnel (p=0.908)
Appartenance sans pratique (p=0.969)
Ni croyance ni appartenance (p=0.265)
Rejet (p=0.180)
NSP ou NVPR (p=0.838)
Heures de télévision / jour (p<0.001***)
0.1
1.0
10.0
OR
car::Anova(mod)
Response: sport
LR Chisq Df Pr(>Chisq)
sexe 17.309 1 3.176e-05 ***
362
groupe_ages 52.803 3 2.020e-11 ***
etudes 123.826 4 < 2.2e-16 ***
relig 4.232 5 0.5165401
[Link] 13.438 1 0.0002465 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Ĺ Note
363
Table 22.7: Ajout des p-valeurs globales
364
interactions dans un prochain chapitre, cf. Chapitre 26).
En présence d’interactions, il est conseillé d’avoir plutôt
recours au type III. Cependant, en toute rigueur, pour
utiliser le type III, il faut que les variables catégorielles
soient codées en utilisant un contrastes dont la somme est
nulle (un contraste de type somme ou polynomial). Or,
par défaut, les variables catégorielles sont codées avec un
contraste de type traitement (nous aborderons les diffé-
rents types de contrastes plus tard, cf. Chapitre 25).
Par défaut, car::Anova() utilise le type II et
gtsummary::add_global_p() le type III. Dans les deux
cas, il est possible de préciser le type de test avec type =
"II" ou type = "III".
Dans le cas de notre exemple, un modèle simple sans in-
teraction, le type de test ne change pas les résultats.
d |>
tbl_uvregression(
y = sport,
include = c(sexe, groupe_ages, etudes, relig, [Link]),
method = glm,
[Link] = list(family = binomial),
365
Table 22.8: Régressions logistiques univariées
exponentiate = TRUE
) |>
bold_labels()
366
22.10 Présenter l’ensemble des résultats
dans un même tableau
tbl_desc <-
d |>
tbl_summary(
by = sport,
include = c(sexe, groupe_ages, etudes, relig, [Link]),
statistic = all_categorical() ~ "{p}% ({n}/{N})",
percent = "row",
digits = all_categorical() ~ c(1, 0, 0)
) |>
modify_column_hide("stat_1") |>
modify_header("stat_2" ~ "**Pratique d'un sport**")
tbl_uni <-
d |>
tbl_uvregression(
y = sport,
include = c(sexe, groupe_ages, etudes, relig, [Link]),
method = glm,
[Link] = list(family = binomial),
exponentiate = TRUE
) |>
modify_column_hide("stat_n")
tbl_multi <-
mod |>
tbl_regression(exponentiate = TRUE)
367
Table 22.9: tableau synthétique de l’analyse
"**Régressions univariées**",
"**Régression multivariée**"
)
) |>
bold_labels()
368
R/analyses/ressources/[Link]
22.11 webin-R
369
23 Sélection pas à pas d’un
modèle
370
library(tidyverse)
library(labelled)
library(gtsummary)
theme_gtsummary_language(
"fr",
[Link] = ",",
[Link] = " "
)
d <-
hdv2003 |>
mutate(
sexe = sexe |> fct_relevel("Femme"),
groupe_ages = age |>
cut(
c(18, 25, 45, 65, 99),
right = FALSE,
[Link] = TRUE,
labels = c("18-24 ans", "25-44 ans",
"45-64 ans", "65 ans et plus")
),
etudes = nivetud |>
fct_recode(
"Primaire" = "N'a jamais fait d'etudes",
"Primaire" = "A arrete ses etudes, avant la derniere annee d'etudes primaires",
"Primaire" = "Derniere annee d'etudes primaires",
"Secondaire" = "1er cycle",
"Secondaire" = "2eme cycle",
"Technique / Professionnel" = "Enseignement technique ou professionnel court",
"Technique / Professionnel" = "Enseignement technique ou professionnel long",
"Supérieur" = "Enseignement superieur y compris technique superieur"
) |>
fct_na_value_to_level("Non documenté")
) |>
set_variable_labels(
sport = "Pratique un sport ?",
sexe = "Sexe",
371
groupe_ages = "Groupe d'âges",
etudes = "Niveau d'études",
relig = "Rapport à la religion",
[Link] = "Lit des bandes dessinées ?"
)
AIC(mod)
[1] 2257.101
372
mod2 <- step(mod)
Start: AIC=2257.1
sport ~ sexe + groupe_ages + etudes + relig + [Link]
Df Deviance AIC
- relig 5 2231.9 2251.9
- [Link] 1 2227.9 2255.9
<none> 2227.1 2257.1
- sexe 1 2245.6 2273.6
- groupe_ages 3 2280.1 2304.1
- etudes 4 2375.5 2397.5
Step: AIC=2251.95
sport ~ sexe + groupe_ages + etudes + [Link]
Df Deviance AIC
- [Link] 1 2232.6 2250.6
<none> 2231.9 2251.9
- sexe 1 2248.8 2266.8
- groupe_ages 3 2282.1 2296.1
- etudes 4 2380.5 2392.5
Step: AIC=2250.56
sport ~ sexe + groupe_ages + etudes
Df Deviance AIC
<none> 2232.6 2250.6
- sexe 1 2249.2 2265.2
- groupe_ages 3 2282.5 2294.5
- etudes 4 2385.2 2395.2
373
Deviance) et donc une baisse de la vraisemblance du modèle,
mais cela est compensé par la réduction du nombre de degrés
de liberté.
Le processus est maintenant répété. À la seconde étape, suppri-
mer [Link] permettrait de diminuer encore l’AIC à 2250,6
et cette variable est supprimée.
À la troisième étape, tout retrait d’une variable additionnelle
reviendrait à augmenter l’AIC.
Lors de la seconde étape, toute suppression d’une autre variable
ferait augmenter l’AIC. La procédure s’arrête donc.
L’objet mod2 renvoyé par step() est le modèle final.
mod2
Coefficients:
(Intercept) sexeHomme
-1.2815 0.4234
groupe_ages25-44 ans groupe_ages45-64 ans
-0.3012 -0.9261
groupe_ages65 ans et plus etudesSecondaire
-1.2696 0.9670
etudesTechnique / Professionnel etudesSupérieur
1.0678 1.9955
etudesNon documenté
2.3192
374
Analysis of Deviance Table
Ď Astuce
library(MASS)
select
select
Start: AIC=2257.1
sport ~ sexe + groupe_ages + etudes + relig + [Link]
375
Df Deviance AIC
- relig 5 2231.9 2251.9
- [Link] 1 2227.9 2255.9
<none> 2227.1 2257.1
- sexe 1 2245.6 2273.6
- groupe_ages 3 2280.1 2304.1
- etudes 4 2375.5 2397.5
Step: AIC=2251.95
sport ~ sexe + groupe_ages + etudes + [Link]
Df Deviance AIC
- [Link] 1 2232.6 2250.6
<none> 2231.9 2251.9
- sexe 1 2248.8 2266.8
- groupe_ages 3 2282.1 2296.1
- etudes 4 2380.5 2392.5
Step: AIC=2250.56
sport ~ sexe + groupe_ages + etudes
Df Deviance AIC
<none> 2232.6 2250.6
- sexe 1 2249.2 2265.2
- groupe_ages 3 2282.5 2294.5
- etudes 4 2385.2 2395.2
library(ggstats)
ggcoef_compare(
list("modèle complet" = mod, "modèle réduit" = mod2),
exponentiate = TRUE
)
376
Femme
Sexe Homme
18−24 ans
Groupe d'âges 25−44 ans
45−64 ans
65 ans et plus
Primaire
Niveau d'études Secondaire
Technique / Professionnel
Supérieur
Non documenté
Pratiquant regulier
Rapport à la religion Pratiquant occasionnel
Appartenance sans pratique
Ni croyance ni appartenance
Rejet
NSP ou NVPR
Non
Lit des bandes dessinées ? Oui
0.3 1.0 3.0 10.0
OR
ggcoef_compare(
list("modèle complet" = mod, "modèle réduit" = mod2),
type = "faceted",
exponentiate = TRUE
)
377
23.4 Sélection pas à pas ascendante
Start: AIC=2619.11
sport ~ 1
Df Deviance AIC
+ etudes 4 2294.9 2304.9
+ groupe_ages 3 2405.4 2413.4
+ sexe 1 2600.2 2604.2
+ [Link] 1 2612.7 2616.7
<none> 2617.1 2619.1
+ relig 5 2608.8 2620.8
Step: AIC=2304.92
sport ~ etudes
378
Df Deviance AIC
+ groupe_ages 3 2249.2 2265.2
+ sexe 1 2282.5 2294.5
<none> 2294.9 2304.9
+ [Link] 1 2294.7 2306.7
+ relig 5 2293.0 2313.0
Step: AIC=2265.17
sport ~ etudes + groupe_ages
Df Deviance AIC
+ sexe 1 2232.6 2250.6
<none> 2249.2 2265.2
+ [Link] 1 2248.8 2266.8
+ relig 5 2246.0 2272.0
Step: AIC=2250.56
sport ~ etudes + groupe_ages + sexe
Df Deviance AIC
<none> 2232.6 2250.6
+ [Link] 1 2231.9 2251.9
+ relig 5 2227.9 2255.9
Ď Astuce
379
mod3 <- step(
mod_vide,
scope = list(
upper = ~ sexe + groupe_ages + etudes + relig + [Link]
)
)
Start: AIC=2619.11
sport ~ 1
Df Deviance AIC
+ etudes 4 2294.9 2304.9
+ groupe_ages 3 2405.4 2413.4
+ sexe 1 2600.2 2604.2
+ [Link] 1 2612.7 2616.7
<none> 2617.1 2619.1
+ relig 5 2608.8 2620.8
Step: AIC=2304.92
sport ~ etudes
Df Deviance AIC
+ groupe_ages 3 2249.2 2265.2
+ sexe 1 2282.5 2294.5
<none> 2294.9 2304.9
+ [Link] 1 2294.7 2306.7
+ relig 5 2293.0 2313.0
- etudes 4 2617.1 2619.1
Step: AIC=2265.17
sport ~ etudes + groupe_ages
Df Deviance AIC
+ sexe 1 2232.6 2250.6
<none> 2249.2 2265.2
+ [Link] 1 2248.8 2266.8
+ relig 5 2246.0 2272.0
- groupe_ages 3 2294.9 2304.9
- etudes 4 2405.4 2413.4
380
Step: AIC=2250.56
sport ~ etudes + groupe_ages + sexe
Df Deviance AIC
<none> 2232.6 2250.6
+ [Link] 1 2231.9 2251.9
+ relig 5 2227.9 2255.9
- sexe 1 2249.2 2265.2
- groupe_ages 3 2282.5 2294.5
- etudes 4 2385.2 2395.2
Start: AIC=2257.1
sport ~ sexe + groupe_ages + etudes + relig + [Link]
381
Df Deviance AIC
- relig 5 2231.9 2251.9
<none> 2227.1 2257.1
- sexe 1 2245.6 2273.6
- groupe_ages 3 2280.1 2304.1
- etudes 4 2375.5 2397.5
Step: AIC=2251.95
sport ~ sexe + groupe_ages + etudes + [Link]
Df Deviance AIC
<none> 2231.9 2251.9
- sexe 1 2248.8 2266.8
- groupe_ages 3 2282.1 2296.1
- etudes 4 2380.5 2392.5
mod4$formula
382
lesquelles des données sont manquantes. Dès lors, pour obte-
nir le nombre exact d’observations incluses dans le modèle, on
peut utiliser la syntaxe mod |> [Link]() |> nrow(),
[Link]() renvoyant la matrice de données ayant servi
au calcul du modèle et nrow() le nombre de lignes.
Start: AIC=2341.11
sport ~ sexe + groupe_ages + etudes + relig + [Link]
Df Deviance AIC
- relig 5 2231.9 2308.0
- [Link] 1 2227.9 2334.3
<none> 2227.1 2341.1
- sexe 1 2245.6 2352.0
- groupe_ages 3 2280.1 2371.3
- etudes 4 2375.5 2459.1
Step: AIC=2307.96
sport ~ sexe + groupe_ages + etudes + [Link]
Df Deviance AIC
- [Link] 1 2232.6 2301.0
<none> 2231.9 2308.0
- sexe 1 2248.8 2317.2
- groupe_ages 3 2282.1 2335.3
- etudes 4 2380.5 2426.1
Step: AIC=2300.97
sport ~ sexe + groupe_ages + etudes
Df Deviance AIC
<none> 2232.6 2301.0
- sexe 1 2249.2 2310.0
- groupe_ages 3 2282.5 2328.1
- etudes 4 2385.2 2423.2
383
23.7 Afficher les indicateurs de performance
# A tibble: 1 x 8
[Link] [Link] logLik AIC BIC deviance [Link] nobs
<dbl> <int> <dbl> <dbl> <dbl> <dbl> <int> <int>
1 2617. 1999 -1114. 2257. 2341. 2227. 1985 2000
Name | Model | AIC (weights) | AICc (weights) | BIC (weights) | Tjur's R2 | RMSE | Sigma | L
-----------------------------------------------------------------------------------------------
mod | glm | 2257.1 (0.025) | 2257.3 (0.023) | 2341.1 (<.001) | 0.183 | 0.434 | 1.000 |
mod2 | glm | 2250.6 (0.651) | 2250.7 (0.654) | 2301.0 (0.971) | 0.181 | 0.435 | 1.000 |
mod4 | glm | 2252.0 (0.325) | 2252.1 (0.323) | 2308.0 (0.029) | 0.181 | 0.435 | 1.000 |
384
mod2 |>
tbl_regression(exponentiate = TRUE) |>
bold_labels() |>
add_glance_source_note()
385
Prenons un exemple, en ajoutant des valeurs manquantes à la
variable relig (pour cela nous allons recoder les refus et les ne
sait pas en NA).
d$relig_na <-
d$relig |>
fct_recode(
NULL = "Rejet",
NULL = "NSP ou NVPR"
)
step(mod_na)
Start: AIC=2096.64
sport ~ sexe + groupe_ages + etudes + relig_na + [Link]
Df Deviance AIC
- relig_na 3 2073.2 2093.2
- [Link] 1 2072.2 2096.2
<none> 2070.6 2096.6
- sexe 1 2088.6 2112.6
- groupe_ages 3 2118.0 2138.0
- etudes 4 2218.1 2236.1
Error in step(mod_na): le nombre de lignes utilisées a changé : supprimer les valeurs manquante
386
2. calculer notre modèle complet à partir de ce jeu de don-
nées ;
3. appliquer step() ;
4. recalculer le modèle réduit en repartant du jeu de données
complet.
Start: AIC=2096.64
sport ~ sexe + groupe_ages + etudes + relig_na + [Link]
Df Deviance AIC
- relig_na 3 2073.2 2093.2
- [Link] 1 2072.2 2096.2
<none> 2070.6 2096.6
- sexe 1 2088.6 2112.6
- groupe_ages 3 2118.0 2138.0
- etudes 4 2218.1 2236.1
387
Step: AIC=2093.19
sport ~ sexe + groupe_ages + etudes + [Link]
Df Deviance AIC
- [Link] 1 2074.6 2092.6
<none> 2073.2 2093.2
- sexe 1 2090.2 2108.2
- groupe_ages 3 2118.5 2132.5
- etudes 4 2221.4 2233.4
Step: AIC=2092.59
sport ~ sexe + groupe_ages + etudes
Df Deviance AIC
<none> 2074.6 2092.6
- sexe 1 2091.1 2107.1
- groupe_ages 3 2119.6 2131.6
- etudes 4 2227.2 2237.2
Cela s’exécute sans problème car tous les sous-modèles sont cal-
culés à partir de d_complet et donc ont bien le même nombre
d’observations. Cependant, dans notre modèle réduit, on a re-
tiré 137 observations en raison d’une valeur manquante sur la
variable relig_na, variable qui n’est plus présente dans notre
modèle réduit. Il serait donc pertinent de réintégrer ces obser-
vations.
Nous allons donc recalculer le modèle réduit mais à partir
de d. Inutile de recopier à la main la formule du mo-
dèle réduit, car nous pouvons l’obtenir directement avec
mod_na_reduit$formula.
388
nombre d’observations, ce qui change très légèrement les valeurs
des coefficients.
Ď Astuce
anova(mod_na_reduit2, mod_na_reduit_direct)
389
24 Prédictions marginales,
contrastes marginaux &
effets marginaux
Á Avertissement
390
Ĺ Note
24.1 Terminologie
391
Nous présenterons ces différents concepts plus en détail dans la
suite de ce chapitre.
Plusieurs packages proposent des fonctions pour le calcul
d’estimations marginales, {marginaleffects}, {emmeans},
{margins}, {effects}, ou encore {ggeffects}, chacun avec
des approches et un vocabulaire légèrement différent.
Le package {[Link]} fournit plusieurs tidiers qui
permettent d’appeler les fonctions de ces autres packages
et de renvoyer un tableau de données compatible avec
la fonction [Link]::tidy_plus_plus() et dès
lors de pouvoir générer un tableau mis en forme avec
gtsummary::tbl_regression() ou un graphique avec
ggstats::ggcoef_model().
library(tidyverse)
library(labelled)
library(gtsummary)
theme_gtsummary_language(
"fr",
[Link] = ",",
[Link] = " "
)
d <-
hdv2003 |>
mutate(
sexe = sexe |> fct_relevel("Femme"),
groupe_ages = age |>
cut(
c(18, 25, 45, 65, 99),
392
right = FALSE,
[Link] = TRUE,
labels = c("18-24 ans", "25-44 ans",
"45-64 ans", "65 ans et plus")
),
etudes = nivetud |>
fct_recode(
"Primaire" = "N'a jamais fait d'etudes",
"Primaire" = "A arrete ses etudes, avant la derniere annee d'etudes primaires",
"Primaire" = "Derniere annee d'etudes primaires",
"Secondaire" = "1er cycle",
"Secondaire" = "2eme cycle",
"Technique / Professionnel" = "Enseignement technique ou professionnel court",
"Technique / Professionnel" = "Enseignement technique ou professionnel long",
"Supérieur" = "Enseignement superieur y compris technique superieur"
) |>
fct_na_value_to_level("Non documenté")
) |>
set_variable_labels(
sport = "Pratique un sport ?",
sexe = "Sexe",
groupe_ages = "Groupe d'âges",
etudes = "Niveau d'études",
[Link] = "Heures de télévision / jour"
)
mod |>
tbl_regression(exponentiate = TRUE) |>
bold_labels()
393
Table 24.1: Odds Ratios du modèle logistique
[1] 1995
colnames(mf)
394
24.3 Prédictions marginales
Nos deux jeux de données sont donc identiques pour toutes les
autres variables et ne varient que pour le sexe. Nous pouvons
maintenant prédire, à partir de notre modèle ajusté, la proba-
bilité de faire du sport de chacun des individus de ces deux
nouveaux jeux de données, puis à en calculer la moyenne.
[1] 0.324814
[1] 0.4036624
395
library(marginaleffects)
mod |>
predictions(variables = "sexe", by = "sexe", type = "response")
mod |>
predictions(variables = "[Link]", by = "[Link]", type = "response")
396
Ĺ Note
mod |>
tbl_regression(
tidy_fun = [Link]::tidy_marginal_predictions,
type = "response",
estimate_fun = scales::label_percent(accuracy = 0.1)
) |>
bold_labels() |>
modify_column_hide("[Link]")
Prédictions
Caractéristique Marginales Moyennes 95% IC
Sexe
Femme 32.5% 29.9% –
35.0%
Homme 40.4% 37.5% –
43.2%
Groupe d’âges
25-44 ans 42.7% 39.3% –
46.2%
18-24 ans 51.2% 42.2% –
60.1%
397
Prédictions
Caractéristique Marginales Moyennes 95% IC
45-64 ans 29.9% 26.6% –
33.2%
65 ans et plus 24.9% 19.7% –
30.0%
Niveau d’études
Supérieur 53.2% 48.4% –
57.9%
Non documenté 59.2% 47.0% –
71.5%
Primaire 16.1% 11.9% –
20.4%
Technique / 34.0% 30.3% –
Professionnel 37.7%
Secondaire 31.8% 27.2% –
36.4%
Heures de
télévision / jour
0 41.0% 37.6% –
44.3%
1 38.6% 36.2% –
41.0%
2 36.3% 34.3% –
38.2%
3 34.0% 31.7% –
36.2%
12 16.8% 8.6% –
25.1%
La fonction [Link]::plot_marginal_predictions()
permet de visualiser les prédictions marginales à la moyenne en
réalisant une liste de graphiques, un par variable, que nous pou-
vons combiner avec patchwork::wrap_plots(). L’opérateur &
permet d’appliquer une fonction de {ggplot2} à chaque sous-
graphique. Ici, nous allons uniformiser l’axe des y.
398
patchwork::wrap_plots() &
scale_y_continuous(
limits = c(0, .8),
labels = scales::label_percent()
)
80% 80%
60% 60%
40% 40%
20% 20%
0% 0%
Femme Homme 18−24 ans
25−44 ans
45−64 ans
65 ans et plus
Sexe Groupe d'âges
80% 80%
60% 60%
40% 40%
20% 20%
0% 0%
Primaire
Secondaire
Technique / Professionnel
Supérieur
Non documenté 0.0 2.5 5.0 7.5 10.0 12.5
Niveau d'études Heures de télévision / jour
p & coord_flip()
399
65 ans et plus
Groupe d'âges
Homme
45−64 ans
Sexe
2