# Dados no diretorio de trabalho atual
::here('dados.txt')
here
# Dados em alguma subpasta do diretorio atual
::here('./pasta_dados/dados.txt')
here
# Dados em alguma pasta anterior ao diretorio atual
::here('../pasta_dados/dados.txt') here
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!!
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
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()
4.2 Etapa 1 - Carregamento
Para o carregamento dos dados iremos utilizar os pacotes: readr e readxl
- readr
- Readr Website
- Utilizado para arquivos em: csv, tsv, txt e web log
- readxl
- Readxl Website
- Utilizado para arquivos em: xlsx e xls
4.3 Etapa 2 - Limpeza Inicial
4.3.1 Janitor
- 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::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)
::starwars |>
dplyr::select(name,
dplyr
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
::starwars |>
dplyr::select(c(name,
dplyr::contains('color')
dplyr
) )
# 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
<- function(x) {
big > mean(x, na.rm = TRUE)
x
}
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 ::filter(dplyr::if_all(contains("bill"), big)) dplyr
# 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 ::filter(dplyr::if_any(contains("bill"), big)) dplyr
# 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
= readr::read_csv(here::here('./conjunto_de_dados/forbes.csv')) df_forbes
|>
df_forbes ::select(-'...1', -'...2') |>
dplyr::clean_names() |>
janitor::remove_empty(which = 'cols') janitor
# 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 ::select(-dplyr::starts_with('...')) dplyr
# 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 ::select(-'...1',
dplyr-'...2') |>
::clean_names() |>
janitor::remove_empty(which = 'cols') |>
janitor::paged_table() rmarkdown
|>
df_forbes ::select(- dplyr::starts_with('...')) |>
dplyr::clean_names() |>
janitor::remove_empty(which = 'cols') |>
janitor::paged_table() rmarkdown
# Salvando
= df_forbes |>
df_forbes ::select(- dplyr::starts_with('...')) |>
dplyr::clean_names() |>
janitor::remove_empty(which = 'cols') janitor
- 1
- Faça uma consulta que retorne apenas indivÃduos dos Estados Unidos
|>
df_forbes ::filter(country == 'United States') dplyr
# 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 ::filter(country == 'United States' & age < 30) dplyr
# 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
= readr::read_csv(here::here('./conjunto_de_dados/datasus.csv'),
df_morbidade n_max = 35,
locale = readr::locale(encoding = "latin1"))
= df_morbidade |>
df_morbidade ::remove_empty(which = 'rows') |>
janitor::row_to_names(2) |>
janitor::rename(ufs = 'Região/Unidade da Federação') |>
dplyr::filter(!stringr::str_detect(ufs, 'Região')) dplyr
|> rmarkdown::paged_table() df_morbidade
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 ::pivot_longer(-c(ufs, Total)) |>
tidyr::filter(!stringr::str_detect(value, '-')) |>
dplyr::select(-Total) |>
dplyr::rename(regiao = name,
dplyrcasos = value) |>
::mutate(ufs = ufs |>
dplyr::str_replace_all("\\.{2} ", "") |>
stringrtolower() |>
::rm_accent(),
abjutilsregiao = regiao |>
::str_remove_all('\\d\\sRegião\\s') |>
stringrtolower()) |>
::paged_table() rmarkdown
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
= readxl::read_xlsx(here::here('./conjunto_de_dados/ibge.xlsx')) |>
df_nasc_vivos ::row_to_names(1) |>
janitor::clean_names() |>
janitor::rename(cod_ibge = codigo_unidade_da_federacao_de_residencia_da_mae,
dplyruf = 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() |>
::paged_table() rmarkdown
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)
= readr::read_csv2(here::here('./conjunto_de_dados/datatran2023.csv'),
df_prf locale = readr::locale(encoding = "latin1"))
|>
df_prf head() |>
::paged_table() rmarkdown
= rvest::read_html('https://www.ibge.gov.br/explica/codigos-dos-municipios.php')
url
= data.frame(
web_scrap_ufs ufs = url|>
::html_nodes('.uf td:nth-child(1) a')|>
rvest::html_text(),
rvestcod = url|>
::html_nodes('.numero a')|>
rvest::html_text()
rvest
)
|>
web_scrap_ufs head() |>
::paged_table() rmarkdown
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
CANNEL, Brad; LIVINGSTON, Melvin. R for Epidemiology [recurso eletrônico]. 1. ed. DisponÃvel em: https://www.r4epi.com/.
ENGEL, Cody. Data Wrangling with R [recurso eletrônico]. 1. ed. DisponÃvel em: https://cengel.github.io/R-data-wrangling/
WICKHAM, Hadley; GROLEMUND, Garrett. R for Data Science [recurso eletrônico]. DisponÃvel em: https://r4ds.had.co.nz/index.html.