Menu

Les facteurs en R : données catégorielles, niveaux et pièges courants

Les facteurs sont la façon dont R stocke les données catégorielles : des codes entiers habillés d'étiquettes texte. Comment les créer, les ordonner, définir le niveau de référence - et éviter le piège facteur vers numérique.

Cette page contient des éditeurs exécutables - modifiez, exécutez et voyez la sortie instantanément.

Ce qu'est réellement un facteur

Un facteur est la réponse de R aux données catégorielles - des valeurs issues d'un menu fixe de possibilités : groupes de traitement, réponses d'enquête, tailles de t-shirts. Ça ressemble à un vecteur de caractères à l'affichage, mais ça n'en est pas un. En interne, un facteur est un vecteur de codes entiers plus une table de correspondance d'étiquettes appelées niveaux :

L'affichage montre les étiquettes, puis une ligne Levels: listant le menu. as.integer() expose la mécanique : les codes reviennent comme 3 1 3 2, parce que chaque valeur est en réalité un indice dans la table des niveaux - et les niveaux sont triés alphabétiquement par défaut (large, medium, small), pas dans l'ordre d'arrivée des données. Donc small est le code 3 et large le code 1, ce qui n'est l'intuition de personne. Retiens ce tri alphabétique par défaut ; il est à l'origine de deux des pièges ci-dessous.

Pourquoi s'embêter avec cette conception à deux couches plutôt que de simples chaînes ? Parce que la statistique en a besoin. Un modèle ne peut pas multiplier « small » par un coefficient - mais il peut coder trois niveaux connus en colonnes de 0 et de 1. Des fonctions comme lm(), glm(), table() et la mécanique derrière l'ANOVA s'appuient toutes sur les facteurs pour savoir qu'une variable est catégorielle, quel est l'ensemble complet des catégories (y compris celles absentes des données), et quelle catégorie sert de base. Les simples vecteurs de caractères ne portent rien de tout ça.

Créer des facteurs : levels, labels et table()

Par défaut, factor() prend les valeurs distinctes qu'il trouve et les trie alphabétiquement en niveaux. Tu voudras souvent contrôler à la fois l'ensemble et l'ordre - passe levels = :

Maintenant les niveaux vont dans leur ordre naturel de taille, et table() - le comptage de fréquences en une ligne que tu utiliseras constamment avec les facteurs - rapporte aussi les effectifs dans cet ordre. nlevels() compte les catégories.

levels = t'apporte deux choses de plus. Les valeurs des données qui ne figurent pas dans ta liste de niveaux deviennent NA (bien : les fautes de frappe apparaissent au lieu de devenir leur propre catégorie). Et les niveaux à zéro occurrence existent quand même, donc un résumé de réponses d'enquête affiche « pas du tout d'accord : 0 » au lieu de faire comme si l'option n'avait jamais existé.

labels = renomme les niveaux à la création, ce qui est pratique quand les données brutes utilisent des codes :

Et as.factor(x) est le convertisseur rapide pour un vecteur existant quand les valeurs par défaut conviennent.

Facteurs ordonnés pour données ordinales

Les facteurs simples traitent les catégories comme non ordonnées - « rouge » n'est pas inférieur à « bleu ». Mais certaines échelles catégorielles ont un vrai classement : faible/moyen/élevé, pas d'accord/neutre/d'accord. Déclare-le avec ordered = TRUE :

L'affichage montre maintenant Levels: low < medium < high, et les opérateurs de comparaison fonctionnent : tu peux demander si une note dépasse une autre, ou filtrer tout ce qui est supérieur ou égal à « medium » - deux erreurs (enfin, des avertissements et des NA) sur un facteur non ordonné. Les facteurs ordonnés changent aussi la façon dont les modèles codent la variable (contrastes polynomiaux au lieu de variables indicatrices), ce qui est généralement ce que tu veux pour des prédicteurs ordinaux.

N'utilise ordered = TRUE que quand le classement est réel. Coder des groupes ordinaires comme ordonnés modifie la sortie des modèles d'une manière facile à mal interpréter.

Le niveau de référence et relevel()

Le premier niveau d'un facteur est spécial : les fonctions de modélisation le traitent comme la catégorie de référence, la base à laquelle est mesuré le coefficient de chaque autre niveau. Comme l'ordre par défaut des niveaux est alphabétique, ta base est choisie par l'alphabet à moins que tu n'interviennes - et « control » perdant face à « aspirin » alphabétiquement n'est pas une décision scientifique.

relevel() promeut un niveau à la première place :

Avant : control n'est premier que par chance alphabétique. Après relevel(..., ref = "control"), il est premier volontairement. Dans une régression linéaire avec ce prédicteur, le coefficient treatment répond maintenant à « en quoi le traitement diffère-t-il du contrôle ? » - la question que tu as réellement posée. Chaque fois que les coefficients catégoriels d'un modèle semblent déroutants, vérifie d'abord le niveau de référence.

(Pour un réordonnancement complet - pas seulement la première place - repasse un vecteur levels = complet à factor().)

Le piège classique : convertir un facteur en numérique

Parfois des nombres arrivent sous forme de facteurs - typiquement une colonne CSV qui contenait une valeur non numérique égarée. Reconvertir semble évident et se passe très mal, de façon mémorable :

as.numeric(f) renvoie 2 1 3. Pas 20, 10, 30 - les codes de niveaux. Les niveaux se trient alphabétiquement en "10", "20", "30", donc "20" est le niveau 2 et se convertit en... 2. Pas d'erreur, pas d'avertissement, de petits entiers d'allure plausible remplaçant discrètement tes données. Des analyses ont été rétractées à cause de ça.

La bonne route passe par le texte : as.numeric(as.character(f)) récupère d'abord les étiquettes sous forme de texte, puis analyse le texte comme des nombres - 20 10 30. Grave cet idiome : facteur vers numérique passe toujours par as.character().

droplevels() et l'histoire de stringsAsFactors

Extraire un sous-ensemble d'un facteur conserve l'ensemble complet des niveaux, même pour des catégories qui n'apparaissent plus :

Après avoir filtré large, table() le rapporte encore - avec un effectif de 0. Parfois c'est exactement ce qu'il faut (tu veux la catégorie vide visible). Quand ce n'est pas le cas - les groupes à effectif nul encombrent les graphiques et peuvent casser les analyses stratifiées - droplevels() élimine les niveaux sans observations.

Une note historique dont tu auras besoin en lisant du code plus ancien ou des réponses Stack Overflow : avant R 4.0 (2020), data.frame() et read.csv() convertissaient automatiquement chaque colonne texte en facteur - stringsAsFactors = TRUE était la valeur par défaut. Une décennie de tutoriels est truffée de contournements pour des facteurs que personne n'avait demandés. Depuis R 4.0, la valeur par défaut est FALSE : les chaînes restent des chaînes, et tu crées des facteurs délibérément, là où une variable de ton data frame est réellement catégorielle. C'est la bonne habitude - des facteurs explicites, voulus, avec les niveaux que tu as choisis.

Ce que tu retiens

  • Un facteur = codes entiers + étiquettes de niveaux ; c'est ce qui indique aux fonctions statistiques qu'une variable est catégorielle.
  • Contrôle l'ensemble et l'ordre des catégories avec levels =, renomme avec labels =, compte avec table().
  • ordered = TRUE active les comparaisons pour des échelles réellement ordinales.
  • Le premier niveau est la base du modèle - définis-le délibérément avec relevel(f, ref = ...).
  • Ne fais jamais as.numeric(f) directement - toujours as.numeric(as.character(f)).
  • droplevels() efface les niveaux inutilisés après un filtrage ; depuis R 4.0, les chaînes restent des chaînes sauf si tu crées les facteurs toi-même.

Prochaine étape : les data frames - là où facteurs, nombres et texte cohabitent en colonnes d'un même tableau.

Questions fréquentes

Qu'est-ce qu'un facteur en R ?

Un facteur est le type de R pour les données catégorielles - des valeurs issues d'un ensemble fixe de possibilités appelées niveaux. En interne, c'est un vecteur de codes entiers plus une table d'étiquettes de niveaux, ce qui permet aux fonctions statistiques de traiter correctement les catégories (les compter, les coder en variables indicatrices dans les modèles) au lieu de les traiter comme du texte libre.

Comment convertir un facteur en numérique en R ?

Passe par le texte : as.numeric(as.character(f)). Appeler as.numeric(f) directement renvoie les codes internes des niveaux (1, 2, 3, ...), pas les valeurs que montrent les étiquettes - donc un facteur affichant « 20 » peut revenir comme 2. C'est l'un des bugs silencieux les plus fréquents en R.

Que fait relevel() en R ?

Il déplace un niveau choisi en première position : relevel(group, ref = "control"). Le premier niveau est la catégorie de référence (la base) à laquelle les fonctions de modélisation comme lm() et glm() comparent tous les autres niveaux, donc le choisir délibérément fait dire aux coefficients de régression ce que tu veux dire.

Pourquoi mon facteur affiche-t-il encore des niveaux que j'ai retirés ?

Extraire un sous-ensemble d'un facteur conserve l'ensemble complet des niveaux même quand certains n'apparaissent plus, donc table() montre des catégories à zéro et les modèles leur réservent encore de la place. Lance droplevels() sur le sous-ensemble pour éliminer les niveaux inutilisés.

Coddy programming languages illustration

Apprendre à coder avec Coddy

COMMENCER