Como tratar a ordem dos fatores com forcats no R

10 minuto(s) de leitura

Fatores e Níveis

A linguagem R possui várias classes de objetos como dataframes, fatores, listas, matrizes, tibbles e vetores. E para nós que estudamos e usamos o R é indispensável saber para que cada objeto serve e como utilizar da melhor forma possível. Neste post vamos aprender um pouco sobre os fatores e sobre o pacote ideal para usar neste tipo de objeto. No R podemos definir fatores como um conjunto de categorias. Os valores que essas variáveis assumem são os níveis, ou simplesmente as categorias que compõem o fator. Os fatores são criados para representar variáveis categóricas.

Alguns exemplos de variáveis categóricas e seus níveis:

  • Sexo: Masculino e Feminino.
  • Continente: Ásia, África, América do Norte, América do Sul, Antártica, Europa e Oceania.
  • Mês: Janeiro, Fevereiro, Março, Abril, Maio, Junho, etc.

Para criar um fator podemos utlizar a função factor(). Vamos utilizar um vetor sexo que armazena a informação do sexo de 7 indivíduos e depois transformar sexo em um fator.

sexo <- c("Masculino", "Feminino", "Feminino", "Feminino", "Masculino", "Feminino", "Masculino")
sexo
## [1] "Masculino" "Feminino"  "Feminino"  "Feminino"  "Masculino" "Feminino" 
## [7] "Masculino"
fator_sexo <- as.factor(sexo)
fator_sexo
## [1] Masculino Feminino  Feminino  Feminino  Masculino Feminino  Masculino
## Levels: Feminino Masculino

Observe que ao chamar o objeto sexo e o fator_sexo eles se apresentam de maneiras diferentes. Enquanto o vetor sexo contém elementos formados por uma sequência de caracteres entre aspas, o fator_sexo é formado por níveis de um fator, os Levels, e não contém aspas.

forcats

O pacote forcats fornece um conjunto de ferramentas que nos ajudam a trabalhar com variáveis categóricas. Suas principais funções são: fct_recode(), fct_colapse(), fct_reorder(), fct_lump() e lvls_reorder(). Para quem não tem o pacote instalado, basta rodar os códigos a seguir.

install.packages("forcats") ## instalando o pacote forcats
library(forcats)  ## carregando o pacote forcats

Além do forcats vamos precisar do dplyr e do ggplot2.

library(dplyr)  ## carregando o pacote dplyr
library(ggplot2)  ## carregando o pacote ggplot2

Para exemplificar as funções principais, vamos usar um conjunto de dados chamado gss_cat que faz parte do pacote forcats, para usar estes dados basta apenas digitar o nome no console.

head(gss_cat) ## Vizualizando o inicio dos dados
## # A tibble: 6 x 9
##    year marital      age race  rincome    partyid     relig     denom    tvhours
##   <int> <fct>      <int> <fct> <fct>      <fct>       <fct>     <fct>      <int>
## 1  2000 Never mar…    26 White $8000 to … Ind,near r… Protesta… Souther…      12
## 2  2000 Divorced      48 White $8000 to … Not str re… Protesta… Baptist…      NA
## 3  2000 Widowed       67 White Not appli… Independent Protesta… No deno…       2
## 4  2000 Never mar…    39 White Not appli… Ind,near r… Orthodox… Not app…       4
## 5  2000 Divorced      25 White Not appli… Not str de… None      Not app…       1
## 6  2000 Married       25 White $20000 - … Strong dem… Protesta… Souther…      NA

gss_cat é uma amostra de dados do General Social Survey http://gss.norc.org, que é uma pesquisa norte-americana e contém uma série de informações sobre as pessoas participantes, como o estado civil, idade, raça, renda, partido político, religião, denominação religiosa e a quantidade de horas que usam a TV por dia.

fct_recode()

A primeira função que veremos é a fct_recode(). Ela tem como objetivo alterar categorias específicas de um fator. Para exemplificar esta função vamos usar a variável marital de gss_cat, esta variável contem os níveis (No answer, Never married, Separated, Divorced, Widowed, Married) das pessoas que participaram da pesquisa.

head(gss_cat$marital)
## [1] Never married Divorced      Widowed       Never married Divorced     
## [6] Married      
## Levels: No answer Never married Separated Divorced Widowed Married

Os argumentos da função funcionam da seguinte forma:

fct_recode(nome_do_fator,  
          nível_que_queremos = "nível_que_vamos_alterar", 
          nível_que_queremos = "nível_que_vamos_alterar",
          nível_que_queremos = "nível_que_vamos_alterar",
         )

Queremos alterar todos os níveis exceto o No answer.

estado_civil <-  fct_recode(gss_cat$marital,
             Solteiro = "Never married",
             Separado = "Separated",
             Divorciado = "Divorced",
             Viúvo = "Widowed",
             Casado = "Married")

head(estado_civil)
## [1] Solteiro   Divorciado Viúvo      Solteiro   Divorciado Casado    
## Levels: No answer Solteiro Separado Divorciado Viúvo Casado

Os níveis que não são mencionados em fct_recode() permanecem do mesmo jeito que estavam.

fct_collapse()

Outra função importante do forcats é a fct_collapse(). Esta função junta manualmente os níveis em categorias definidas. Usaremos novamente os dados gss_cat e a variável marital. Queremos criar dois grupos de estado civil, solteiro e casado. A fct_collapse() segue a mesma estrutura de argumentos que a fct_recode().

estado_civil2 <- fct_collapse(gss_cat$marital,
                             solteiro = (c("Never married", "Divorced", "Widowed", "Separated")),
                             casado = ("Married"))
head(estado_civil2)
## [1] solteiro solteiro solteiro solteiro solteiro casado  
## Levels: No answer solteiro casado

Como o nível No answer não foi incluído na função, ele não sofreu alteração alguma.

fct_reorder()

A função fct_reorder() tem como principal objetivo reordenar a ordem dos níveis de fator. Vamos supor que queremos saber qual é o número médio de horas por dia que as pessoas passam diante da TV de acordo com cada religião. Para vizualizar esta idéia vamos criar uma tabela com todas as informações necessárias.

relig <- gss_cat %>%
  group_by(relig) %>%
  summarize(
    tvhours = mean(tvhours, na.rm = TRUE),
    n = n()
  )
head(relig)
## # A tibble: 6 x 3
##   relig                   tvhours     n
##   <fct>                     <dbl> <int>
## 1 No answer                  2.72    93
## 2 Don't know                 4.62    15
## 3 Inter-nondenominational    2.87   109
## 4 Native american            3.46    23
## 5 Christian                  2.79   689
## 6 Orthodox-christian         2.42    95

As funções group_by()e summarize() fazem parte do pacote dplyr. Para quem não conhece é só dar uma olhada neste post.

Criamos a variável relig com as informações das religões, das idades e da média de horas gastas por dia diante da TV. Olhando apenas a tabela acima não é possível concluir muita coisa, para uma melhor vizualização vamos criar um gráfico com o ggplot2.

ggplot(relig, aes(tvhours, relig)) + geom_point()

Note que as informações no gráfico ficaram todas espalhadas e desordenadas, para resolver isso vamos usar a função fct_reorder(). Ela pode receber três argumentos:

fct_reorder(f = "argumento 1", x = "argumento 2", fun = "argumento 3")

O primeiro argumento, f, é o fator cujo níveis queremos modificar. O segundo argumento, x, é um vetor numérico que queremos usar para reordenar os níveis. O terceiro argumento, fun, é uma função que é usada se houver múltiplos valores de x para cada valor de f. No nosso exemplo o argumento f é a nossa tabela relig e o nosso argumento x é a variável tvhours.

ggplot(relig, aes(tvhours, fct_reorder(relig, tvhours))) +
  geom_point()

Observando o gráfico ordenado podemos concluir que as pessoas que seguem o Hinduímos e outras religiões orientais passam menos horas em frente a TV do que as pessoas nativo americanas e protestantes.

fct_lump()

Esta função ajuda a agrupar as categorias menores em apenas um grupo denominado other. Para este exemplo vamos utilizar a variável relig novamente.

 gss_cat %>%
  count(relig, sort = TRUE)## Conta a quantidade de observações em cada categoria em ordem decresecente
## # A tibble: 15 x 2
##    relig                       n
##    <fct>                   <int>
##  1 Protestant              10846
##  2 Catholic                 5124
##  3 None                     3523
##  4 Christian                 689
##  5 Jewish                    388
##  6 Other                     224
##  7 Buddhism                  147
##  8 Inter-nondenominational   109
##  9 Moslem/islam              104
## 10 Orthodox-christian         95
## 11 No answer                  93
## 12 Hinduism                   71
## 13 Other eastern              32
## 14 Native american            23
## 15 Don't know                 15

Na variável relig, a religião que possui um maior número de pessoas é a Protestante, ao aplicar a função fct_lump todas as outras religiões menores serão agrupadas em apenas uma.

gss_cat %>%
  mutate(relig = fct_lump(relig)) %>%
  count(relig)
## # A tibble: 2 x 2
##   relig          n
##   <fct>      <int>
## 1 Protestant 10846
## 2 Other      10637

Apesar dos americanos participantes da pesquisa serem em grande número protestantes, nós deixamos outras religiões com quantidades significativas de fora. Para especificar melhor quais as observações queremos agrupar, vamos usar um argumento n dentro da função fct_lump().

gss_cat %>%
  mutate(relig = fct_lump(relig, n = 5)) %>%
  count(relig, sort = TRUE)
## # A tibble: 6 x 2
##   relig          n
##   <fct>      <int>
## 1 Protestant 10846
## 2 Catholic    5124
## 3 None        3523
## 4 Other        913
## 5 Christian    689
## 6 Jewish       388

Usamos o argumento n para especificar quantos grupos queremos manter fora do agrupamento. Assim podemos ver que os católicos, os cristãos e os judeus também estão em número expressivo na pesquisa.

Dentro de fct_lump() temos quatro funções: fct_lump_min(), fct_lump_prop(), fct_lump_n() e fct_lump_lowfreq().

  • fct_lump_min(): agrupa os níveis de fator que aparecem com menor frequência do que uma quantidade determinada de vezes.
  • fct_lump_n(): agrupa todos os níveis, exceto os n níveis mais frequentes.
  • fct_lump_prop(): agrupa os níveis que aparecem em menos proporção.
  • fct_lump_lowfreq(): agrupa os níveis menos frequentes.

Aqui há algumas aplicações destas funções.

lvls_reorder()

Esta função tem como objetivo modificar a ordem dos níveis de um fator. Para exemplificar, vamos utilizar a variável marital.

fator <- head(gss_cat$marital)
fator
## [1] Never married Divorced      Widowed       Never married Divorced     
## [6] Married      
## Levels: No answer Never married Separated Divorced Widowed Married

Note que os níveis estão ordenados assim: No answer, Never married, Separated, Divorced, Widowed, Married.

Para modificar a ordem basta imaginarmos que cada nível tem uma posição, um índice, e o que temos que fazer é reorganizar estas posições. Então ficaria assim:

Os níveis estão ordenados: No answer(1), Never married(2), Separated(3), Divorced(4), Widowed(5), Married(6).

Queremos que seja: Divorced(4), Married(6), Never married(2), No answer(1), Separated(3), Widowed(5).

lvls_reorder(fator, c(4, 6, 2, 1, 3, 5))
## [1] Never married Divorced      Widowed       Never married Divorced     
## [6] Married      
## Levels: Divorced Married Never married No answer Separated Widowed

Além destas funções apresentadas até agora, o forcats possui outras funções bastante úteis. Para exemplificar algumas vamos criar um fator com letras e fazer alguns testes.

fator <- factor(c("b", "b", "d", "c", "a", "d", "d", "d", "c"))
fator
## [1] b b d c a d d d c
## Levels: a b c d

A primeira função é a fct_relevel(), com ela é possível ordenar os níveis manualmente. Observe que os níveis sempre são ordenados automaticamente em ordem alfabética, para controlar isso é só escrever a ordem desejada no segundo argumento da função.

fct_relevel(fator, c("d", "a", "c", "b"))
## [1] b b d c a d d d c
## Levels: d a c b

Esta função é similiar a lvls_reorder(), a diferença é que a fct_relevel()considera os níveis de fator para reordenar enquanto na lvls_reorder() utilizamos os índices (1, 2,…) dos níveis.

Uma outra função que vale a pena ser comentada é a fct_infreq(). Ela tem como objetivo organizar os níveis de um fator por sua frequência.

fct_infreq(fator)
## [1] b b d c a d d d c
## Levels: d b c a

Note que agora as ordens dos níveis são: d, b, c, a. A mudança foi feita pois no nosso fator ‘fator’ há quatro vezes a letra ‘d’, duas vezes a letra ‘b’, duas vezes a letra ‘c’ e apenas uma vez a letra ‘a’.

Falando ainda em frequências, temos a função fct_count(), ela cria uma tabela de frequências dos níveis de um fator.

fct_count(fator)
## # A tibble: 4 x 2
##   f         n
##   <fct> <int>
## 1 a         1
## 2 b         2
## 3 c         2
## 4 d         4

Neste exemplo, a letra ‘f’ representa os níveis (a, b, c, d), e a letra ‘n’ representa a frequência em que cada nível aparece no fator.

Outra função interessante é a fct_unique(), ela remove os níveis duplicados em um fator para que haja apenas um valor de cada nível.

fct_unique(fator)
## [1] a b c d
## Levels: a b c d

Repare que o R só printou um único valor de cada nível.

Agora vamos ver um exemplo da função fct_c(), ela combina dois fatores. Ja temos o fator ‘fator’, agora vamos criar o ‘fator2’.

fator2 <- factor(c("g", "h"))
fct_c(fator, fator2)
##  [1] b b d c a d d d c g h
## Levels: a b c d g h

Veja que a função fct_c() juntou os dois fatores e deu origem ao novo fator com os níveis: a, b, c, d, g, h.

Estas foram algumas das funções que o forcats tem a nos oferecer. Se fosse possível acrescentaríamos muitas outras funções deste pacote, porém o post tem que acabar. Para saber mais sobre o assunto recomendo uma leitura nos links abaixo.

Referências

https://forcats.tidyverse.org/

https://r4ds.had.co.nz/factors.html.

Atualizado em: