Introdução ao data cleaning

Aqui, vamos explorar técnicas para limpeza e organização de dados com os pacotes {dplyr} e {janitor}, otimizando o fluxo e a precisão dos dados para análise.
análises
data cleaning
dplyr
janitor
Autor

Aldani Braz Carvalho

Data de Publicação

6 de novembro de 2024

Introdução

A limpeza e organização dos dados é fundamental para evitar retrabalho e simplificar as etapas subsequentes. Abaixo, apresento pacotes e funções chave:

tidyverse - não é um pacote, mas um conjunto de pacotes1 que fornece uma gramática consistente para manipulação de dados, visualização e modelagem. Inclui funções para filtrar, agrupar e transformar dados de maneira intuitiva.

dplyr - é fundamental para limpeza e manipulação de dados no R, oferecendo uma sintaxe intuitiva e poderosa especialmente para:

  • seleção de colunas com select() e linhas com filter() com base em condições específicas;

  • criação e modificação colunas e para transformar variáveis com mutate();

  • renomear colunas com rename(), tornando o processo mais simples e legível;

janitor - oferece funções para limpar e organizar conjuntos de dados, como renomear colunas e remover dados duplicados. É especialmente útil para preparar dados para análise.Mas aqui eu utilizei sua principal função clean_names().

Mão na massa

Importação e pré-processamentos

Diretório de trabalho

O primeiro passo é determinar o diretório de trabalho. Há mais de uma forma de fazer, portanto, recomendo que inicie um novo projeto no R em vez de usar o setwd(). Leia mais sobre isso neste post.

Bibliotecas

  1. Instale as bibliotecas:
install.packages("tidyverse", 
                 dependencies = T)
install.packages("janitor", 
                 dependencies = T)
  1. Carregue as bibliotecas para que possamos utilizá-las:

Importar o dado

Para otimizar o processo de importação de dados, podemos utilizar a função read.csv() do R base.



Após importar os dados, gosto de visualizar rapidamente as 15 primeiras linhas. Para isso, recorro à função slice_head() do dplyr, que me proporciona uma maneira prática de obter uma amostra inicial dos dados.



Outra forma de visualizar os dados é por meio do glimpse() que proporciona um vislubre dos dados, incluindo seus tipos e estruturas. A aba Código skip e seu resultado mostram o uso dessa função.



Como você pode ver na aba Código e seu Resultado, as primeiras 9 linhas são um cabeçalho inútil para nós, então podemos eliminá-las ao importar o dado com o argumento skip na aba Código skip e seu Resultado.

# URL do arquivo CSV no GitHub
url <- "https://raw.githubusercontent.com/aldanicarvalho/datacleaning/refs/heads/main/PVH_2022-08-01_2023-05-09_Diarios.csv"

# Ler o arquivo CSV diretamente do GitHub
dados <- read.csv(url,
                  sep = ";") # separador é ;

# Visualizar os dados carregados
dplyr::slice_head(dados,
                  n = 15)
                               Nome..PORTO.VELHO
1                           Codigo Estacao: A925
2                           Latitude: -8.7936111
3                        Longitude: -63.84583333
4                                 Altitude: 86.7
5                             Situacao: Operante
6                       Data Inicial: 2022-08-01
7                         Data Final: 2023-05-09
8               Periodicidade da Medicao: Diaria
9                                   Data Medicao
10          PRECIPITACAO TOTAL, DIARIO (AUT)(mm)
11           TEMPERATURA MEDIA, DIARIA (AUT)(°C)
12 UMIDADE RELATIVA DO AR, MEDIA DIARIA (AUT)(%)
13     VENTO, VELOCIDADE MEDIA DIARIA (AUT)(m/s)
14                                    2022-08-01
15                                             0
# URL do arquivo CSV no GitHub
url <- "https://raw.githubusercontent.com/aldanicarvalho/datacleaning/refs/heads/main/PVH_2022-08-01_2023-05-09_Diarios.csv"

# Ler o arquivo CSV diretamente do GitHub
dados_2 <- read.csv(url,
                    sep = ";", # separador é ;
                    skip = 9)  # pula as 9 primeiras linhas 

# Visualizar os dados carregados
glimpse(dados_2)
Rows: 282
Columns: 6
$ Data.Medicao                                  <chr> "2022-08-01", "2022-08-0…
$ PRECIPITACAO.TOTAL..DIARIO..AUT..mm.          <chr> "0", "0", "0", "0", ".4"…
$ TEMPERATURA.MEDIA..DIARIA..AUT...C.           <chr> "26.7", "28.1", "28", "2…
$ UMIDADE.RELATIVA.DO.AR..MEDIA.DIARIA..AUT.... <chr> "null", "null", "null", …
$ VENTO..VELOCIDADE.MEDIA.DIARIA..AUT..m.s.     <chr> "1", "1.5", "1.2", "1.1"…
$ X                                             <lgl> NA, NA, NA, NA, NA, NA, …

Limpar e organizar

Simplificando os nomes das colunas

Os dados agora estão salvos como um objeto no R, prontos para explorarmos e manipulá-los à vontade.


A primeira ação que tomaremos será a automatização da renomeação das colunas, utilizando a função clean_names() do pacote janitor.

A Figura 1 resume bem a ação da principal função do pacote.

Síntese da ação da função clear_names()
Figura 1: Síntese da ação da função clean_names(). Fonte: ilustrado por Horst (2024).



Vamos aproveitar a versatilidade do operador pipe (|>), acessível pelo atalho CTRL + SHIFT + M.


Essa ferramenta fantástica permite que escrevamos o código de forma linear, refletindo nosso raciocínio, o que torna a experiência de programação em R não apenas eficiente, mas também agradável.

Também usei a função as_tibble() para converter os dados em um formato de tibble, que é uma versão moderna de data frames em R.


O tibble oferece uma maneira mais eficiente de trabalhar com conjuntos de dados, permitindo uma visualização mais clara e funcionalidades aprimoradas. Essa conversão facilita a manipulação e análise dos dados, tornando as operações mais intuitivas e o código mais legível.

# Limpar nome das colunas
dados_3 <- dados_2 |>
  janitor::clean_names() |> 
  as_tibble() |> 
  dplyr::glimpse()
Rows: 282
Columns: 6
$ data_medicao                            <chr> "2022-08-01", "2022-08-02", "2…
$ precipitacao_total_diario_aut_mm        <chr> "0", "0", "0", "0", ".4", "4.4…
$ temperatura_media_diaria_aut_c          <chr> "26.7", "28.1", "28", "26.4", …
$ umidade_relativa_do_ar_media_diaria_aut <chr> "null", "null", "null", "null"…
$ vento_velocidade_media_diaria_aut_m_s   <chr> "1", "1.5", "1.2", "1.1", "1.3…
$ x                                       <lgl> NA, NA, NA, NA, NA, NA, NA, NA…

Renomeando as colunas

Após utilizar a função clean_names() do pacote janitor para realizar a limpeza automática dos nomes das colunas, observamos que, embora a função tenha cumprido seu papel de forma eficaz, ainda é necessário simplificar esses nomes para facilitar sua manipulação e interpretação. Para esse propósito, empregaremos a função rename() do dplyr.



Você pode utilizar a função names() do R base para extrair os nomes das colunas do data frame. Essa abordagem facilitará o processo de renomeação, permitindo que você visualize rapidamente os nomes atuais e os ajuste conforme necessário.

# pega os nomes das colunas
names(dados_3)
[1] "data_medicao"                           
[2] "precipitacao_total_diario_aut_mm"       
[3] "temperatura_media_diaria_aut_c"         
[4] "umidade_relativa_do_ar_media_diaria_aut"
[5] "vento_velocidade_media_diaria_aut_m_s"  
[6] "x"                                      
# renomear colunas
dados_4 <- dados_3 |> 
  dplyr::rename(
    data = data_medicao,
    chuva = precipitacao_total_diario_aut_mm,
    temp = temperatura_media_diaria_aut_c,
    umid = umidade_relativa_do_ar_media_diaria_aut,
    ws = vento_velocidade_media_diaria_aut_m_s
  ) |> 
  dplyr::glimpse()
Rows: 282
Columns: 6
$ data  <chr> "2022-08-01", "2022-08-02", "2022-08-03", "2022-08-04", "2022-08…
$ chuva <chr> "0", "0", "0", "0", ".4", "4.4", "0", "6.2", ".8", "0", "0", "0"…
$ temp  <chr> "26.7", "28.1", "28", "26.4", "26.4", "26.2", "28.2", "25.4", "2…
$ umid  <chr> "null", "null", "null", "null", "null", "null", "null", "null", …
$ ws    <chr> "1", "1.5", "1.2", "1.1", "1.3", "1.2", "1.2", "1.1", "1.4", "2.…
$ x     <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …

Selecionando colunas

Nós fizemos um bom trabalho organizando e limpando os dados, mas agora vamos selecionar somente as colunas que nos interessam. Para isso utilizamos a função select() do dplyr.

Dica

Embora o select() permita escolher colunas por números, eu recomendo fortemente que você resista a essa tentação! Escolher colunas pelo nome deixa o código mais claro e fácil de entender, enquanto números tornam o código enigmático e difícil de revisar depois. Imagine voltar ao seu código meses depois e tentar decifrar por que escolheu a coluna 5 e não a 6. 😅



Neste caso, utilizei select(data:temp) para selecionar todos os elementos de data até temp de uma vez e ws que não estava na sequência. Isso agiliza o processo quando quero uma sequência de colunas específica, economizando tempo e mantendo o código limpo.

Outra opção interessante é incluir ou excluir colunas individuais, colocando um sinal de menos - antes das variáveis que quero deixar de fora. Isso me permite, por exemplo, selecionar várias colunas ao mesmo tempo, enquanto omito apenas algumas que não são úteis para a análise atual. Foi o que eu fiz ao usar select(-x, -umid) na aba Código com menos.

# selecionar colunas
dados_5 <- dados_4 |> 
  dplyr::select(
    data:temp,
    ws
  ) |> 
  glimpse()
Rows: 282
Columns: 4
$ data  <chr> "2022-08-01", "2022-08-02", "2022-08-03", "2022-08-04", "2022-08…
$ chuva <chr> "0", "0", "0", "0", ".4", "4.4", "0", "6.2", ".8", "0", "0", "0"…
$ temp  <chr> "26.7", "28.1", "28", "26.4", "26.4", "26.2", "28.2", "25.4", "2…
$ ws    <chr> "1", "1.5", "1.2", "1.1", "1.3", "1.2", "1.2", "1.1", "1.4", "2.…
# selecionar colunas
dados_5 <- dados_4 |> 
  dplyr::select(
    -x, 
    -umid) |> 
  glimpse()
Rows: 282
Columns: 4
$ data  <chr> "2022-08-01", "2022-08-02", "2022-08-03", "2022-08-04", "2022-08…
$ chuva <chr> "0", "0", "0", "0", ".4", "4.4", "0", "6.2", ".8", "0", "0", "0"…
$ temp  <chr> "26.7", "28.1", "28", "26.4", "26.4", "26.2", "28.2", "25.4", "2…
$ ws    <chr> "1", "1.5", "1.2", "1.1", "1.3", "1.2", "1.2", "1.1", "1.4", "2.…

Transformando colunas

Para filtrar variáveis em R, é essencial que cada uma esteja na classe correta. Caso contrário, o R não conseguirá processá-las conforme esperado, o que pode impedir ou comprometer a análise. Por exemplo, ao rodar o comando class(dados_5$temp) o resultado será character, impossibilitando qualquer tipo de análise numérica.

É aqui que entra a função mutate() do dplyr. Com mutate(), é possível converter rapidamente as variáveis para as classes que preciso – seja transformando texto em datas, números em fatores, ou qualquer ajuste que a análise exija.

# mudar as classes
dados_6 <- dados_5 |> 
  dplyr::mutate(
    data = as.Date(data),
    chuva = as.numeric(chuva),
    temp = as.numeric(temp),
    umid = as.numeric(umid),
    ws = as.numeric(ws)
  ) |>
  glimpse()
Rows: 282
Columns: 4
$ data  <date> 2022-08-01, 2022-08-02, 2022-08-03, 2022-08-04, 2022-08-05, 202…
$ chuva <dbl> 0.0, 0.0, 0.0, 0.0, 0.4, 4.4, 0.0, 6.2, 0.8, 0.0, 0.0, 0.0, 0.0,…
$ temp  <dbl> 26.7, 28.1, 28.0, 26.4, 26.4, 26.2, 28.2, 25.4, 26.7, 25.1, 24.7…
$ ws    <dbl> 1.0, 1.5, 1.2, 1.1, 1.3, 1.2, 1.2, 1.1, 1.4, 2.6, 1.5, 1.1, 1.3,…

Se rodar o comando class(dados_6$temp) o seu resultado será numeric, compatível com o filtro que aplicaremos adiante.

Filtrando variáveis

Agora nós vamos filtrar variáveis com base em seus atributos. Neste caso eu quero casos em que a temperatura esteja acima de 22º C, a precipitação exceda 1 mm e a velocidade do vento seja superior a 1 m/s . Para isso usaremos a função filter() do dplyr.

Dica

É importante notar que estou usando o operador &, que indica que todas essas condições devem ser atendidas simultaneamente. Caso contrário, se usarmos o operador |, o resultado incluirá casos que atendam a pelo menos uma das condições.

# filtrar linhas
filtrado <- dados_6 |> 
  dplyr::filter(
    temp > 22 & 
    chuva > 1 &
    ws > 1
) |> 
  glimpse()
Rows: 46
Columns: 4
$ data  <date> 2022-08-06, 2022-08-08, 2022-08-19, 2022-08-29, 2022-09-11, 202…
$ chuva <dbl> 4.4, 6.2, 19.4, 6.8, 3.6, 8.2, 27.2, 2.0, 9.2, 5.6, 24.4, 28.0, …
$ temp  <dbl> 26.2, 25.4, 22.8, 25.8, 27.4, 26.3, 26.0, 26.7, 27.4, 27.7, 26.5…
$ ws    <dbl> 1.2, 1.1, 2.8, 1.6, 1.8, 2.2, 1.5, 1.5, 1.3, 1.5, 1.7, 1.1, 1.3,…


Eu optei por fazer o processo em etapas e explicar cada uma delas, mas o R permite fazer isso um único comando.

"https://raw.githubusercontent.com/aldanicarvalho/datacleaning/refs/heads/main/PVH_2022-08-01_2023-05-09_Diarios.csv" |> 
read.csv(
         sep = ";",
         skip = 9) |> 
janitor::clean_names() |> 
as_tibble() |> 
dplyr::rename(
    data = data_medicao,
    chuva = precipitacao_total_diario_aut_mm,
    temp = temperatura_media_diaria_aut_c,
    umid = umidade_relativa_do_ar_media_diaria_aut,
    ws = vento_velocidade_media_diaria_aut_m_s
  ) |> 
dplyr::select(
    -x, 
    -umid) |> 
dplyr::mutate(
    data = as.Date(data),
    chuva = as.numeric(chuva),
    temp = as.numeric(temp),
    ws = as.numeric(ws)
  ) |> 
dplyr::filter(
    temp > 22 & 
    chuva > 1 &
    ws > 1
) |> 
glimpse()
Rows: 46
Columns: 4
$ data  <date> 2022-08-06, 2022-08-08, 2022-08-19, 2022-08-29, 2022-09-11, 202…
$ chuva <dbl> 4.4, 6.2, 19.4, 6.8, 3.6, 8.2, 27.2, 2.0, 9.2, 5.6, 24.4, 28.0, …
$ temp  <dbl> 26.2, 25.4, 22.8, 25.8, 27.4, 26.3, 26.0, 26.7, 27.4, 27.7, 26.5…
$ ws    <dbl> 1.2, 1.1, 2.8, 1.6, 1.8, 2.2, 1.5, 1.5, 1.3, 1.5, 1.7, 1.1, 1.3,…


Poderíamos continuar com várias etapas adicionais, como cálculos específicos, filtragens mais avançadas ou até mesmo criar visualizações com o ggplot2. No entanto, deixarei isso para postagens futuras, onde abordarei esses aspectos em detalhes.


Nos vemos na próxima postagem, Aldani👋.

Referências

HORST, A. Repositório do GitHub., 2024. Disponível em: <https://github.com/allisonhorst>

Notas de rodapé

  1. Quando nós usamos o library(tidyverse) ativamos um conjunto de pacotes, inclusive o dplyr() e lubridate():

    dplyr 1.1.3 readr 2.1.4 forcats 1.0.0 stringr 1.5.1 ggplot2 3.4.3 tibble 3.2.1 lubridate 1.9.2 tidyr 1.3.0 purrr 1.0.2↩︎