4  Facteurs

En R, un facteur (factor, en anglais) ou variable factorielle est un vecteur dont les éléments ne peuvent prendre que des modalités prédéfinies. Ce qui caractérise un facteur en R est le fait qu’elle dispose de l’attribut Levels (niveaux, modalités ou valeurs possibles). En pratique, un facteur est typiquement utilisé pour stocker les valeurs observées d’une variable catégorielle, càd une variable avec un nombre fixé et limité de valeurs possibles (couleur, sexe, jours de la semaine, religion, …).

4.1 Créer un facteur avec factor()

La création d’un facteur se fait à l’aide de la fonction factor(). En général, on part d’un vecteur (numérique ou de chaînes de caractères), que l’on convertit par la suite en facteur.

fh <- c("H", "F", "F", "F", "F", "H", "F", "H", "H", "F", "F", "F")
sexe <- factor(fh)
sexe
 [1] H F F F F H F H H F F F
Levels: F H

Notez qu’en affichant un facteur, R montre d’abord les valeurs du vecteur, suivies des niveaux (Levels) reconnus, qui correspondent aux différentes catégories identifiées.

Un facteur en R enregistre automatiquement non seulement les valeurs observées d’une variable, mais aussi l’ensemble de ses modalités (niveaux). Par défaut, ces derniers sont déterminés automatiquement à partir des valeurs uniques présentes dans le vecteur initial. Par exemple, dans le facteur sexe défini ci-dessus, les seules modalités autorisées sont “H” et “F”. Ainsi, si l’on tente d’y insérer une valeur qui ne fait pas partie de ces niveaux — comme “Homme” — R génère un Warning et remplace la valeur par NA (valeur manquante) :

sexe[13] <- "Homme"
Warning in `[<-.factor`(`*tmp*`, 13, value = "Homme"): invalid factor level, NA
generated
sexe
 [1] H    F    F    F    F    H    F    H    H    F    F    F    <NA>
Levels: F H

Cela est normal, puisque “Homme” ne fait pas partie de la liste des valeurs possibles de l’objet sexe tel que défini. Pour éviter ce type de problème, il est possible — et souvent recommandé — de définir explicitement les niveaux d’un facteur dès sa création. Nous verrons comment procéder un peu plus loin.

Avant cela, il est important de souligner que de nombreuses fonctions en R traitent les facteurs de manière spécifique. C’est pourquoi il est essentiel de bien déclarer une variable comme facteur lorsque celle-ci représente une donnée catégorielle, afin qu’elle soit correctement interprétée par R. Voici un exemple qui illustre ce comportement particulier.

plot(fh)
Error in plot.window(...) : ....
plot(sexe)

Notez également qu’en interne, R encode les valeurs d’un facteur sous forme d’entiers : 1 pour le premier niveau, 2 pour le deuxième, et ainsi de suite. Cette représentation numérique permet à R de traiter efficacement les variables catégorielles dans les analyses statistiques et les modèles. Pour voir cela, examinons la structure de l’objet sexe.

typeof(sexe)
str(sexe)
[1] "integer"
 Factor w/ 2 levels "F","H": 2 1 1 1 1 2 1 2 2 1 ...

Cette sortie indique que sexe est bel et bien un facteur avec deux modalités “F” et “H”, encodées comme 1 et 2, respectivement. Les premiers éléments de sexe sont : 2 1 1 …, càd “H” “F” “F” ….

4.2 L’argument levels de factor()

On a vu que les niveaux d’un facteur sont déterminés automatiquement à partir des valeurs uniques du vecteur utilisé pour le créer. De plus, ces niveaux sont affichés selon l’ordre alphanumérique croissant. Par exemple, dans les sorties précédentes, on remarque que “F” apparaît toujours avant “H”, ce qui reflète cet ordre par défaut.

L’argument optionnel levels de la fonction factor() permet de préciser explicitement les modalités possibles d’un facteur, ainsi que l’ordre dans lequel ces niveaux seront affichés.

sexe <- fh |> factor(levels = c("H", "F"))
sexe
 [1] H F F F F H F H H F F F
Levels: H F
plot(sexe)

Pour mieux comprendre l’importance de l’argument levels, imaginons que l’on souhaite analyser les résultats d’une expérience simple : lancer un dé à six faces dix fois, et enregistrer les valeurs obtenues. Pour cela, on stocke les résultats dans un vecteur, puis on les convertit en facteur afin de les traiter comme une variable catégorique.

de <- c(3, 2, 2, 1, 3, 1, 3, 1, 6, 6) |> factor(levels = 1:6)
de
 [1] 3 2 2 1 3 1 3 1 6 6
Levels: 1 2 3 4 5 6

En utilisant l’argument levels = 1:6, on indique explicitement que le facteur de peut prendre toutes les valeurs de 1 à 6, même si certaines (comme 4 et 5) ne sont pas présentes dans notre échantillon. Cette précision est utile, par exemple, lorsqu’on veut afficher ou analyser la fréquence de chaque face du dé.

table(de)
de
1 2 3 4 5 6 
3 2 3 0 0 2 

Grâce à l’argument levels, le code suivant ne génère aucun Warning lorsque l’on ajoute, par exemple, la valeur 5 :

de[11] <- 5
de
 [1] 3 2 2 1 3 1 3 1 6 6 5
Levels: 1 2 3 4 5 6

Cela fonctionne car 5 fait partie des niveaux explicitement définis lors de la création du facteur (levels = 1:6).

4.3 Manipuler un facteur avec levels()

Une fois le facteur créé, la fonction levels() permet d’accéder ou de modifier les niveaux d’un facteur existant, comme illustré dans les exemples suivants.

Afficher les niveaux

levels(sexe)
levels(de)
[1] "H" "F"
[1] "1" "2" "3" "4" "5" "6"

Modifier un ou plusieurs niveau(x)

levels(sexe)[1] <- "male"
sexe
 [1] male F    F    F    F    male F    male male F    F    F   
Levels: male F
levels(de)[c(2, 5)] <- c("Face2", "Face5")
de
 [1] 3     Face2 Face2 1     3     1     3     1     6     6     Face5
Levels: 1 Face2 3 4 Face5 6

Il est aussi possible de changer tous les niveaux d’un facteur en une seule commande simple :

levels(sexe) <- c("Homme", "Femme")
sexe
 [1] Homme Femme Femme Femme Femme Homme Femme Homme Homme Femme Femme Femme
Levels: Homme Femme

Attention à bien respecter l’ordre des niveaux lors de leur modification. Par exemple, écrire levels(sexe) <- c("Femme", "Homme") au lieu de levels(sexe) <- c("Homme", "Femme") inverse les libellés. Pour réduire le risque d’erreur lors de la modification des niveaux, on peut utiliser une liste nommée qui associe explicitement chaque nouveau niveau à l’ancien niveau. Cela rend le code plus lisible et plus robuste :

levels(sexe) <- list("Fille" = "Femme", "Garçon" = "Homme")
sexe
 [1] Garçon Fille  Fille  Fille  Fille  Garçon Fille  Garçon Garçon Fille 
[11] Fille  Fille 
Levels: Fille Garçon

Ajouter des niveaux à un facteur existant

levels(sexe) <- c(levels(sexe), "Male", "Femelle", "Fille", "Garçon", "H", "F")
sexe
 [1] Garçon Fille  Fille  Fille  Fille  Garçon Fille  Garçon Garçon Fille 
[11] Fille  Fille 
Levels: Fille Garçon Male Femelle H F

Supprimer/regrouper des niveaux

levels(sexe) <- list("Homme" = c("Homme", "Male", "Garçon", "H"), "Femme" = c("Femme", "Femelle", "Fille", "F"))
sexe
 [1] Homme Femme Femme Femme Femme Homme Femme Homme Homme Femme Femme Femme
Levels: Homme Femme

Transformer une variable numérique en facteur

La fonction cut() permet de transformer une variable numérique en facteur en la découpant en intervalles. Elle est particulièrement utile pour créer des classes à partir de données continues. Exemple :

age <- c(23, 35, 42, 20, 51, 67, 45, 60, 18, 15, 38, 30, 85)

ageC <- cut(age,
1  breaks = c(17, 30, 59, Inf),
2  labels = c("Jeune Adulte", "Adulte", "Senior")
)
ageC
1
Définir les intervalles. Par défaut, ceux‑ci sont ouverts à gauche et fermés à droite, ce qui donne : (17, 30], (30, 59], (59, Inf]. L’argument right = FALSE inverse cette convention.
2
Associer une étiquette à chaque tranche pour obtenir un facteur lisible et interprétable.
 [1] Jeune Adulte Adulte       Adulte       Jeune Adulte Adulte      
 [6] Senior       Adulte       Senior       Jeune Adulte <NA>        
[11] Adulte       Jeune Adulte Senior      
Levels: Jeune Adulte Adulte Senior