Aula 2 - Dados Tidy

1 Botando a mão na massa

Seja bem-vindo a segunda aula do nosso minicurso de Fundamentos de Processamento de Dados Utilizando o Tidyverse!

Parabéns pela perseverança e vontade de aprender!!

Arte de @allison_horst

Na aula de hoje, iremos:

  • Entender as principais diferenças entre os objetos tabulares do R

  • Introduzir o conceito de Tidy Data e observar os principais erros ao se trabalhar com conjunto de dados

  • Começar a botar a mão na massa

2 Objetos Tabulares

2.1 Data.frame

Sâo objetos para manipulação de dados padrão do R, ou seja, esses já vem instalados com o software

Um data.frame é retangular como uma matriz, mas tem a vantagem de armazenar vetores de diferentes tipos (character, numeric, logical e etc) nas suas colunas. O que não é possível em uma matriz. Ou seja é uma estrutura de armazenamento de dados heterogênea.

Cada linha de um data.frame corresponde a uma observação. Cada coluna corresponde a uma variável.

2.2 Tibble

Se auto denomina como a versão aperfeiçoada de uma data.frame, e é o objeto tabular padrão do Tidyverse

Sua sintaxe se assemelha com funções do SQL e Spark

A introdução do Tibble veio conjuntamente com o conceito de dados Tidy(Tidy Data) desenvolvido por Hadley Wickham, em 2014 no artigo publicado em Journal of Statistical Software: Tidy Data

Esse objeto será profundamente estudado durante esse mini curso

2.3 Data.table

Assim como um data.frame e um tibble, um data.table também é um objeto tabular, onde observações devem ser dispostas nas linhas e variáveis em colunas

O data.table surgiu no contexto de Big Data, sendo um objeto otimizado para processamento de dados em bases de alta dimensionalidade. Sua principal característica é a velocidade de execução

Apesar de ser consumir menos memória e ser extremamente veloz, seus comandos não são compatíveis em outros frameworks, onde um tibble se destaca por essa característica

3 Tidy Data

Arte de @allison_horst

O conceito introduzido por Hadley Wickham em 2014 teve como objetivo de melhorar o processo de limpeza e preparação de dados

Durante o artigo, Wickham listou os 5 erros mais comuns na hora de organizar os dados de acordo com estes princípios.

  • Nome de Colunas e Variáveis
    • Os cabeçalhos (a primeira linha da tabela) são valores, não o nome das variáveis.
  • Duplo Sentido
    • Uma única variável armazenada em diversas colunas
  • Dados sem orientação
    • Variáveis armazenadas tanto em linhas, como em colunas.
  • Observações Duplicatas
    • Diferentes tipos de unidades observacionais estão armazenadas na mesma tabela
  • Observações Dispersas
    • Uma única unidade observacional está armazenada em diferentes tabelas.

4 Iniciando o processamento de dados

4.1 Etapa 0 - Se localizar

O pacote here surgiu para solucionar problemas a relacionados a localização de diretórios de trabalhos. Em contrates a função setwd() que é frágil, e causa inúmeros problemas ao se trabalhar em projetos de equipe, o pacote utiliza o conceito de Project-oriented workflow

A documentação oficial do pacote Here Website

Ele possui 2 funções principais

  • here::here()
    • Retorna seu diretório atual de trabalho e permite incluir argumentos de caminho posteriores ao seu diretório atual na própria função
  • here::i_am()
    • Funciona como a função setwd(), é utilizada em conjunto com a função here()
# Dados no diretorio de trabalho atual
here::here('dados.txt')

# Dados em alguma subpasta do diretorio atual
here::here('./pasta_dados/dados.txt')

# Dados em alguma pasta anterior ao diretorio atual

here::here('../pasta_dados/dados.txt')

4.2 Etapa 1 - Carregamento

Para o carregamento dos dados iremos utilizar os pacotes: readr e readxl

4.3 Etapa 2 - Limpeza Inicial

4.3.1 Janitor

Janitor Vignette

  • janitor::clean_names()
    • Reescreve nomes de colunas de maneira automática
    • Utilizado sempre após o carregamento inicial dos dados
  • janitor::remove_empty()
    • Remove linhas ou colunas com valores NAs
  • janitor::row_to_names()
    • Seleciona determinada linha para torna-la como nome de colunas

4.3.2 Dplyr

Dplyr Website

  • dplyr::filter()
    • Filtra linhas baseadas em alguma condiÇão
  • dplyr::rename()
    • Renomeia colunas
  • dplyr::select()
    • Seleciona apenas as colunas desejadas

4.4 Funções Auxiliares

Utilizadas ao desejar filtrar, renomear ou selecionar várias linhas ou colunas em ‘uma tacada’

  • Selecionar variáveis baseado em alguma condição
    • As funções dplyr::starts_with(), dplyr::ends_with() e dplyr::contains() selecionam variáveis do tipo caracter baseados em alguma condição (É interessante conhecer as regular expressions (regex) para utilizar essas funções)
dplyr::starwars |>
  dplyr::select(name,
                hair_color,
                skin_color,
                eye_color)
# A tibble: 87 x 4
   name               hair_color    skin_color  eye_color
   <chr>              <chr>         <chr>       <chr>    
 1 Luke Skywalker     blond         fair        blue     
 2 C-3PO              <NA>          gold        yellow   
 3 R2-D2              <NA>          white, blue red      
 4 Darth Vader        none          white       yellow   
 5 Leia Organa        brown         light       brown    
 6 Owen Lars          brown, grey   light       blue     
 7 Beru Whitesun lars brown         light       blue     
 8 R5-D4              <NA>          white, red  red      
 9 Biggs Darklighter  black         light       brown    
10 Obi-Wan Kenobi     auburn, white fair        blue-gray
# i 77 more rows
## Com função auxiliar

dplyr::starwars |>
  dplyr::select(c(name, 
                  dplyr::contains('color')
                  )
                )
# A tibble: 87 x 4
   name               hair_color    skin_color  eye_color
   <chr>              <chr>         <chr>       <chr>    
 1 Luke Skywalker     blond         fair        blue     
 2 C-3PO              <NA>          gold        yellow   
 3 R2-D2              <NA>          white, blue red      
 4 Darth Vader        none          white       yellow   
 5 Leia Organa        brown         light       brown    
 6 Owen Lars          brown, grey   light       blue     
 7 Beru Whitesun lars brown         light       blue     
 8 R5-D4              <NA>          white, red  red      
 9 Biggs Darklighter  black         light       brown    
10 Obi-Wan Kenobi     auburn, white fair        blue-gray
# i 77 more rows
  • Filtragem não especificada
    • As funções dplyr::if_any dplyr::if_all são utilizadas para uma condição em uma filtragem que não especifica uma variável

Exemplo Retirado do site do tidyverse

library(palmerpenguins)

# Funcao retorne T ou F se o valor for maoior que o valor médio da variável
big <- function(x) {
  x > mean(x, na.rm = TRUE)
}


penguins
# A tibble: 344 x 8
   species island    bill_length_mm bill_depth_mm flipper_length_mm body_mass_g
   <fct>   <fct>              <dbl>         <dbl>             <int>       <int>
 1 Adelie  Torgersen           39.1          18.7               181        3750
 2 Adelie  Torgersen           39.5          17.4               186        3800
 3 Adelie  Torgersen           40.3          18                 195        3250
 4 Adelie  Torgersen           NA            NA                  NA          NA
 5 Adelie  Torgersen           36.7          19.3               193        3450
 6 Adelie  Torgersen           39.3          20.6               190        3650
 7 Adelie  Torgersen           38.9          17.8               181        3625
 8 Adelie  Torgersen           39.2          19.6               195        4675
 9 Adelie  Torgersen           34.1          18.1               193        3475
10 Adelie  Torgersen           42            20.2               190        4250
# i 334 more rows
# i 2 more variables: sex <fct>, year <int>
# keep rows if all the selected columns are "big"
penguins |>
  dplyr::filter(dplyr::if_all(contains("bill"), big))
# A tibble: 61 x 8
   species   island   bill_length_mm bill_depth_mm flipper_length_mm body_mass_g
   <fct>     <fct>             <dbl>         <dbl>             <int>       <int>
 1 Adelie    Torgers~           46            21.5               194        4200
 2 Adelie    Dream              44.1          19.7               196        4400
 3 Adelie    Torgers~           45.8          18.9               197        4150
 4 Adelie    Biscoe             45.6          20.3               191        4600
 5 Adelie    Torgers~           44.1          18                 210        4000
 6 Gentoo    Biscoe             44.4          17.3               219        5250
 7 Gentoo    Biscoe             50.8          17.3               228        5600
 8 Chinstrap Dream              46.5          17.9               192        3500
 9 Chinstrap Dream              50            19.5               196        3900
10 Chinstrap Dream              51.3          19.2               193        3650
# i 51 more rows
# i 2 more variables: sex <fct>, year <int>
# keep rows where at least one of the columns is "big"
penguins |>
  dplyr::filter(dplyr::if_any(contains("bill"), big))
# A tibble: 296 x 8
   species island    bill_length_mm bill_depth_mm flipper_length_mm body_mass_g
   <fct>   <fct>              <dbl>         <dbl>             <int>       <int>
 1 Adelie  Torgersen           39.1          18.7               181        3750
 2 Adelie  Torgersen           39.5          17.4               186        3800
 3 Adelie  Torgersen           40.3          18                 195        3250
 4 Adelie  Torgersen           36.7          19.3               193        3450
 5 Adelie  Torgersen           39.3          20.6               190        3650
 6 Adelie  Torgersen           38.9          17.8               181        3625
 7 Adelie  Torgersen           39.2          19.6               195        4675
 8 Adelie  Torgersen           34.1          18.1               193        3475
 9 Adelie  Torgersen           42            20.2               190        4250
10 Adelie  Torgersen           37.8          17.3               180        3700
# i 286 more rows
# i 2 more variables: sex <fct>, year <int>

4.5 Exemplos

4.5.1 Grandes Fortunas - Forbes

O seguinte conjunto de dados foi retirado do Kaggle lista os indivíduos mais ricos do mundo, assim como algumas de suas características

df_forbes = readr::read_csv(here::here('./conjunto_de_dados/forbes.csv'))
df_forbes |>
  dplyr::select(-'...1', -'...2') |>
  janitor::clean_names() |>
  janitor::remove_empty(which = 'cols')
# A tibble: 2,600 x 7
    rank name                     net_worth   age country       source  industry
   <dbl> <chr>                    <chr>     <dbl> <chr>         <chr>   <chr>   
 1     1 Elon Musk                $219 B       50 United States Tesla,~ Automot~
 2     2 Jeff Bezos               $171 B       58 United States Amazon  Technol~
 3     3 Bernard Arnault & family $158 B       73 France        LVMH    Fashion~
 4     4 Bill Gates               $129 B       66 United States Micros~ Technol~
 5     5 Warren Buffett           $118 B       91 United States Berksh~ Finance~
 6     6 Larry Page               $111 B       49 United States Google  Technol~
 7     7 Sergey Brin              $107 B       48 United States Google  Technol~
 8     8 Larry Ellison            $106 B       77 United States softwa~ Technol~
 9     9 Steve Ballmer            $91.4 B      66 United States Micros~ Technol~
10    10 Mukesh Ambani            $90.7 B      64 India         divers~ Diversi~
# i 2,590 more rows
df_forbes |>
  dplyr::select(-dplyr::starts_with('...'))
# A tibble: 2,600 x 8
    rank name              `Net Worth`   AGE country Source industry soccer_team
   <dbl> <chr>             <chr>       <dbl> <chr>   <chr>  <chr>    <lgl>      
 1     1 Elon Musk         $219 B         50 United~ Tesla~ Automot~ NA         
 2     2 Jeff Bezos        $171 B         58 United~ Amazon Technol~ NA         
 3     3 Bernard Arnault ~ $158 B         73 France  LVMH   Fashion~ NA         
 4     4 Bill Gates        $129 B         66 United~ Micro~ Technol~ NA         
 5     5 Warren Buffett    $118 B         91 United~ Berks~ Finance~ NA         
 6     6 Larry Page        $111 B         49 United~ Google Technol~ NA         
 7     7 Sergey Brin       $107 B         48 United~ Google Technol~ NA         
 8     8 Larry Ellison     $106 B         77 United~ softw~ Technol~ NA         
 9     9 Steve Ballmer     $91.4 B        66 United~ Micro~ Technol~ NA         
10    10 Mukesh Ambani     $90.7 B        64 India   diver~ Diversi~ NA         
# i 2,590 more rows
  • 0
    • Remova colunas e linhas indesejáveis. Padronize o nome das variáveis
df_forbes |>
  dplyr::select(-'...1',
                -'...2') |>
  janitor::clean_names() |>
  janitor::remove_empty(which =  'cols') |>
  rmarkdown::paged_table()
df_forbes |>
  dplyr::select(- dplyr::starts_with('...')) |>
  janitor::clean_names() |>
  janitor::remove_empty(which =  'cols') |>
  rmarkdown::paged_table()
# Salvando 
df_forbes = df_forbes |>
  dplyr::select(- dplyr::starts_with('...'))  |>
  janitor::clean_names() |>
  janitor::remove_empty(which =  'cols') 
  • 1
    • Faça uma consulta que retorne apenas indivíduos dos Estados Unidos
df_forbes |>
  dplyr::filter(country == 'United States') 
# A tibble: 719 x 7
    rank name              net_worth   age country       source         industry
   <dbl> <chr>             <chr>     <dbl> <chr>         <chr>          <chr>   
 1     1 Elon Musk         $219 B       50 United States Tesla, SpaceX  Automot~
 2     2 Jeff Bezos        $171 B       58 United States Amazon         Technol~
 3     4 Bill Gates        $129 B       66 United States Microsoft      Technol~
 4     5 Warren Buffett    $118 B       91 United States Berkshire Hat~ Finance~
 5     6 Larry Page        $111 B       49 United States Google         Technol~
 6     7 Sergey Brin       $107 B       48 United States Google         Technol~
 7     8 Larry Ellison     $106 B       77 United States software       Technol~
 8     9 Steve Ballmer     $91.4 B      66 United States Microsoft      Technol~
 9    12 Michael Bloomberg $82 B        80 United States Bloomberg LP   Media &~
10    15 Mark Zuckerberg   $67.3 B      37 United States Facebook       Technol~
# i 709 more rows
  • 2
    • Faça uma consulta que retorne apenas indivíduos dos Estados Unidos e com idade abaixo de 30 anos
df_forbes |>
  dplyr::filter(country == 'United States' & age < 30) 
# A tibble: 5 x 7
   rank name           net_worth   age country       source             industry
  <dbl> <chr>          <chr>     <dbl> <chr>         <chr>              <chr>   
1   431 Gary Wang      $5.9 B       28 United States cryptocurrency ex~ Finance~
2  1513 Ryan Breslow   $2 B         27 United States e-commerce softwa~ Technol~
3  1818 Austin Russell $1.6 B       27 United States sensors<U+2605>    Automot~
4  2324 Stanley Tang   $1.2 B       29 United States food delivery app  Technol~
5  2448 Andy Fang      $1.1 B       29 United States food delivery app  Technol~

5 Desafio do Minicurso

Os seguintes desafios serão utilizados durante todo o mini curso.

5.1 Dados Tabnet/Datasus - Morbidade Hospitalar

Os dados foram retirados do Tabnet.

O conjunto de dados possui a ufs de referéncia, assim como o total de morbidade hospitalar

df_morbidade = readr::read_csv(here::here('./conjunto_de_dados/datasus.csv'),
                        n_max = 35,
                        locale = readr::locale(encoding = "latin1"))


df_morbidade = df_morbidade |>
  janitor::remove_empty(which = 'rows') |>
  janitor::row_to_names(2) |>
  dplyr::rename(ufs = 'Região/Unidade da Federação') |>
  dplyr::filter(!stringr::str_detect(ufs, 'Região'))
df_morbidade |> rmarkdown::paged_table()

Podemos chegar até essa etapa de uma limpeza dos dados com o que foi visto nessa aula

Um spoiler do que veremos na próxima aula, onde conheceremos as funções mutate, pivot_longer e pivot_wider

df_morbidade |>
  tidyr::pivot_longer(-c(ufs, Total)) |>
  dplyr::filter(!stringr::str_detect(value, '-')) |>
  dplyr::select(-Total) |>
  dplyr::rename(regiao = name,
                casos = value) |>
  dplyr::mutate(ufs = ufs |>
                  stringr::str_replace_all("\\.{2} ", "") |>
                  tolower() |>
                  abjutils::rm_accent(),
                regiao = regiao |>
                  stringr::str_remove_all('\\d\\sRegião\\s') |>
                  tolower()) |>
  rmarkdown::paged_table()

5.2 Dados IBGE - Nascidos Vivos

O seguinte conjunto de dados foi retirado do site do IBGE

A tabela possui números de nascidos vivos por uf e por idade da mãe, além de números de subresgistros e subnotificações

Nosso objetivo é limpar o conjunto de dados, corrigindo nome de variáveis, seu tipo e corrigindo eventuais obstáculos das etapas de análise e modelagem

df_nasc_vivos = readxl::read_xlsx(here::here('./conjunto_de_dados/ibge.xlsx')) |>
  janitor::row_to_names(1) |>
  janitor::clean_names() |>
  dplyr::rename(cod_ibge = codigo_unidade_da_federacao_de_residencia_da_mae,
                uf = unidade_da_federacao_de_residencia_da_mae,
                idade = idade_da_mae_na_ocasiao_do_parto,
                nasc_vivo = total_estimado_de_nascidos_vivos,
                subres_nasc_vivo = sub_registro_de_nascidos_vivos_ibge_percent,
                subnot_nasc_vivos = subnotificacao_de_nascidos_vivos_ministerio_da_saude_percent)

df_nasc_vivos |> 
  head() |>
  rmarkdown::paged_table()

5.3 Dados - PRF Sudeste

O seguinte conjunto de dados foi baixado no site do Detran, se tratando de acidentes de transito de 2023

O conjunto de dados possui observações do Brasil inteiro, nosso objetivo é limpar esse conjunto, filtrando apenas pelas observações da região Sudeste

library(rvest)

df_prf = readr::read_csv2(here::here('./conjunto_de_dados/datatran2023.csv'), 
                          locale = readr::locale(encoding = "latin1"))


df_prf |>
  head() |>
  rmarkdown::paged_table()
url = rvest::read_html('https://www.ibge.gov.br/explica/codigos-dos-municipios.php')

web_scrap_ufs = data.frame(
  ufs = url|>
      rvest::html_nodes('.uf td:nth-child(1) a')|>
      rvest::html_text(),
  cod = url|>
      rvest::html_nodes('.numero a')|>
      rvest::html_text()
)

web_scrap_ufs |> 
  head() |>
  rmarkdown::paged_table()

Para filtrar baseado na tabela web_scraps_ufs devemos antes limpa-la, para isso, sera necessária a função mutate, que veremos na próxima aula

6 Referências


Footer Image