Confusão entre níveis de fator e rótulos de fator


106

Parece haver uma diferença entre os níveis e os rótulos de um fator em R. Até agora, sempre pensei que os níveis eram o nome 'real' dos níveis dos fatores e os rótulos eram os nomes usados ​​para a saída (como tabelas e gráficos) . Obviamente, este não é o caso, como mostra o exemplo a seguir:

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"

Achei que os níveis ('a', 'b', 'c') ainda poderiam ser acessados ​​durante o script, mas isso não funciona:

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

Mas isso faz:

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

Então, minha pergunta consiste em duas partes:

  • Qual é a diferença entre níveis e rótulos?

  • É possível ter nomes diferentes para níveis de fator para script e saída?

Histórico: para scripts mais longos, a criação de scripts com níveis de fator curtos parece ser muito mais fácil. No entanto, para relatórios e gráficos, esses níveis curtos de fator podem não ser adequados e devem ser substituídos por nomes mais precisos.

Respostas:


131

Muito breve: os níveis são a entrada, os rótulos são a saída da factor()função. Um fator possui apenas um levelatributo, que é definido pelo labelsargumento na factor()função. Isso é diferente do conceito de rótulos em pacotes estatísticos como o SPSS e pode ser confuso no início.

O que você faz nesta linha de código

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

está dizendo a R que há um vetor df$f

  • que você deseja transformar em um fator,
  • em que os diferentes níveis são codificados como a, b e c
  • e para os quais você deseja que os níveis sejam rotulados como Tratamento A etc.

A função de fator irá procurar os valores a, bec, convertê-los em classes de fator numéricas e adicionar os valores de rótulo ao levelatributo do fator. Este atributo é usado para converter os valores numéricos internos para os rótulos corretos. Mas, como você vê, não há labelatributo.

> 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"

1
Obrigado pela resposta rápida! Acho que agora entendo o propósito dos níveis e rótulos. Talvez alguma sugestão para tornar a saída humanamente mais legível sem editar manualmente os nomes das tabelas e legendas de plotagem?
— donodarazao

6
Eu costumava transformar os níveis logo antes de plotar / criar rótulos, por exemplo, manter os níveis como "a", "b", "c" enquanto manipulava e, em seguida, usar os níveis (f) <- colar ("Tratamento", toupper (níveis ( f)), sep = "") [ou algo] durante a plotagem. Ou crie um fator paralelo f_pretty que você carrega e usa apenas para a saída ...
— Ben Bolker

Pensei em ambos, mas ambos os métodos têm desvantagens. O primeiro pode ser enfadonho ao plotar um grande número de gráficos e o segundo pode se tornar enfadonho quando uma grande quantidade de agregação de dados está envolvida no script. Mas, aparentemente, não há como evitar isso facilmente, então vou seguir suas sugestões. :)
— donodarazao

@ 42- Não tenho certeza do que você quer dizer com "valores numéricos". Se você se refere aos valores internos do fator, é exatamente o que eu disse acima. Daí a menção de valores numéricos internos . Se você especificar o levelsargumento, fornecerá os valores na entrada que devem corresponder ao labelsargumento. R mantém os rótulos (como o atributo levels, e aí está a confusão) e armazena códigos inteiros internamente. Esses códigos inteiros não têm nada a ver com os valores originais, qualquer que seja o tipo. Eu acho que você me entendeu mal.
— Joris Meys

Desculpas. O que você escreveu foi meu entendimento também, e agora que estou relendo sua pergunta, não consigo ver onde pensei que você disse de outra forma. Vou deletar meu comentário porque adiciona menos do que nada.
— IRTFM

17

Eu escrevi um pacote "lfactors" que permite que você se refira a níveis ou rótulos.

# 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

Observe que um lfactor requer que os níveis sejam numéricos para que não possam ser confundidos com os rótulos.


3
este é um bom pacote e obrigado por postar sobre ele (e por escrever). Parece o tipo de funcionalidade que deveria ser nativa para fatores R - bom ver um pacote que fornece esse tipo de mapeamento de par nome-valor com verificações de equivalência integradas.
— Soren
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.