Menu

Fatores no R: Dados Categóricos, Níveis e Armadilhas Comuns

Fatores são como o R armazena dados categóricos: códigos inteiros vestindo rótulos de texto. Como criá-los, ordená-los, definir o nível de referência - e escapar da armadilha de fator para numérico.

Esta página tem editores executáveis - edite, execute e veja a saída na hora.

O Que um Fator Realmente É

Um fator é a resposta do R para dados categóricos - valores que vêm de um cardápio fixo de possibilidades: grupos de tratamento, respostas de pesquisa, tamanhos de camiseta. Parece um vetor de caracteres quando impresso, mas não é um. Internamente, um fator é um vetor de códigos inteiros mais uma tabela de consulta de rótulos chamados de níveis:

A impressão mostra os rótulos e depois uma linha Levels: listando o cardápio. as.integer() expõe a engrenagem: os códigos voltam como 3 1 3 2, porque cada valor é na verdade um índice na tabela de níveis - e os níveis são ordenados alfabeticamente por padrão (large, medium, small), não na ordem em que os dados chegaram. Então small é o código 3 e large é o código 1, o que não é a intuição de ninguém. Lembre-se desse padrão alfabético; ele causa duas das armadilhas abaixo.

Por que se dar ao trabalho desse design em duas camadas em vez de strings simples? Porque a estatística precisa dele. Um modelo não consegue multiplicar "small" por um coeficiente - mas consegue codificar três níveis conhecidos em colunas de 0s e 1s. Funções como lm(), glm(), table() e a maquinaria por trás da ANOVA usam fatores para saber que uma variável é categórica, qual é o conjunto completo de categorias (incluindo as ausentes dos dados) e qual categoria é a linha de base. Vetores de caracteres simples não carregam nada disso.

Criando Fatores: levels, labels e table()

Por padrão, factor() pega os valores distintos que encontra e os ordena alfabeticamente em níveis. Muitas vezes você vai querer controle tanto sobre o conjunto quanto sobre a ordem - passe levels =:

Agora os níveis seguem sua ordem natural de tamanho, e table() - a contagem de frequências de uma linha que você vai usar o tempo todo com fatores - reporta as contagens nessa ordem também. nlevels() conta as categorias.

Mais duas coisas que levels = te dá. Valores nos dados que não estão na sua lista de níveis viram NA (o que é bom: erros de digitação aparecem em vez de virarem sua própria categoria). E níveis com zero ocorrências continuam existindo, então um resumo de respostas de pesquisa mostra "discordo totalmente: 0" em vez de fingir que a opção nunca existiu.

labels = renomeia os níveis no momento da criação, o que é prático quando os dados brutos usam códigos:

E as.factor(x) é o conversor rápido para um vetor existente quando os padrões servem.

Fatores Ordenados para Dados Ordinais

Fatores comuns tratam categorias como não ordenadas - "red" não é menor que "blue". Mas algumas escalas categóricas têm uma hierarquia genuína: baixo/médio/alto, discordo/neutro/concordo. Declare isso com ordered = TRUE:

A impressão agora mostra Levels: low < medium < high, e os operadores de comparação funcionam: você pode perguntar se uma avaliação supera outra, ou filtrar tudo igual ou acima de "medium" - ambos dariam erro (bem, avisos e NAs) em um fator não ordenado. Fatores ordenados também mudam como os modelos codificam a variável (contrastes polinomiais em vez de variáveis dummy), o que normalmente é o que você quer para preditores ordinais.

Use ordered = TRUE apenas quando a hierarquia é real. Codificar grupos comuns como ordenados muda a saída do modelo de formas fáceis de interpretar errado.

O Nível de Referência e relevel()

O primeiro nível de um fator é especial: funções de modelo o tratam como a categoria de referência, a linha de base contra a qual o coeficiente de todo outro nível é medido. Como a ordem padrão dos níveis é alfabética, sua linha de base é escolhida pelo alfabeto a menos que você intervenha - e "control" perder para "aspirin" no alfabeto não é uma decisão científica.

relevel() promove um nível ao primeiro lugar:

Antes: control acaba sendo o primeiro apenas por sorte alfabética. Depois de relevel(..., ref = "control") ele é o primeiro de propósito. Em uma regressão linear com esse preditor, o coeficiente de treatment agora responde "como o tratamento difere do controle?" - a pergunta que você de fato fez. Sempre que os coeficientes categóricos de um modelo parecerem confusos, cheque primeiro o nível de referência.

(Para reordenar tudo - não apenas o primeiro lugar - passe de novo um vetor levels = completo para factor().)

A Armadilha Clássica: Converter um Fator em Numérico

Às vezes números chegam como fatores - normalmente uma coluna de CSV que continha um valor não numérico perdido. Converter de volta parece óbvio e dá memoravelmente errado:

as.numeric(f) retorna 2 1 3. Não 20, 10, 30 - os códigos de nível. Os níveis ordenam alfabeticamente para "10", "20", "30", então "20" é o nível 2 e converte para... 2. Sem erro, sem aviso, pequenos inteiros de aparência plausível substituindo silenciosamente seus dados. Análises já foram retratadas por causa disso.

O caminho correto passa por caractere: as.numeric(as.character(f)) primeiro recupera os rótulos como texto, depois interpreta o texto como números - 20 10 30. Grave esse idioma: de fator para numérico sempre passa por as.character().

droplevels() e a História do stringsAsFactors

Fazer subconjunto de um fator mantém o conjunto completo de níveis, mesmo para categorias que não aparecem mais:

Depois de filtrar large, table() ainda o reporta - com contagem 0. Às vezes isso é exatamente o certo (você quer a categoria vazia visível). Quando não é - grupos com contagem zero poluem gráficos e podem quebrar análises estratificadas - droplevels() descarta os níveis sem observações.

Uma nota histórica de que você vai precisar ao ler código antigo ou respostas do Stack Overflow: antes do R 4.0 (2020), data.frame() e read.csv() convertiam toda coluna de caracteres em fator automaticamente - stringsAsFactors = TRUE era o padrão. Uma década de tutoriais está repleta de contornos para fatores que ninguém pediu. Desde o R 4.0 o padrão é FALSE: strings continuam strings, e você cria fatores deliberadamente, onde uma variável do seu data frame é genuinamente categórica. Esse é o hábito certo - fatores explícitos, de propósito, com níveis que você escolheu.

O Que Você Leva Daqui

  • Um fator = códigos inteiros + rótulos de nível; é o que diz às funções estatísticas que uma variável é categórica.
  • Controle o conjunto e a ordem das categorias com levels =, renomeie com labels =, conte com table().
  • ordered = TRUE habilita comparações para escalas genuinamente ordinais.
  • O primeiro nível é a linha de base do modelo - defina-o deliberadamente com relevel(f, ref = ...).
  • Nunca use as.numeric(f) diretamente - sempre as.numeric(as.character(f)).
  • droplevels() limpa níveis não usados depois de um subconjunto; desde o R 4.0, strings continuam strings a menos que você mesmo crie fatores.

A seguir: data frames - onde fatores, números e texto convivem como colunas de uma mesma tabela.

Perguntas frequentes

O que é um fator no R?

Um fator é o tipo do R para dados categóricos - valores extraídos de um conjunto fixo de possibilidades chamado de níveis (levels). Internamente é um vetor de códigos inteiros mais uma tabela de rótulos de nível, e é isso que permite às funções estatísticas tratarem categorias corretamente (contando-as, codificando-as como variáveis dummy em modelos) em vez de tratá-las como texto livre.

Como converter um fator em numérico no R?

Passe por caractere: as.numeric(as.character(f)). Chamar as.numeric(f) diretamente retorna os códigos internos de nível (1, 2, 3, ...), não os valores que os rótulos mostram - então um fator exibindo "20" pode voltar como 2. Esse é um dos bugs silenciosos mais comuns do R.

O que a função relevel() faz no R?

Ela move um nível escolhido para a primeira posição: relevel(group, ref = "control"). O primeiro nível é a categoria de referência (linha de base) contra a qual funções de modelo como lm() e glm() comparam todos os outros níveis, então escolhê-lo deliberadamente faz os coeficientes da regressão significarem o que você pretende.

Por que meu fator ainda mostra níveis que eu removi?

Fazer um subconjunto de um fator mantém o conjunto completo de níveis mesmo quando alguns não ocorrem mais, então table() mostra categorias com contagem zero e os modelos ainda reservam espaço para elas. Rode droplevels() no subconjunto para descartar os níveis não usados.

Coddy programming languages illustration

Aprenda a programar com o Coddy

COMEÇAR