Confusion entre les niveaux de facteur et les étiquettes de facteur

106

Il semble y avoir une différence entre les niveaux et les étiquettes d'un facteur dans R. Jusqu'à présent, j'ai toujours pensé que les niveaux étaient le `` vrai '' nom des niveaux de facteur, et les étiquettes étaient les noms utilisés pour la sortie (comme les tableaux et les graphiques) . Ce n'est évidemment pas le cas, comme le montre l'exemple suivant:

df <- data.frame(v=c(1,2,3),f=c('a','b','c'))
str(df)
'data.frame':   3 obs. of  2 variables:
 $ v: num  1 2 3
 $ f: Factor w/ 3 levels "a","b","c": 1 2 3

df$f <- factor(df$f, levels=c('a','b','c'),
  labels=c('Treatment A: XYZ','Treatment B: YZX','Treatment C: ZYX'))
levels(df$f)
[1] "Treatment A: XYZ" "Treatment B: YZX" "Treatment C: ZYX"

Je pensais que les niveaux ('a', 'b', 'c') pouvaient toujours être accessibles lors de la création de scripts, mais cela ne fonctionne pas:

> df$f=='a'
[1] FALSE FALSE FALSE

Mais cela fait:

> df$f=='Treatment A: XYZ' 
[1]  TRUE FALSE FALSE

Donc, ma question se compose de deux parties:

  • Quelle est la différence entre les niveaux et les étiquettes?

  • Est-il possible d'avoir des noms différents pour les niveaux de facteur pour le script et la sortie?

Contexte: pour les scripts plus longs, les scripts avec des niveaux de facteurs courts semblent être beaucoup plus faciles. Cependant, pour les rapports et les graphiques, ces niveaux de facteurs courts peuvent ne pas être adéquats et doivent être remplacés par des noms plus précis.

donodarazao
la source

Réponses:

131

Très court: les niveaux sont l'entrée, les étiquettes sont la sortie dans la factor()fonction. Un facteur n'a qu'un levelattribut, qui est défini par l' labelsargument de la factor()fonction. Ceci est différent du concept d'étiquettes dans des progiciels statistiques comme SPSS, et peut prêter à confusion au début.

Ce que vous faites dans cette ligne de code

df$f <- factor(df$f, levels=c('a','b','c'),
  labels=c('Treatment A: XYZ','Treatment B: YZX','Treatment C: ZYX'))

dit à R qu'il existe un vecteur df$f

  • que vous souhaitez transformer en facteur,
  • dans lequel les différents niveaux sont codés comme a, b et c
  • et pour lequel vous voulez que les niveaux soient étiquetés comme Traitement A, etc.

La fonction factor recherchera les valeurs a, b et c, les convertira en classes de facteurs numériques et ajoutera les valeurs d'étiquette à l' levelattribut du facteur. Cet attribut est utilisé pour convertir les valeurs numériques internes en étiquettes correctes. Mais comme vous le voyez, il n'y a pas d' labelattribut.

> df <- data.frame(v=c(1,2,3),f=c('a','b','c'))    
> attributes(df$f)
$levels
[1] "a" "b" "c"

$class
[1] "factor"

> df$f <- factor(df$f, levels=c('a','b','c'),
+   labels=c('Treatment A: XYZ','Treatment B: YZX','Treatment C: ZYX'))    
> attributes(df$f)
$levels
[1] "Treatment A: XYZ" "Treatment B: YZX" "Treatment C: ZYX"

$class
[1] "factor"
Joris Meys
la source
1
Merci pour la réponse rapide! Je suppose que je comprends maintenant le but des niveaux et des étiquettes. Peut-être des suggestions pour rendre la sortie plus lisible par l'homme sans modifier manuellement les noms de table et les légendes de tracé?
donodarazao
6
Je transformais souvent les niveaux juste avant de tracer / créer des étiquettes, par exemple garder les niveaux comme "a", "b", "c" pendant la manipulation, puis utiliser les niveaux (f) <- paste ("Treatment", toupper (levels ( f)), sep = "") [ou quelque chose] lors du traçage. Ou créez un facteur parallèle f_pretty que vous emportez et n'utilisez que pour la sortie ...
Ben Bolker
J'ai pensé aux deux, mais les deux méthodes ont des inconvénients. Le premier peut devenir fastidieux lors du traçage d'un grand nombre de graphiques, et le second peut devenir fastidieux lorsque beaucoup d'agrégation de données est impliquée dans le script. Mais apparemment, il n'y a aucun moyen d'éviter cela facilement, alors je vais suivre vos suggestions. :)
donodarazao
@ 42- Je ne suis pas sûr de ce que vous entendez par "valeurs numériques". Si vous voulez dire les valeurs internes du facteur, c'est exactement ce que j'ai dit ci-dessus. D'où la mention de valeurs numériques internes . Si vous spécifiez l' levelsargument, vous donnez les valeurs dans l'entrée qui doivent être mises en correspondance avec l' labelsargument. R conserve les étiquettes (comme attribut levels, et il y a confusion) et stocke les codes entiers en interne. Ces codes entiers n'ont rien à voir avec les valeurs d'origine, quel que soit leur type. Je pense que vous m'avez mal compris.
Joris Meys
Toutes mes excuses. Ce que vous écrivez était aussi ma compréhension, et maintenant que je relis votre question, je ne vois pas où je pensais que vous aviez dit différemment. Je supprimerai mon commentaire car il ajoute moins que rien.
IRTFM
17

J'ai écrit un package "lfactors" qui vous permet de faire référence à des niveaux ou à des étiquettes.

# packages
install.packages("lfactors")
require(lfactors)

flips <- lfactor(c(0,1,1,0,0,1), levels=0:1, labels=c("Tails", "Heads"))
# Tails can now be referred to as, "Tails" or 0
# These two lines return the same result
flips == "Tails"
#[1]  TRUE FALSE FALSE  TRUE  TRUE FALSE
flips == 0 
#[1]  TRUE FALSE FALSE  TRUE  TRUE FALSE

Notez qu'un facteur exige que les niveaux soient numériques afin qu'ils ne puissent pas être confondus avec les étiquettes.

PDB
la source
3
c'est un bon paquet et merci de poster à ce sujet (et de l'écrire). Cela semble être le genre de fonctionnalité qui devrait être native des facteurs R - c'est bien de voir un package qui fournit ce type de mappage de paires nom-valeur avec des contrôles d'équivalence intégrés.
Soren