Dernière mise à jour: 2026-10-23 19:45.
Pour télécharger et ouvrir ce fichier, vérifiez
d’abord d’être dans le bon dossier de
travail (working directory), puis copier-coller ces lignes
dans la console R:
download.file("https://matteo.gagliolo.web.ulb.be/INFOD203/factors.r",
"factors.r")
file.edit("factors.r")
Commencez, comme d’habitude, par charger les packages nécessaires pour cette leçon.
library("forcats")
library("dplyr")
Attaching package: 'dplyr'
The following objects are masked from 'package:stats':
filter, lag
The following objects are masked from 'package:base':
intersect, setdiff, setequal, union
library("questionr")
Pour plus d’infos: forcats. Voir
aussi le chapitre sur
le recodage dans le syllabus.
Dans cette leçon on a besoin de deux fonctions définies dans
dplyr: if_else et case_when. On
va aussi utiliser la fonction filter de façon intuitive,
dans quelques exemples. Dans la suite on aura toute une leçon sur
dplyr.
forcatsforcats?Le package forcats sert à manipuler des facteurs. Des
facteurs sont aussi appelés des variables qualitatives.
Rappel: Les variables qualitatives peuvent être de type
nominal ou ordinal. Dans R, une variable qualitative est de type
factor.
Dans ce chapitre, nous privilégierons le format factor,
auquel s’appliquent toutes les fonctions du package
forcats.
Dans cette leçon, vous aurez parfois l’impression de voir des
fonctions différentes qui peuvent être utilisées pour résoudre un même
problème. C’est normal, parce que c’est le cas, nous vous présentons
plusieurs outils, à vous de vous familiariser avec chacun, ils ont tous
leurs avantages et leurs inconvénients. Le package forcats
va donc nous être utile pour changer l’ordre des niveaux par exemple, ou
agréger deux niveaux. Nous allons voir différents exemples, au moyen
d’un mini jeu de données, ainsi que sur des data frames plus
conséquents.
Création d’un petit jeu de données pour comprendre les principes.
df <- data.frame(etudiant_ID = 1:7,
resultats_info = c(15, 17, 9, 13, 12, 10, 14),
section = c("SHUM","SOCA","POLI","SHUM","SOCA", "TRAV", "TRAV"),
annee = c("BA2", "MA1", "DOC", "MA1", "BA3", "MA1", "MA1"),
stringsAsFactors = TRUE)
Nous utiliserons aussi une base de données plus conséquente:
data("hdv2003")
Rappel: Demandez toujours un minimum d’information concernant vos données
class(df)
[1] "data.frame"
str(df)
'data.frame': 7 obs. of 4 variables:
$ etudiant_ID : int 1 2 3 4 5 6 7
$ resultats_info: num 15 17 9 13 12 10 14
$ section : Factor w/ 4 levels "POLI","SHUM",..: 2 3 1 2 3 4 4
$ annee : Factor w/ 4 levels "BA2","BA3","DOC",..: 1 4 3 4 2 4 4
Pour plus d’infos sur hdv2003: France;
voir description
dans le syllabus.
class(hdv2003)
[1] "data.frame"
str(hdv2003)
'data.frame': 2000 obs. of 20 variables:
$ id : int 1 2 3 4 5 6 7 8 9 10 ...
$ age : int 28 23 59 34 71 35 60 47 20 28 ...
$ sexe : Factor w/ 2 levels "Homme","Femme": 2 2 1 1 2 2 2 1 2 1 ...
$ nivetud : Factor w/ 8 levels "N'a jamais fait d'etudes",..: 8 NA 3 8 3 6 3 6 NA 7 ...
$ poids : num 2634 9738 3994 5732 4329 ...
$ occup : Factor w/ 7 levels "Exerce une profession",..: 1 3 1 1 4 1 6 1 3 1 ...
$ qualif : Factor w/ 7 levels "Ouvrier specialise",..: 6 NA 3 3 6 6 2 2 NA 7 ...
$ freres.soeurs: int 8 2 2 1 0 5 1 5 4 2 ...
$ clso : Factor w/ 3 levels "Oui","Non","Ne sait pas": 1 1 2 2 1 2 1 2 1 2 ...
$ relig : Factor w/ 6 levels "Pratiquant regulier",..: 4 4 4 3 1 4 3 4 3 2 ...
$ trav.imp : Factor w/ 4 levels "Le plus important",..: 4 NA 2 3 NA 1 NA 4 NA 3 ...
$ trav.satisf : Factor w/ 3 levels "Satisfaction",..: 2 NA 3 1 NA 3 NA 2 NA 1 ...
$ hard.rock : Factor w/ 2 levels "Non","Oui": 1 1 1 1 1 1 1 1 1 1 ...
$ lecture.bd : Factor w/ 2 levels "Non","Oui": 1 1 1 1 1 1 1 1 1 1 ...
$ peche.chasse : Factor w/ 2 levels "Non","Oui": 1 1 1 1 1 1 2 2 1 1 ...
$ cuisine : Factor w/ 2 levels "Non","Oui": 2 1 1 2 1 1 2 2 1 1 ...
$ bricol : Factor w/ 2 levels "Non","Oui": 1 1 1 2 1 1 1 2 1 1 ...
$ cinema : Factor w/ 2 levels "Non","Oui": 1 2 1 2 1 2 1 1 2 2 ...
$ sport : Factor w/ 2 levels "Non","Oui": 1 2 2 2 1 2 1 1 1 2 ...
$ heures.tv : num 0 1 0 2 3 2 2.9 1 2 2 ...
Rappel: Si l’on veut connaître les niveaux d’un
facteur, on emploie la fonction levels, comme dans
l’exemple ci-dessous.
levels(hdv2003$nivetud)
[1] "N'a jamais fait d'etudes"
[2] "A arrete ses etudes, avant la derniere annee d'etudes primaires"
[3] "Derniere annee d'etudes primaires"
[4] "1er cycle"
[5] "2eme cycle"
[6] "Enseignement technique ou professionnel court"
[7] "Enseignement technique ou professionnel long"
[8] "Enseignement superieur y compris technique superieur"
Rappel: Si l’on souhaite obtenir une table des
effectifs, on emploie la fonction summary (NA inclues) ou
table (sans NA) .
summary(hdv2003$nivetud)
N'a jamais fait d'etudes
39
A arrete ses etudes, avant la derniere annee d'etudes primaires
86
Derniere annee d'etudes primaires
341
1er cycle
204
2eme cycle
183
Enseignement technique ou professionnel court
463
Enseignement technique ou professionnel long
131
Enseignement superieur y compris technique superieur
441
NA's
112
table(hdv2003$nivetud)
N'a jamais fait d'etudes
39
A arrete ses etudes, avant la derniere annee d'etudes primaires
86
Derniere annee d'etudes primaires
341
1er cycle
204
2eme cycle
183
Enseignement technique ou professionnel court
463
Enseignement technique ou professionnel long
131
Enseignement superieur y compris technique superieur
441
Astuce: on peut visualiser les NA aussi
avec table, en passant le paramètre useNA,
avec valeur "ifany" (uniquement si presents) ou
"always" (montrer en tout cas).
table(hdv2003$nivetud, useNA = "always")
N'a jamais fait d'etudes
39
A arrete ses etudes, avant la derniere annee d'etudes primaires
86
Derniere annee d'etudes primaires
341
1er cycle
204
2eme cycle
183
Enseignement technique ou professionnel court
463
Enseignement technique ou professionnel long
131
Enseignement superieur y compris technique superieur
441
<NA>
112
Quand on manipule des facteurs, R garde soigneusement
les valeurs possibles pour ses niveaux parmi les metadata, même si aucun
individu n’est recensé dans ce niveau. Par exemple, si je crée un
sous-ensemble de df sans l’étudiant en sciences politiques,
j’obtiens ceci:
df_sanspoli <- filter(df, section != "POLI")
df_sanspoli
etudiant_ID resultats_info section annee
1 1 15 SHUM BA2
2 2 17 SOCA MA1
3 4 13 SHUM MA1
4 5 12 SOCA BA3
5 6 10 TRAV MA1
6 7 14 TRAV MA1
Et pourtant, si je demande les niveaux du facteur
section pour ce sous-ensemble, "POLI" y est
repris. Il faudrait utiliser unique pour ne voir que les
niveaux effectivement présents, comme nous l’avons fait dans dplyr pour
vérifier nos résultats.
levels(df_sanspoli$section)
[1] "POLI" "SHUM" "SOCA" "TRAV"
unique(df_sanspoli$section)
[1] SHUM SOCA TRAV
Levels: POLI SHUM SOCA TRAV
factorEssayons de créer un nouveau facteur, d’abord, sous forme de vecteur,
très simple. Nous voyons ici qu’il s’agit d’une variable de type
character.
df$dpmt <- c("sciences sociales", "sciences sociales",
"sciences politiques", "sciences sociales",
"sciences sociales", "sciences sociales",
"sciences sociales")
class(df$dpmt)
[1] "character"
length(df$dpmt)
[1] 7
Pour créer un vecteur de classe factor, afin de pouvoir
employer le package forcats pour de futures manipulation,
il faut utiliser la fonction factor.
df$dpmt <- factor(df$dpmt)
levels(df$dpmt)
[1] "sciences politiques" "sciences sociales"
On peut aussi transformer une variable chr en
factor:
df$dpmt <- as.factor(c("sciences sociales", "sciences sociales",
"sciences politiques", "sciences sociales",
"sciences sociales", "sciences sociales",
"sciences sociales"))
levels(df$dpmt)
[1] "sciences politiques" "sciences sociales"
factor crée un facteur à partir de son
premier argument.arrange (cf. dplyr), le tri se fera par
ordre alphabétique.levelsOn peut choisir les niveaux, et leur ordre, avec le deuxième
paramètre de la fonction, levels. Par exemple, ici, je
souhaite permuter l’ordre et placer les sciences sociales d’abord.
df$dpmt2 <- factor(df$dpmt, levels = c("sciences sociales", "sciences politiques"))
df$dpmt2
[1] sciences sociales sciences sociales sciences politiques
[4] sciences sociales sciences sociales sciences sociales
[7] sciences sociales
Levels: sciences sociales sciences politiques
levels(df$dpmt2)
[1] "sciences sociales" "sciences politiques"
Rappel: Remarquez que l’on donne un nouveau nom au facteur créé. Cela évite d’écraser le facteur original par un facteur qui n’est pas le résultat que l’on souhaite.
Je peux bien entendu intégrer des niveaux supplémentaires. Admettons que le deuxième étudiant soit finalement un étudiant en grh… Tentons de lui assigner une nouvelle valeur.
df$section[2] <- "GRH"
Warning in `[<-.factor`(`*tmp*`, 2, value = structure(c(2L, NA, 1L, 2L, :
invalid factor level, NA generated
df$section
[1] SHUM <NA> POLI SHUM SOCA TRAV TRAV
Levels: POLI SHUM SOCA TRAV
R nous dit que c’est impossible, et a généré une NA
parce qu’il n’a pas trouvé ce niveau dans la liste des niveaux du jeu de
données. Il faut donc d’abord créer ce niveau avant de pouvoir
l’assigner à un individu.
df$section <- factor(df$section, levels = c("GRH", "SHUM", "SOCA", "POLI", "TRAV"))
df$section
[1] SHUM <NA> POLI SHUM SOCA TRAV TRAV
Levels: GRH SHUM SOCA POLI TRAV
levels(df$section)
[1] "GRH" "SHUM" "SOCA" "POLI" "TRAV"
df$section[2] <- "GRH"
df$section
[1] SHUM GRH POLI SHUM SOCA TRAV TRAV
Levels: GRH SHUM SOCA POLI TRAV
labelsOn peut renommer les niveaux, leur donner une sorte d’étiquette. Pour
la comparaison, c’est comme si vous aviez le nom latin d’une plante, et
puis son nom commun, que tout le monde connaît. De la même manière le
level est le nom officiel du niveau, et son
label est le nom qui s’affichera dans la base de données,
les graphiques, les tables, etc. Pour chaque level, un
label doit être spécifié.
df$section2 <- factor(df$section,
levels = c("SHUM", "SOCA", "POLI", "TRAV", "GRH"),
labels = c("Sc.Humaines", "Socio.Anthropo",
"Sc.Politique", "Sc.Travail",
"Gestion des ressources humaines"))
df$section2
[1] Sc.Humaines Gestion des ressources humaines
[3] Sc.Politique Sc.Humaines
[5] Socio.Anthropo Sc.Travail
[7] Sc.Travail
5 Levels: Sc.Humaines Socio.Anthropo Sc.Politique ... Gestion des ressources humaines
df
etudiant_ID resultats_info section annee dpmt
1 1 15 SHUM BA2 sciences sociales
2 2 17 GRH MA1 sciences sociales
3 3 9 POLI DOC sciences politiques
4 4 13 SHUM MA1 sciences sociales
5 5 12 SOCA BA3 sciences sociales
6 6 10 TRAV MA1 sciences sociales
7 7 14 TRAV MA1 sciences sociales
dpmt2 section2
1 sciences sociales Sc.Humaines
2 sciences sociales Gestion des ressources humaines
3 sciences politiques Sc.Politique
4 sciences sociales Sc.Humaines
5 sciences sociales Socio.Anthropo
6 sciences sociales Sc.Travail
7 sciences sociales Sc.Travail
Quand un facteur représente une variable ordinale,
c’est à dire avec une relation d’ordre définie entre ses niveaux, il est
préférable de l’encoder comme facteur ordonné, et pas l’ordre
alphabétique par défaut. Cette opération est simple et donne l’avantage
de pouvoir utiliser les relations
d’ordre(<,>,<=,>=)
sur la variable résultante.
Par exemple: si on vous demande de classer la réception de votre wifi à la maison entre très mauvaise, mauvaise, neutre, bonne, très bonne, les données résultantes peuvent être encodés dans un facteur ordonné, avec cet ordre:
"très mauvaise" < "mauvaise" < "neutre" < "bonne" < "très bonne"
On va commencer par un exemple encore plus simple sur base de notre
mini jeu de données. Si l’on regarde la variable annee par
exemple, celle-ci est par défaut organisée par ordre alphabétique:
levels(df$annee)
[1] "BA2" "BA3" "DOC" "MA1"
Or, le doctorat vient après le master, dans l’ordre social des choses. On peut donc ré-ordonner le facteur.
df$annee_ord <- factor(df$annee,
levels = c("BA1", "BA2", "BA3", "MA1", "MA2", "DOC") ,
ordered = TRUE)
levels(df$annee_ord)
[1] "BA1" "BA2" "BA3" "MA1" "MA2" "DOC"
Remarquez qu’on rajoute tous les niveaux possibles, mêmes ceux qui sont absents dans ce jeu de données. C’est une bonne pratique: si les données changent, le code est déjà prêt!
On peut maintenant utiliser les relations d’ordre. Cela permet de
gagner en clarté et synthèse. Par exemple, on peut utiliser la relation
<= pour sélectionner tous les niveaux inférieurs ou
égales à "BA3":
filter(df, annee_ord <= "BA3")
etudiant_ID resultats_info section annee dpmt dpmt2
1 1 15 SHUM BA2 sciences sociales sciences sociales
2 5 12 SOCA BA3 sciences sociales sciences sociales
section2 annee_ord
1 Sc.Humaines BA2
2 Socio.Anthropo BA3
Attention: Sans l’argument ordered = TRUE,
vos niveaux seront effectivement dans un autre ordre que l’ordre
alphabétique mais le facteur ne sera pas considéré comme ordonné, ce qui
vous empêchera d’utiliser les relations logiques.
Astuce: il est possible de convertir en facteur
ordonné, un facteur existant dont les niveaux sont déjà dans l’ordre en
utilisant la fonction as.ordered.
levels(df$annee_ord)
[1] "BA1" "BA2" "BA3" "MA1" "MA2" "DOC"
as.ordered(df$annee_ord)
[1] BA2 MA1 DOC MA1 BA3 MA1 MA1
Levels: BA1 < BA2 < BA3 < MA1 < MA2 < DOC
forcatsfct_recodefct_recodeJe peux utiliser fct_recode pour assigner de nouveaux
labels à plusieurs niveaux.
Le premier argument est le facteur, suivi par une série de commandes
d’assignation séparés par virgule, dans cette forme:
"nouveau label" = "ancien label". Les niveaux qui ne sont
pas nommés sont laissés invariés.
df$section_rec <- fct_recode(df$section, "Sc.humaines" = "SHUM",
"Sc.Politique" = "POLI")
table(df$section, df$section_rec, useNA = "always")
GRH Sc.humaines SOCA Sc.Politique TRAV <NA>
GRH 1 0 0 0 0 0
SHUM 0 2 0 0 0 0
SOCA 0 0 1 0 0 0
POLI 0 0 0 1 0 0
TRAV 0 0 0 0 2 0
<NA> 0 0 0 0 0 0
occup.
Rappel: employez la fonction dput pour
obtenir les niveaux des variables sous forme de vecteur, cela vous
permet de copier/coller facilement les niveaux et vous évite le piège
des fautes de frappe.
dput(levels(hdv2003$occup))
c("Exerce une profession", "Chomeur", "Etudiant, eleve", "Retraite",
"Retire des affaires", "Au foyer", "Autre inactif")
hdv2003$occup_rcd <- fct_recode(hdv2003$occup, "Emploi" = "Exerce une profession",
"Chomage" = "Chomeur",
"Etudes" = "Etudiant, eleve")
table(hdv2003$occup, hdv2003$occup_rcd, useNA = "always")
Emploi Chomage Etudes Retraite Retire des affaires
Exerce une profession 1049 0 0 0 0
Chomeur 0 134 0 0 0
Etudiant, eleve 0 0 94 0 0
Retraite 0 0 0 392 0
Retire des affaires 0 0 0 0 77
Au foyer 0 0 0 0 0
Autre inactif 0 0 0 0 0
<NA> 0 0 0 0 0
Au foyer Autre inactif <NA>
Exerce une profession 0 0 0
Chomeur 0 0 0
Etudiant, eleve 0 0 0
Retraite 0 0 0
Retire des affaires 0 0 0
Au foyer 171 0 0
Autre inactif 0 83 0
<NA> 0 0 0
fct_collapsefct_collapseParfois, il est souhaitable de regrouper certains niveaux, de les
agréger. C’est le cas si vous avez un effectif assez faible dans l’un ou
l’autre niveau qui pourraient dès lors n’en former qu’un seul, à
condition que cela soit justifié. En effet, dans vos cours de
méthodologie, vous avez déjà vu que catégoriser, c’est faire des choix.
Et ceux-ci doivent être explicités clairement. On a pour habitude de
dire qu’on ne collecte pas des données mais qu’on les construit. Et
l’agrégation fait partie de cette construction.
fct_collapse permet des assignations groupées ainsi:
"niveau agrégé" = c("niveau1", "niveau2", ...). La fonction
dput devient alors carrément pratique dans ce cas.
dput(levels(df$section))
c("GRH", "SHUM", "SOCA", "POLI", "TRAV")
df$dpmt <- fct_collapse(df$section, "Sc.Sociale" = c("SHUM", "SOCA", "TRAV", "GRH"),
"Sc.Politique" = "POLI")
df
etudiant_ID resultats_info section annee dpmt dpmt2
1 1 15 SHUM BA2 Sc.Sociale sciences sociales
2 2 17 GRH MA1 Sc.Sociale sciences sociales
3 3 9 POLI DOC Sc.Politique sciences politiques
4 4 13 SHUM MA1 Sc.Sociale sciences sociales
5 5 12 SOCA BA3 Sc.Sociale sciences sociales
6 6 10 TRAV MA1 Sc.Sociale sciences sociales
7 7 14 TRAV MA1 Sc.Sociale sciences sociales
section2 annee_ord section_rec
1 Sc.Humaines BA2 Sc.humaines
2 Gestion des ressources humaines MA1 GRH
3 Sc.Politique DOC Sc.Politique
4 Sc.Humaines MA1 Sc.humaines
5 Socio.Anthropo BA3 SOCA
6 Sc.Travail MA1 TRAV
7 Sc.Travail MA1 TRAV
Voyons un exemple sur une base de données plus conséquente. Admettons que l’on souhaite pouvoir créer un facteur binaire, déterminant si une personne est active ou non sur le marché de l’emploi (notez que les chômeurs sont considérés comme actifs, puisqu’ils recherchent un emploi).
dput(levels(hdv2003$occup))
c("Exerce une profession", "Chomeur", "Etudiant, eleve", "Retraite",
"Retire des affaires", "Au foyer", "Autre inactif")
hdv2003$occup_agr <- fct_collapse(hdv2003$occup,
"Actif" = c("Exerce une profession", "Chomeur"),
"Inactif" = c("Etudiant, eleve",
"Retraite",
"Retire des affaires",
"Au foyer",
"Autre inactif"))
table(hdv2003$occup, hdv2003$occup_agr, useNA = "always")
Actif Inactif <NA>
Exerce une profession 1049 0 0
Chomeur 134 0 0
Etudiant, eleve 0 94 0
Retraite 0 392 0
Retire des affaires 0 77 0
Au foyer 0 171 0
Autre inactif 0 83 0
<NA> 0 0 0
fct_relevelfct_relevelNous avons déjà vu que c’était possible en début de chapitre. Cette fonction est équivalente. Il suffit de reclasser les niveaux dans l’ordre. Dans l’exemple ci-dessous, le doctorat vient avant le master, on doit donc le ré-ordonner.
levels(df$annee)
[1] "BA2" "BA3" "DOC" "MA1"
df$annee_ord <- fct_relevel(df$annee, "BA2", "BA3", "MA1", "DOC")
levels(df$annee_ord)
[1] "BA2" "BA3" "MA1" "DOC"
Dans cet exemple, on souhaiterait placer les cadres après les employés dans la classification.
dput(levels(hdv2003$qualif))
c("Ouvrier specialise", "Ouvrier qualifie", "Technicien", "Profession intermediaire",
"Cadre", "Employe", "Autre")
On réordonne (toujours sans écraser) - vous en avez sans doute marre de nous l’entendre dire, mais on le répète parce que ça arrive encore trop souvent.
hdv2003$qualif_rlv <- fct_relevel(hdv2003$qualif,
"Ouvrier specialise",
"Ouvrier qualifie", "Technicien",
"Profession intermediaire",
"Employe", "Cadre")
levels(hdv2003$qualif_rlv)
[1] "Ouvrier specialise" "Ouvrier qualifie"
[3] "Technicien" "Profession intermediaire"
[5] "Employe" "Cadre"
[7] "Autre"
table(hdv2003$qualif, hdv2003$qualif_rlv, useNA = "always")
Ouvrier specialise Ouvrier qualifie Technicien
Ouvrier specialise 203 0 0
Ouvrier qualifie 0 292 0
Technicien 0 0 86
Profession intermediaire 0 0 0
Cadre 0 0 0
Employe 0 0 0
Autre 0 0 0
<NA> 0 0 0
Profession intermediaire Employe Cadre Autre <NA>
Ouvrier specialise 0 0 0 0 0
Ouvrier qualifie 0 0 0 0 0
Technicien 0 0 0 0 0
Profession intermediaire 160 0 0 0 0
Cadre 0 0 260 0 0
Employe 0 594 0 0 0
Autre 0 0 0 58 0
<NA> 0 0 0 0 347
Si on veut juste déplacer quelques niveaux au début, on peut omettre les autres, dans ce cas ils vont suivre en gardant le même ordre. Dans l’exemple ci-dessus, nous avons omis le niveau “Autre” parce qu’il suivait automatiquement.
cutcutCette fonction vous permet de créer des classes/niveaux à partir
d’une variable quantitative. Dans le cadre d’un questionnaire, si le
répondant connaît la réponse précise à une question, il vaut toujours
mieux lui laisser l’opportunité de répondre le plus précisément possible
(âge, nombre d’enfants), quitte à créer des classes par après. Notez
bien que dans certains cas, il est plus facile pour un répondant de se
retrouver dans des classes que d’identifier un nombre précis (Ex: le
montant hebdomadaire des courses pour le ménage). Cette fonction
contient un paramètre breaks qui symbolisent les points de
découpe des classes dans votre variable quantitative originale. Par
exemple, si l’on souhaite distinguer deux classes d’étudiants, ceux qui
ont réussi, et ceux qui ont échoué, on doit créer deux classes, l’une
allant de 0 à 9 (inclus), et l’une de 10 à 20 (inclus). On coupe donc la
variable originale à 0, 9 et 20.
df$statut <- cut(df$resultats_info, breaks = c(0, 9, 20))
df
etudiant_ID resultats_info section annee dpmt dpmt2
1 1 15 SHUM BA2 Sc.Sociale sciences sociales
2 2 17 GRH MA1 Sc.Sociale sciences sociales
3 3 9 POLI DOC Sc.Politique sciences politiques
4 4 13 SHUM MA1 Sc.Sociale sciences sociales
5 5 12 SOCA BA3 Sc.Sociale sciences sociales
6 6 10 TRAV MA1 Sc.Sociale sciences sociales
7 7 14 TRAV MA1 Sc.Sociale sciences sociales
section2 annee_ord section_rec statut
1 Sc.Humaines BA2 Sc.humaines (9,20]
2 Gestion des ressources humaines MA1 GRH (9,20]
3 Sc.Politique DOC Sc.Politique (0,9]
4 Sc.Humaines MA1 Sc.humaines (9,20]
5 Socio.Anthropo BA3 SOCA (9,20]
6 Sc.Travail MA1 TRAV (9,20]
7 Sc.Travail MA1 TRAV (9,20]
Attention: Par défaut, les niveaux incluent l’extrême droit et excluent l’extrême gauche de chaque intervalle: ce sont donc les intervalles ]0;9] et ]9;20]. En notation anglophone, la ( équivaut au ] : (0, 9] et (9, 20].
Le 6ème étudiant qui a obtenu 0 n’appartient à aucun
intervalle, il est donc devenu une NA. il faut donc
employer un paramètre supplémentaire pour inclure la valeur extrême
gauche: include.lowest = TRUE.
df$statut <- cut(df$resultats_info, breaks = c(0, 9, 20),
include.lowest = TRUE)
df
etudiant_ID resultats_info section annee dpmt dpmt2
1 1 15 SHUM BA2 Sc.Sociale sciences sociales
2 2 17 GRH MA1 Sc.Sociale sciences sociales
3 3 9 POLI DOC Sc.Politique sciences politiques
4 4 13 SHUM MA1 Sc.Sociale sciences sociales
5 5 12 SOCA BA3 Sc.Sociale sciences sociales
6 6 10 TRAV MA1 Sc.Sociale sciences sociales
7 7 14 TRAV MA1 Sc.Sociale sciences sociales
section2 annee_ord section_rec statut
1 Sc.Humaines BA2 Sc.humaines (9,20]
2 Gestion des ressources humaines MA1 GRH (9,20]
3 Sc.Politique DOC Sc.Politique [0,9]
4 Sc.Humaines MA1 Sc.humaines (9,20]
5 Socio.Anthropo BA3 SOCA (9,20]
6 Sc.Travail MA1 TRAV (9,20]
7 Sc.Travail MA1 TRAV (9,20]
On peut aussi choisir d’inclure l’extrême gauche de chaque
intervalle, plutôt que le droit, en ajoutant le paramètre
right = FALSE, mais pour obtenir le même résultat, il faut
alors modifier les breaks:
df$statut <- cut(df$resultats_info, breaks = c(0, 10, 20),
right= FALSE, include.lowest = TRUE)
df
etudiant_ID resultats_info section annee dpmt dpmt2
1 1 15 SHUM BA2 Sc.Sociale sciences sociales
2 2 17 GRH MA1 Sc.Sociale sciences sociales
3 3 9 POLI DOC Sc.Politique sciences politiques
4 4 13 SHUM MA1 Sc.Sociale sciences sociales
5 5 12 SOCA BA3 Sc.Sociale sciences sociales
6 6 10 TRAV MA1 Sc.Sociale sciences sociales
7 7 14 TRAV MA1 Sc.Sociale sciences sociales
section2 annee_ord section_rec statut
1 Sc.Humaines BA2 Sc.humaines [10,20]
2 Gestion des ressources humaines MA1 GRH [10,20]
3 Sc.Politique DOC Sc.Politique [0,10)
4 Sc.Humaines MA1 Sc.humaines [10,20]
5 Socio.Anthropo BA3 SOCA [10,20]
6 Sc.Travail MA1 TRAV [10,20]
7 Sc.Travail MA1 TRAV [10,20]
Notez que les paramètres que vus au point 1. sont toujours valables
ici. labels peut être utilisé pour renommer les
niveaux:
df$statut <- cut(df$resultats_info, breaks = c(0, 10, 20),
right= FALSE, include.lowest = TRUE,
labels = c("échec", "réussite"))
df
etudiant_ID resultats_info section annee dpmt dpmt2
1 1 15 SHUM BA2 Sc.Sociale sciences sociales
2 2 17 GRH MA1 Sc.Sociale sciences sociales
3 3 9 POLI DOC Sc.Politique sciences politiques
4 4 13 SHUM MA1 Sc.Sociale sciences sociales
5 5 12 SOCA BA3 Sc.Sociale sciences sociales
6 6 10 TRAV MA1 Sc.Sociale sciences sociales
7 7 14 TRAV MA1 Sc.Sociale sciences sociales
section2 annee_ord section_rec statut
1 Sc.Humaines BA2 Sc.humaines réussite
2 Gestion des ressources humaines MA1 GRH réussite
3 Sc.Politique DOC Sc.Politique échec
4 Sc.Humaines MA1 Sc.humaines réussite
5 Socio.Anthropo BA3 SOCA réussite
6 Sc.Travail MA1 TRAV réussite
7 Sc.Travail MA1 TRAV réussite
levels(df$statut)
[1] "échec" "réussite"
Sur base d’hdv2003, nous souhaiterions déterminer des classes de consommation de télévision.
summary(hdv2003$heures.tv)
Min. 1st Qu. Median Mean 3rd Qu. Max. NA's
0.000 1.000 2.000 2.247 3.000 12.000 5
Sachant que le minimum ici vaut 0 et le maximum 12, que la durée moyenne d’un film avoisine les 2 heures et que la dépendance à la télévision ne se définit pas qu’en termes de temps passé devant, partons donc sur cinq classes, une première de non-consommateurs (0), une de consommateurs modérés (entre 0 exclu et 1h), une autre de consommateurs moyens (entre 1h et 3h), une de grands consommateurs (entre 3 et 5h), et une de très grands consommateurs (plus que 5h).
hdv2003$conso_tv <- cut(hdv2003$heures.tv, breaks = c(0, 0.01, 1, 3, 5, 24),
include.lowest = TRUE, right = FALSE,
labels = c("Non-conso", "Conso modérée",
"Conso moyenne", "Grande conso", "Très grande conso"))
Ici on joue avec les breaks pour avoir un niveau
correspondant à 0 heures, "Non-conso"; on inclût l’extrême
gauche dans chaque niveau (right = FALSE); on inclût le
maximum théorique (24h) dans le plus haut niveau, [5, 24]
(include.lowest = TRUE). En effet, avec
right = FALSE, include.lowest va inclure
l’extrême droit du plus haut niveau.
head(hdv2003) # ça semble correct
id age sexe nivetud poids
1 1 28 Femme Enseignement superieur y compris technique superieur 2634.398
2 2 23 Femme <NA> 9738.396
3 3 59 Homme Derniere annee d'etudes primaires 3994.102
4 4 34 Homme Enseignement superieur y compris technique superieur 5731.662
5 5 71 Femme Derniere annee d'etudes primaires 4329.094
6 6 35 Femme Enseignement technique ou professionnel court 8674.699
occup qualif freres.soeurs clso
1 Exerce une profession Employe 8 Oui
2 Etudiant, eleve <NA> 2 Oui
3 Exerce une profession Technicien 2 Non
4 Exerce une profession Technicien 1 Non
5 Retraite Employe 0 Oui
6 Exerce une profession Employe 5 Non
relig trav.imp trav.satisf
1 Ni croyance ni appartenance Peu important Insatisfaction
2 Ni croyance ni appartenance <NA> <NA>
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
hard.rock lecture.bd peche.chasse cuisine bricol cinema sport heures.tv
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
occup_rcd occup_agr qualif_rlv conso_tv
1 Emploi Actif Employe Non-conso
2 Etudes Inactif <NA> Conso moyenne
3 Emploi Actif Technicien Non-conso
4 Emploi Actif Technicien Conso moyenne
5 Retraite Inactif Employe Grande conso
6 Emploi Actif Employe Conso moyenne
table(hdv2003$heures.tv, hdv2003$conso_tv, useNA = "always")
Non-conso Conso modérée Conso moyenne Grande conso Très grande conso
0 239 0 0 0 0
0.1 0 26 0 0 0
0.2 0 2 0 0 0
0.3 0 29 0 0 0
0.4 0 46 0 0 0
0.6 0 19 0 0 0
0.7 0 21 0 0 0
0.9 0 12 0 0 0
1 0 0 290 0 0
1.1 0 0 12 0 0
1.4 0 0 24 0 0
1.7 0 0 5 0 0
2 0 0 494 0 0
2.1 0 0 7 0 0
2.7 0 0 1 0 0
2.9 0 0 8 0 0
3 0 0 0 388 0
4 0 0 0 190 0
4.3 0 0 0 1 0
4.6 0 0 0 1 0
5 0 0 0 0 86
5.1 0 0 0 0 1
6 0 0 0 0 49
7 0 0 0 0 13
8 0 0 0 0 13
9 0 0 0 0 2
10 0 0 0 0 12
11 0 0 0 0 2
12 0 0 0 0 2
<NA> 0 0 0 0 0
<NA>
0 0
0.1 0
0.2 0
0.3 0
0.4 0
0.6 0
0.7 0
0.9 0
1 0
1.1 0
1.4 0
1.7 0
2 0
2.1 0
2.7 0
2.9 0
3 0
4 0
4.3 0
4.6 0
5 0
5.1 0
6 0
7 0
8 0
9 0
10 0
11 0
12 0
<NA> 5
Tout comme prévu, la catégorie "Non-conso" inclut
uniquement les 0, et les 5 NA sont restés tels.
if_elseif_elseCette fonction est inclue dans le package dplyr. Elle
est une version améliorée de la fonction de base ifelse.
Elle se décompose de la façon suivante:
condition) est typiquement le
résultat d’une relation ou opération logique. C’est une condition que
vous imposez;true) est une valeur ou un niveau
que vous attribuez lorsque la condition est vraie;false) est une valeur ou un niveau que
vous attribuez lorsque la condition est fausse;À l’issue du processus, vous obtenez une variable binaire. Par exemple, reprenons le même exemple que précédemment, vous souhaitez créer une variable statut qui serait échec ou réussite en fonction du résultat de l’étudiant.
df$statut2 <- factor(if_else(df$resultats_info > 9, "réussite", "échec"))
df
etudiant_ID resultats_info section annee dpmt dpmt2
1 1 15 SHUM BA2 Sc.Sociale sciences sociales
2 2 17 GRH MA1 Sc.Sociale sciences sociales
3 3 9 POLI DOC Sc.Politique sciences politiques
4 4 13 SHUM MA1 Sc.Sociale sciences sociales
5 5 12 SOCA BA3 Sc.Sociale sciences sociales
6 6 10 TRAV MA1 Sc.Sociale sciences sociales
7 7 14 TRAV MA1 Sc.Sociale sciences sociales
section2 annee_ord section_rec statut statut2
1 Sc.Humaines BA2 Sc.humaines réussite réussite
2 Gestion des ressources humaines MA1 GRH réussite réussite
3 Sc.Politique DOC Sc.Politique échec échec
4 Sc.Humaines MA1 Sc.humaines réussite réussite
5 Socio.Anthropo BA3 SOCA réussite réussite
6 Sc.Travail MA1 TRAV réussite réussite
7 Sc.Travail MA1 TRAV réussite réussite
Jusqu’ici, on aurait très bien pu se contenter du cut
mais le if_else a l’avantage de pouvoir générer des
conditions plus complexes. En revanche, contrairement à
cut, il ne permet pas de générer plusieurs classes. Comme
nous vous l’indiquions dans l’introduction, chaque méthode présente ses
avantages et ses inconvénients, en fonction du problème. Les arguments
true et false peuvent bien entendu être le
résultat d’une opération, de la même longueur que la
condition: dans ce cas les valeurs correspondants à chaque
position dans la condition sont rendus. Par exemple, si on veut obtenir
les résultats en % de ceux qui ont réussi, et mettre 0 à tous les
autres, on peut procéder comme ceci:
df$statut2 <- if_else(df$resultats_info > 9, df$resultats_info*5, 0)
df
etudiant_ID resultats_info section annee dpmt dpmt2
1 1 15 SHUM BA2 Sc.Sociale sciences sociales
2 2 17 GRH MA1 Sc.Sociale sciences sociales
3 3 9 POLI DOC Sc.Politique sciences politiques
4 4 13 SHUM MA1 Sc.Sociale sciences sociales
5 5 12 SOCA BA3 Sc.Sociale sciences sociales
6 6 10 TRAV MA1 Sc.Sociale sciences sociales
7 7 14 TRAV MA1 Sc.Sociale sciences sociales
section2 annee_ord section_rec statut statut2
1 Sc.Humaines BA2 Sc.humaines réussite 75
2 Gestion des ressources humaines MA1 GRH réussite 85
3 Sc.Politique DOC Sc.Politique échec 0
4 Sc.Humaines MA1 Sc.humaines réussite 65
5 Socio.Anthropo BA3 SOCA réussite 60
6 Sc.Travail MA1 TRAV réussite 50
7 Sc.Travail MA1 TRAV réussite 70
Prenons un exemple sur une base de données plus conséquente, en compliquant un peu la condition. On souhaite créer dans hdv2003, un facteur, qui permet de distinguer les hommes retraités des autres répondants.
levels(hdv2003$sexe)
[1] "Homme" "Femme"
levels(hdv2003$occup)
[1] "Exerce une profession" "Chomeur" "Etudiant, eleve"
[4] "Retraite" "Retire des affaires" "Au foyer"
[7] "Autre inactif"
hdv2003 %>% mutate(homme_retraite = factor(if_else(sexe == "Homme" & occup == "Retraite",
"Homme retraité", "Autre"))) -> hdv2003
table(hdv2003$occup, hdv2003$sexe, hdv2003$homme_retraite, useNA = "ifany")
, , = Autre
Homme Femme
Exerce une profession 520 529
Chomeur 54 80
Etudiant, eleve 48 46
Retraite 0 184
Retire des affaires 39 38
Au foyer 0 171
Autre inactif 30 53
, , = Homme retraité
Homme Femme
Exerce une profession 0 0
Chomeur 0 0
Etudiant, eleve 0 0
Retraite 208 0
Retire des affaires 0 0
Au foyer 0 0
Autre inactif 0 0
case_whencase_whenCette fonction est une généralisation de if_else,
permettant de prendre en compte des fonctions complexes de plusieurs
variables existantes. case_when prends une série de
formules condition ~ valeur, et rends valeur
là où condition est vraie.
Par exemple, on pourrait créer une variable statut de réussite avec des grades. (C’est très nul, mais c’est pour l’exemple.)
df$grade <- factor(case_when(df$resultats_info < 10 ~ "échec",
df$resultats_info >= 10 & df$resultats_info < 14 ~ "Satisfaction",
df$resultats_info >= 14 & df$resultats_info < 16 ~ "Distinction",
df$resultats_info >= 16 & df$resultats_info < 18 ~ "Grande distinction",
df$resultats_info >= 18 ~ "La plus grande distinction"))
df
etudiant_ID resultats_info section annee dpmt dpmt2
1 1 15 SHUM BA2 Sc.Sociale sciences sociales
2 2 17 GRH MA1 Sc.Sociale sciences sociales
3 3 9 POLI DOC Sc.Politique sciences politiques
4 4 13 SHUM MA1 Sc.Sociale sciences sociales
5 5 12 SOCA BA3 Sc.Sociale sciences sociales
6 6 10 TRAV MA1 Sc.Sociale sciences sociales
7 7 14 TRAV MA1 Sc.Sociale sciences sociales
section2 annee_ord section_rec statut statut2
1 Sc.Humaines BA2 Sc.humaines réussite 75
2 Gestion des ressources humaines MA1 GRH réussite 85
3 Sc.Politique DOC Sc.Politique échec 0
4 Sc.Humaines MA1 Sc.humaines réussite 65
5 Socio.Anthropo BA3 SOCA réussite 60
6 Sc.Travail MA1 TRAV réussite 50
7 Sc.Travail MA1 TRAV réussite 70
grade
1 Distinction
2 Grande distinction
3 échec
4 Satisfaction
5 Satisfaction
6 Satisfaction
7 Distinction
Attention: Les éléments ne répondant à aucune condition
deviennent des NA. Vous devez donc être attentif à bien
inclure toutes les possibilités dans vos conditions.
Par exemple:
df$grade <- factor(case_when(df$resultats_info >= 10 & df$resultats_info < 14 ~ "Satisfaction",
df$resultats_info >= 14 & df$resultats_info < 16 ~ "Distinction",
df$resultats_info >= 16 & df$resultats_info < 18 ~ "Grande distinction",
df$resultats_info >= 18 ~ "La plus grande distinction"))
table(df$grade, df$resultats_info, useNA = "ifany")
9 10 12 13 14 15 17
Distinction 0 0 0 0 1 1 0
Grande distinction 0 0 0 0 0 0 1
Satisfaction 0 1 1 1 0 0 0
<NA> 1 0 0 0 0 0 0
# L'étudiant qui a échoué n'est repris dans aucune condition, il reçoit donc un `NA`
Reprenons l’exemple utilisé dans le point précédent pour déterminer les hommes à la retraite. On pourrait très bien envisager une variable qui distingue les hommes retraités, les femmes retraitées et les autres.
levels(hdv2003$sexe)
[1] "Homme" "Femme"
levels(hdv2003$occup)
[1] "Exerce une profession" "Chomeur" "Etudiant, eleve"
[4] "Retraite" "Retire des affaires" "Au foyer"
[7] "Autre inactif"
hdv2003$retraite <- factor(case_when(hdv2003$sexe == "Homme" &
hdv2003$occup == "Retraite" ~ "Homme retraité",
hdv2003$sexe == "Femme" &
hdv2003$occup == "Retraite" ~ "Femme retraitée",
hdv2003$occup != "Retraite" ~ "Autre"))
table(hdv2003$occup, hdv2003$sexe, hdv2003$retraite, useNA = "ifany")
, , = Autre
Homme Femme
Exerce une profession 520 529
Chomeur 54 80
Etudiant, eleve 48 46
Retraite 0 0
Retire des affaires 39 38
Au foyer 0 171
Autre inactif 30 53
, , = Femme retraitée
Homme Femme
Exerce une profession 0 0
Chomeur 0 0
Etudiant, eleve 0 0
Retraite 0 184
Retire des affaires 0 0
Au foyer 0 0
Autre inactif 0 0
, , = Homme retraité
Homme Femme
Exerce une profession 0 0
Chomeur 0 0
Etudiant, eleve 0 0
Retraite 208 0
Retire des affaires 0 0
Au foyer 0 0
Autre inactif 0 0
Attention: Les conditions sont interprétées dans l’ordre: les éléments auxquels s’appliquent la condition sont exclus de l’évaluation des conditions suivantes. Il faut donc les mettre en ordre de généralité croissante, du plus précis, au plus général.
Par exemple, comparez ces deux variantes:
retraite_right <- case_when(hdv2003$sexe == "Femme" &
hdv2003$occup == "Retraite" ~ "Femme retraitée",
# D'abord les "Femme" "Retraite" deviennent "Femme retraitée"
hdv2003$sexe == "Femme" ~ "Autre femme",
# En suite les "Femme" restantes deviennent "Autre femme"
hdv2003$sexe == "Homme" ~ "Autre")
table(hdv2003$occup, hdv2003$sexe, retraite_right, useNA = "ifany")
, , retraite_right = Autre
Homme Femme
Exerce une profession 520 0
Chomeur 54 0
Etudiant, eleve 48 0
Retraite 208 0
Retire des affaires 39 0
Au foyer 0 0
Autre inactif 30 0
, , retraite_right = Autre femme
Homme Femme
Exerce une profession 0 529
Chomeur 0 80
Etudiant, eleve 0 46
Retraite 0 0
Retire des affaires 0 38
Au foyer 0 171
Autre inactif 0 53
, , retraite_right = Femme retraitée
Homme Femme
Exerce une profession 0 0
Chomeur 0 0
Etudiant, eleve 0 0
Retraite 0 184
Retire des affaires 0 0
Au foyer 0 0
Autre inactif 0 0
retraite_wrong <- case_when(hdv2003$sexe == "Femme" ~ "Autre femme",
# Ici TOUTES les "Femme" deviennent "Autre femme"
hdv2003$sexe == "Femme" &
hdv2003$occup == "Retraite" ~ "Femme retraitée",
# Ici il ne reste plus aucun "Femme", donc cette condition n'est jamais vraie
hdv2003$sexe == "Homme" ~ "Autre")
table(hdv2003$occup, hdv2003$sexe, retraite_wrong, useNA = "ifany")
, , retraite_wrong = Autre
Homme Femme
Exerce une profession 520 0
Chomeur 54 0
Etudiant, eleve 48 0
Retraite 208 0
Retire des affaires 39 0
Au foyer 0 0
Autre inactif 30 0
, , retraite_wrong = Autre femme
Homme Femme
Exerce une profession 0 529
Chomeur 0 80
Etudiant, eleve 0 46
Retraite 0 184
Retire des affaires 0 38
Au foyer 0 171
Autre inactif 0 53
table(retraite_right, retraite_wrong, useNA = "ifany")
retraite_wrong
retraite_right Autre Autre femme
Autre 899 0
Autre femme 0 917
Femme retraitée 0 184