Arrumando BDs: o pacote janitor

Por William 24/07/2017

No primeiro post sobre arrumação de base de dados, a gente viu como usar as funções do stringr para arrumar o nome das variáveis. Seguindo a dica do Julio, o quebrador de captchas, vamos falar do pacote janitor, que traz algumas funções para dar aquele trato nas BDs.

Antes de mais nada, instale e carregue o pacote:

install.packages("janitor")
devtools::install_github("sfirke/janitor") # Versão de desenvolvimento
library(tidyverse)
library(janitor)

Arrumando o nome das variáveis

Assim como no post passado, utilizaremos a base com informações de pacientes com arritmia cardíaca, cujas variáveis selecionadas foram:

dados %>% names
##  [1] "ID"                   "Sexo"                 "Nascimento"          
##  [4] "Idade"                "Inclusão"             "Cor"                 
##  [7] "Peso"                 "Altura"               "cintura"             
## [10] "IMC"                  "Superfície corporal"  "Tabagismo"           
## [13] "cg.tabag (cig/dia)"   "Alcool (dose/semana)" "Drogas ilícitas"     
## [16] "Cafeína/dia"          "Refrig/dia"           "Sedentario"          
## [19] "ativ. Fisica"

Os nomes têm letras maiúsculas, acentos, parênteses, pontos e barras, o que atrapalha na hora da programação. Para resolver esse problema, usamos a função clean_names().

dados %>% 
  clean_names() %>% 
  names
##  [1] "id"                  "sexo"                "nascimento"         
##  [4] "idade"               "inclusão"            "cor"                
##  [7] "peso"                "altura"              "cintura"            
## [10] "imc"                 "superfície_corporal" "tabagismo"          
## [13] "cg_tabag_cig_dia"    "alcool_dose_semana"  "drogas_ilícitas"    
## [16] "cafeína_dia"         "refrig_dia"          "sedentario"         
## [19] "ativ_fisica"

Veja que a função removeu os parênteses, pontos e barras e substituiu os espaços por _. No entanto, ela não remove os acentos. Assim, podemos adicionar mais uma linha ao pipeline para chegar onde queremos.

dados %>%
  clean_names() %>% 
  names %>% 
  abjutils::rm_accent()
##  [1] "id"                  "sexo"                "nascimento"         
##  [4] "idade"               "inclusao"            "cor"                
##  [7] "peso"                "altura"              "cintura"            
## [10] "imc"                 "superficie_corporal" "tabagismo"          
## [13] "cg_tabag_cig_dia"    "alcool_dose_semana"  "drogas_ilicitas"    
## [16] "cafeina_dia"         "refrig_dia"          "sedentario"         
## [19] "ativ_fisica"

E para substituir na base.

nomes <- dados %>%
  clean_names() %>% 
  names %>% 
  abjutils::rm_accent()

names(dados) <- nomes

Removendo linhas e colunas vazias

Esse banco de dados também tinha outro problema: linhas vazias. Na verdade, elas não eram completamente vazias, pois havia algumas informações de identificação do paciente, mas nenhuma outra variável tinha sido computada.

dados[3,]
## # A tibble: 1 x 19
##      id  sexo nascimento idade inclusao   cor  peso altura cintura   imc
##   <dbl> <chr>     <dttm> <dbl>   <dttm> <chr> <dbl>  <dbl>   <chr> <dbl>
## 1     3  <NA>         NA    NA       NA  <NA>    NA     NA    <NA>    NA
## # ... with 9 more variables: superficie_corporal <chr>, tabagismo <chr>,
## #   cg_tabag_cig_dia <dbl>, alcool_dose_semana <dbl>,
## #   drogas_ilicitas <chr>, cafeina_dia <dbl>, refrig_dia <dbl>,
## #   sedentario <chr>, ativ_fisica <chr>

Essa foi a solução que eu pensei para resolver o problema utilizando a função remove_empty_row().

dados %<>% 
  as.data.frame %>% 
  `row.names<-`(dados$id) %>%
  select(-id) %>% 
  remove_empty_rows() %>% 
  mutate(id = row.names(.)) %>%
  select(id, everything())

dados %>% as_tibble()
## # A tibble: 4 x 19
##      id  sexo nascimento idade   inclusao    cor  peso altura cintura
##   <chr> <chr>     <dttm> <dbl>     <dttm>  <chr> <dbl>  <dbl>   <chr>
## 1     1     F 1964-01-31    41 2006-02-17 branca    75   1.63      98
## 2     2     M 1959-01-28    45 2005-11-29  negra    71   1.70      NT
## 3     4     M 1957-09-13    50 2008-02-13     NT    80   1.64      NT
## 4     5     F 1938-02-06    71 2009-06-25  parda    56   1.51      96
## # ... with 10 more variables: imc <dbl>, superficie_corporal <chr>,
## #   tabagismo <chr>, cg_tabag_cig_dia <dbl>, alcool_dose_semana <dbl>,
## #   drogas_ilicitas <chr>, cafeina_dia <dbl>, refrig_dia <dbl>,
## #   sedentario <chr>, ativ_fisica <chr>

Eu precisei converter para data.frame primeiro porque não é possível definir os nomes das linhas de uma tibble. Se a linha estivesse completamente vazia, bastaria usar diretamente a função remove_empty_rows().

Equivalentemente para colunas, existe a função remove_empty_cols().

Identificando linhas duplicadas

O pacote janitor possui uma função para identificar entradas duplicadas numa base de dados: get_dupes(). Vamos criar uma base genérica para testá-la.


p_nome <- c("Athos", "Daniel", "Fernando", "Julio", "William")
sobrenome <- c("Damiani", "Falbel", "Corrêa", "Trecenti", "Amorim")

base_qualquer <- tibble(nome = sample(p_nome, 25, replace = T),
                        sobrenome = sample(sobrenome, 25, replace = T),
                        variavel_importante = rnorm(25))

get_dupes(base_qualquer, nome, sobrenome)
## # A tibble: 13 x 4
##        nome sobrenome dupe_count variavel_importante
##       <chr>     <chr>      <int>               <dbl>
##  1    Athos    Corrêa          2         -0.31916013
##  2    Athos    Corrêa          2         -0.58043597
##  3    Athos  Trecenti          2          0.47964748
##  4    Athos  Trecenti          2          0.81266293
##  5   Daniel  Trecenti          2          0.70663312
##  6   Daniel  Trecenti          2         -1.24561119
##  7 Fernando   Damiani          3          1.11151803
##  8 Fernando   Damiani          3          1.91397433
##  9 Fernando   Damiani          3         -0.42731219
## 10    Julio    Amorim          2          0.44948233
## 11    Julio    Amorim          2         -0.76396685
## 12    Julio   Damiani          2          0.68206736
## 13    Julio   Damiani          2         -0.09278403

Todas as linhas na tibble resultante representam uma combinação de nome-sobrenome repetida.

Outras funções

Por fim, o janitor também tem funções equivalentes à table() para produzir tabelas de frequência:

  • tabyl() - similar a table(), mas pipe-ável e com mais recursos.
  • crosstab() - para tabelas de contingência.
  • adorn_totals() - acrescenta o total das linhas ou colunas.
  • adorn_crosstab() - deixa tabelas de contingência mais bonitas.
mtcars %>% 
  tabyl(cyl)
##   cyl  n percent
## 1   4 11 0.34375
## 2   6  7 0.21875
## 3   8 14 0.43750

mtcars %>% 
  tabyl(cyl) %>% 
  adorn_totals
##     cyl  n percent    Total
## 1     4 11 0.34375 11.34375
## 2     6  7 0.21875  7.21875
## 3     8 14 0.43750 14.43750
## 4 Total 32 1.00000 33.00000

mtcars %>% 
  crosstab(cyl, am)
##   cyl  0 1
## 1   4  3 8
## 2   6  4 3
## 3   8 12 2

mtcars %>% 
  crosstab(cyl, am) %>% 
  adorn_crosstab
##   cyl          0         1
## 1   4 27.3%  (3) 72.7% (8)
## 2   6 57.1%  (4) 42.9% (3)
## 3   8 85.7% (12) 14.3% (2)

É isso! Espero que essas dicas e o pacote janitor ajudem a agilizar as suas análises. Dúvidas, críticas ou sugestões, deixe um comentário ou nos envie uma mensagem. :)

comments powered by Disqus