Pacote Forcats

É muito frustrante quando uma coluna de strings é lida como um fator, pois fatores não podem ser manipulados do mesmo jeito que manipulamos vetores de strings.

Muitos dos problemas associados ao uso de fatores no R existe por conta da falta de algumas ferramentas úteis no pacote base. Para resolver esse o problema, Hadley Wickham desenvolveu o pacote forcats (for categorial variables), que implementa algumas dessas ferramentas.

As principais funções do forcats servem para alterar a ordem e modificar os níveis de um fator.

Pacote forcats.

Pacote forcats.

Um fator é definido como um vetor de integers com dois atributos específicos:

Fatores são úteis porque facilitam a ordenação de vetores de texto, principalmente quando estamos fazendo gráficos.

O forcats é um pacote bastante simples. Este pacote não faz parte do tidyverse. Ele é composto por funções de apenas dois tipos:

Criando fatores

x1<-c("Fev","Mar","Abr","Jan", "Jul", "Jun")
is.factor(x1)
## [1] FALSE
sort(x1)
## [1] "Abr" "Fev" "Jan" "Jul" "Jun" "Mar"
x2<-c("Mar","ABr","Jam","Jun","Jul")
meses<-c("Jan","Fev","Mar","Abr","Mai","Jun","Jul","Ago","Set","Out","Nov","Dez")

y1<-factor(x1,levels = meses)
is.factor(y1)
## [1] TRUE
sort(y1)
## [1] Jan Fev Mar Abr Jun Jul
## Levels: Jan Fev Mar Abr Mai Jun Jul Ago Set Out Nov Dez
y2<-factor(x2)
is.factor(y2)
## [1] TRUE
sort(y2)
## [1] ABr Jam Jul Jun Mar
## Levels: ABr Jam Jul Jun Mar
y3<-factor(x2, levels = meses)
y3
## [1] Mar  <NA> <NA> Jun  Jul 
## Levels: Jan Fev Mar Abr Mai Jun Jul Ago Set Out Nov Dez
sort(y3)
## [1] Mar Jun Jul
## Levels: Jan Fev Mar Abr Mai Jun Jul Ago Set Out Nov Dez
y4<-readr::parse_factor(x2,levels = meses)
## Warning: 2 parsing failures.
## row col           expected actual
##   2  -- value in level set    ABr
##   3  -- value in level set    Jam

Podemos preferir que a ordem dos níveis combine com a ordem da primeira aparição nos dados.

f1<-factor(x1,levels = unique(x1))
f1
## [1] Fev Mar Abr Jan Jul Jun
## Levels: Fev Mar Abr Jan Jul Jun
# ou da forma

library(tidyverse)
## -- Attaching packages -------------------------------------------------- tidyverse 1.2.1 --
## v ggplot2 3.2.0     v purrr   0.3.2
## v tibble  2.1.3     v dplyr   0.8.3
## v tidyr   0.8.3     v stringr 1.4.0
## v readr   1.3.1     v forcats 0.4.0
## -- Conflicts ----------------------------------------------------- tidyverse_conflicts() --
## x dplyr::filter() masks stats::filter()
## x dplyr::lag()    masks stats::lag()
library(forcats)

f2<- x1 %>% factor() %>% fct_inorder()
f2
## [1] Fev Mar Abr Jan Jul Jun
## Levels: Fev Mar Abr Jan Jul Jun
levels(f2)
## [1] "Fev" "Mar" "Abr" "Jan" "Jul" "Jun"

Vamos ver agora o exemplo de um conjunto de dados do General Social Survey (https://gss.norc.org/Get-The-Data) que é uma pesquisa norte amearicana de longa duração conduzida pela organização independente de pesquisas NORC da Universidade de Chicago.

glimpse(gss_cat)
## Observations: 21,483
## Variables: 9
## $ year    <int> 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, ...
## $ marital <fct> Never married, Divorced, Widowed, Never married, Divor...
## $ age     <int> 26, 48, 67, 39, 25, 25, 36, 44, 44, 47, 53, 52, 52, 51...
## $ race    <fct> White, White, White, White, White, White, White, White...
## $ rincome <fct> $8000 to 9999, $8000 to 9999, Not applicable, Not appl...
## $ partyid <fct> "Ind,near rep", "Not str republican", "Independent", "...
## $ relig   <fct> Protestant, Protestant, Protestant, Orthodox-christian...
## $ denom   <fct> Southern baptist, Baptist-dk which, No denomination, N...
## $ tvhours <int> 12, NA, 2, 4, 1, NA, 3, NA, 0, 3, 2, NA, 1, NA, 1, 7, ...
# ?gss_cat

gss_cat %>% count(race)
ggplot(gss_cat, aes(race)) + geom_bar() + scale_x_discrete(drop=FALSE)

Modificando a ordem dos fatores

relig<- gss_cat %>% group_by(relig) %>% 
  summarise(mean(age,na.rm =TRUE),
            tvhours = mean(tvhours, na.rm = TRUE),
            n = n())

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

# Podemos melhorar este gráfico reordenando os níveis relig usando fct_reorder()

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

rincome <- gss_cat %>% 
  group_by(rincome) %>% 
  summarise(mean(age,na.rm =TRUE),
            tvhours = mean(tvhours, na.rm = TRUE),
            n = n())
head(rincome)
ggplot(rincome,aes(tvhours,fct_reorder(rincome,tvhours))) + geom_point()

ggplot(rincome,aes(tvhours,fct_relevel(rincome,"Not applicable"))) + geom_point()

* A função fct_reorder2() reordena o fator pelos valores de y associados com os maiores valores de x.

by_age <- gss_cat %>%
  filter(!is.na(age)) %>%
  count(age, marital) %>%
  group_by(age) %>%
  mutate(prop = n / sum(n))

ggplot(by_age, aes(age, prop, colour = marital)) +
  geom_line(na.rm = TRUE)

ggplot(by_age, aes(age, prop, colour = fct_reorder2(marital, age, prop))) +
  geom_line() +
  labs(colour = "marital")

f <- factor(c("a", "b", "c"))
fct_rev(f)
## [1] a b c
## Levels: c b a
gss_cat %>%
  mutate(marital = marital %>% fct_infreq() %>% fct_rev()) %>%
  ggplot(aes(marital)) +
    geom_bar()

gss_cat %>% count(partyid)
gss_cat %>%
  mutate(partyid = fct_recode(partyid,
    "Republican, strong"    = "Strong republican",
    "Republican, weak"      = "Not str republican",
    "Independent, near rep" = "Ind,near rep",
    "Independent, near dem" = "Ind,near dem",
    "Democrat, weak"        = "Not str democrat",
    "Democrat, strong"      = "Strong democrat"
  )) %>%
  count(partyid)
gss_cat %>%
  mutate(partyid = fct_recode(partyid,
    "Republican, strong"    = "Strong republican",
    "Republican, weak"      = "Not str republican",
    "Independent, near rep" = "Ind,near rep",
    "Independent, near dem" = "Ind,near dem",
    "Democrat, weak"        = "Not str democrat",
    "Democrat, strong"      = "Strong democrat",
    "Other"                 = "No answer",
    "Other"                 = "Don't know",
    "Other"                 = "Other party"
  )) %>%
  count(partyid)
# Agora veja o exemplo:

gss_cat %>%
  mutate(partyid = fct_collapse(partyid,
    other = c("No answer", "Don't know", "Other party"),
    rep = c("Strong republican", "Not str republican"),
    ind = c("Ind,near rep", "Independent", "Ind,near dem"),
    dem = c("Not str democrat", "Strong democrat")
  )) %>%
  count(partyid)
gss_cat %>%
  mutate(relig = fct_lump(relig)) %>%
  count(relig)
# O que muda agora?

gss_cat %>%
  mutate(relig = fct_lump(relig, n = 10)) %>%
  count(relig, sort = TRUE) %>%
  print(n = Inf)
## # A tibble: 10 x 2
##    relig                       n
##    <fct>                   <int>
##  1 Protestant              10846
##  2 Catholic                 5124
##  3 None                     3523
##  4 Christian                 689
##  5 Other                     458
##  6 Jewish                    388
##  7 Buddhism                  147
##  8 Inter-nondenominational   109
##  9 Moslem/islam              104
## 10 Orthodox-christian         95

Usando pipes com magrittr

Pacote magrittr.

Pacote magrittr.

library(magrittr)
## 
## Attaching package: 'magrittr'
## The following object is masked from 'package:purrr':
## 
##     set_names
## The following object is masked from 'package:tidyr':
## 
##     extract
head(iris)
iris %>% filter(Sepal.Width == 3)
# Agora usando %<>% (operador de atribuição composta)

iris<- iris%>% 
  transform(Sepal.Length = Sepal.Width)
iris
iris %<>% transform(Sepal.Length = Sepal.Width)

iris %$% cor(Petal.Length, Petal.Width)
## [1] 0.9628654
set.seed(123)
rnorm(1000) %>%
  matrix(ncol = 2) %>%
  plot() %>%
  str()

##  NULL
rnorm(1000) %>%
  matrix(ncol = 2) %T>%
  plot() %>%
  str()

##  num [1:500, 1:2] -0.996 -1.04 -0.018 -0.132 -2.549 ...