Introdução à Ciência de Dados no R


Aula 08 - Manipulação Avançada

Aula 08

Antonio Vinícius Barbosa

26-03-2024


Formatando Dados

Manipulação de Dados

Nesta parte, veremos mais alguns pacotes importantes para a manipulação de dados no R:

  • lubridate: pacote para manipular variáveis contendo datas.
  • stringr: manipulação de variáveis de texto (characters ou strings).
  • forcats: manipulação de fatores.

Manipulando datas

Manipulando datas no R

Em muitas situações, é necessário manipular informações que contêm datas a fim de capturar, por exemplo, o intervalo de tempo entre dois eventos ou a dinâmica temporal de uma variável.

O pacote lubridate possui diversas funções que facilitam a manipulação de datas.

Foi criado por Garrett Grolemund e Hadley Wickham e faz parte do conjunto de pacotes do tidyverse. Ver documentação oficial.

Manipulando datas no R

Nesta seção, veremos como:

  • Transformar e extrair datas
  • Aprender funções básicas para a manipulação de datas
  • Realizar operações com datas

A classe Date

Variáveis que contêm datas são tratadas como um tipo especial de objeto, da classe Date. Para criar um objeto dessa classe, fazemos:

# Criar data
data_char <- c("31/12/2021", "01/01/2022")
class(data_char)
## [1] "character"

# Usando a funcao as.Date()
data_date <- as.Date(data_char)
class(data_date)
## [1] "Date"
data_date
## [1] "31-12-20" "1-01-20"

A função as.Date() transforma objetos na classe Date, porém com um valor inesperado. Tal função se ajusta apenas para datas do tipo yyyy-mm-dd.

O pacote lubridate

Para lidar com datas do tipo dd-mm-yyyy, o pacote lubridate oferece a função dmy() (day, month, year):

# Criar data
data_char <- c("31/12/2021", "01/01/2022")

# Usando a funcao dmy()
data <- dmy(data_char)
class(data)
## [1] "Date"
data
## [1] "2021-12-31" "2022-01-01"

Para os demais ordenações de datas, o pacote oferece as variações dym(), mdy(),
myd(), ymd() e ydm().

Formatos de datas ao redor do mundo

O pacote lubridate

Podemos transformar diversos formatos para a classe Date:

# Datas com diferentes formatos
dmy(31122019) # numerico
## [1] "2019-12-31"
dmy("31122019") # character
## [1] "2019-12-31"
dmy("31/12/2019") # separado por "/"
## [1] "2019-12-31"
dmy("31.12.2019") # separado por "."
## [1] "2019-12-31"

O pacote lubridate

Além de datas, podemos adicionar as horas. Para isso, basta identificar a ordem do year(y), month(m), day(d), hour(h), minute(m) e second(s)

# Datas e horarios
ymd_h("2020020515")
## [1] "2020-02-05 15:00:00 UTC"
ymd_hm("202002051531")
## [1] "2020-02-05 15:31:00 UTC"
ymd_hms("20200205153140")
## [1] "2020-02-05 15:31:40 UTC"

O pacote lubridate

Para extrair informações instantâneas do sistema, fazemos:

# Data atual
today()
## [1] "2024-03-26"
now()
## [1] "2024-03-26 11:24:47 -03"

O último bloco de informações da função now() corresponde ao fuso horário.

O pacote lubridate

Há diversas funções para extrair informações de um objeto da classe Date:

hora_atual <- now()
hora_atual
## [1] "2024-03-26 11:24:47 -03"
# Extrair data
date(hora_atual)
## [1] "2024-03-26"
# Extrair ano
year(hora_atual)
## [1] 2024
# Extrair mes
month(hora_atual)
## [1] 3
# Extrair dia do mes
day(hora_atual)
## [1] 26
# Extrair hora
hour(hora_atual)
## [1] 11
# Extrair minutos
minute(hora_atual)
## [1] 24
# Extrair segundos
second(hora_atual)
## [1] 47.46304

O pacote lubridate

Outras informações de um objeto da classe Date:

# Extrair dia da semana
wday(hora_atual, label = TRUE)
## [1] Tue
## Levels: Sun < Mon < Tue < Wed < Thu < Fri < Sat

Outras informações:

Operações com datas

Intervalos de datas são realizados areavés da função interval()

# Datas
data_inic <- ymd("2023-04-08")
data_fim <- ymd("2023-06-16")

# Intervalo de datas
periodo <- interval(data_inic, data_fim)
periodo
## [1] 2023-04-08 UTC--2023-06-16 UTC

# Outra notação (operador intervalo %--%)
periodo <- data_inic %--% data_fim
periodo
## [1] 2023-04-08 UTC--2023-06-16 UTC

evento <- ymd("2023-12-10")
evento %within% periodo
## [1] FALSE

Operações com datas

Algumas operações aritméticas disponíveis são:

# Adição de datas
today() + days(5)
## [1] "2024-03-31"
today() + years(2)
## [1] "2026-03-26"
# Datas recorrentes
aulas <- today() + weeks(1:2) 
aulas
## [1] "2024-04-02" "2024-04-09"
# Diferença de datas
as.period(periodo); as.period(periodo, unit = "day")
## [1] "2m 8d 0H 0M 0S"
## [1] "69d 0H 0M 0S"

Datas em R

  • Outras classes de datas no R são POSIXct e POSIXlt.
  • A classe POSIXct é útil para datas que contenham horas.
  • A classe POSIXlt facilita a extração de componentes da data.
  • O pacote lubridate é um wrapper para manipular as duas classes, com uma sintaxe mais simples e intuitiva.
  • Para mais informações, ver a ajuda das funções https://lubridate.tidyverse.org

Quizz #1

  1. Utilize a função do lubridate apropriada para analisar cada uma das seguintes datas:
d1 <- "January 20, 2020"
d2 <- "2020-Abril-01"
d3 <- "11-Nov-2020"
d4 <- c("July 13 (1969)", "August 23 (1972)", "July 1 (1975)")
d5 <- "2008/13/10" 
  1. Precisamente, qual a sua idade agora? Calcule a idade em anos, meses, semanas, dias, horas e minutos.

Quizz #2

Para este exercício, será necessário utilizar a base dados::voos

  1. Observar a estrutura de dados utilizando glimpse().
  2. Criar uma variável informando a velocidade média (km/h) do voo utilizando as variáveis distancia e tempo_voo (medida em minutos).
  3. Construa a variável com a data e hora exata da decolagem.
  4. Reporte a hora de chegada relativa ao local de partida.
  5. Criar um banco apenas com dados dos voos atrasados.

Strings (ou variáveis de texto)

Variáveis de texto

  • Outra classe importante são as variáveis character (ou strings).
  • Muitas vezes, é difícil manipular strings devido a existência de diversas funções com diferentes argumentos.
  • Neste sentido, o pacote stringr traz uma sintaxe mais consistente e simples para manipular tais variáveis.

As funções do stringr

# Instalar e carregar pacote 
install.packages("stringr")
library(stringr)
  • O pacote também faz parte do tidyverse
  • As funções de manipulação de texto começam com str_
  • Para listar todas as funções disponíveis, basta digitar stringr::str_ e visualizar todas as funções com este prefixo

As funções do stringr

Algumas funções básicas para manipulação de caracteres:

# Numero de caracteres
str_length("João Pessoa")
## [1] 11

# Minusculas
str_to_lower("João Pessoa")
## [1] "joão pessoa"

# Maiusculas
str_to_upper("João Pessoa")
## [1] "JOÃO PESSOA"

# Iniciais maiusculas
str_to_title("joão pessoa")
## [1] "João Pessoa"

As funções do stringr

# Extrair por posicao
str_sub("João Pessoa", start = 1, end = 4)
## [1] "João"

# Extrair por padrao
cidades <- c("Sapé", "Sumé", "Cuité", "Santa Rita")

# Detectar
str_detect(cidades, "Sa")
## [1]  TRUE FALSE FALSE  TRUE

# Subconjunto
str_subset(cidades, "Sa")
## [1] "Sapé"       "Santa Rita"

As funções do stringr

# Variavel sexo
sexo_quest <- c("M", "F", " M", "F ", " M ")
sexo_quest
## [1] "M"   "F"   " M"  "F "  " M "

# Remover espacos em branco
sexo <- str_trim(sexo_quest)
sexo
## [1] "M" "F" "M" "F" "M"

# Remover espacos em branco em qualquer parte
str_squish("  Este   texto está   com espaços  ")
## [1] "Este texto está com espaços"

# Concatenar strings
pre <- "O status é:"
status <- "APROVADO"
str_c(pre, status, sep = " ")
## [1] "O status é: APROVADO"

# Excluir padrões
id_var <- c("id1", "id2", "id3")
str_replace(id_var, "id", "")
## [1] "1" "2" "3"

As funções do stringr

Para dividir elementos de uma string baseada em um caractere específico, utilizamos a função str_split():

# Inserir texto
texto <- c("Lorem ipsum dolor sit amet")

# Dividir string (em lista)
str_split(texto, " ")
## [[1]]
## [1] "Lorem" "ipsum" "dolor" "sit"   "amet"

# Dividir string (em matriz)
str_split(texto, " ", simplify = TRUE)
##      [,1]    [,2]    [,3]    [,4]  [,5]  
## [1,] "Lorem" "ipsum" "dolor" "sit" "amet"

As funções do stringr

Para adicionar caracteres e ajustar em um tamanho fixo, utilizamos a função str_pad()

# CNPJ numerico
cnpj_bb <- 00000000000191
cnpj_bb
## [1] 191

# Ajustar CNPJ
str_pad(cnpj_bb, width = 14, side = "left", pad = 0)
## [1] "00000000000191"

Documentação oficial

Quizz #3

Exercício 1

O CPF é um número composto por 11 dígitos. Por exemplo, 54491651884. No entanto, para facilitar a visualização, costumamos mostrá-lo com separadores a cada 3 casas: 544.916.518-84. Como obter esse padrão utilizando unicamente as funções do pacote stringr?

Exercício 2

Suponha que tenhamos o seguinte endereço em uma URL: https://www.ibge.gov.br/cidades-e-estados/pb/campina-grande.html Transforme o endereço no formato identificador Campina Grande (PB)

O pacote forcats

Fatores

Até o momento, vimos a existência de objetos da classe factor. De forma geral:

  • Representam uma forma prática de lidar com variáveis categorizadas, tanto para fins de modelagem quanto para fins de visualização.

Fatores

  • As principais funções do pacote forcats auxiliam na reordenação das categorias e na modificação dos níveis de um fator.

  • Fatores são estruturas de dados utilizadas para ordenar strings. Formalmente, um fator é definido como um vetor de integers com dois atributos específicos:

    • levels: vetor de strings que indica a relação de ordem entre as variáveis.
    • class: a string atômica factor.

Variáveis categóricas

Suponha um vetor com as disciplinas preferidas dos alunos em uma dado semestre:

disciplinas <- c("micro", "macro", "econometria", "macro", 
                 "micro", "brasileira", "macro", "econometria", 
                 "micro", "brasileira", "macro", "micro")
class(disciplinas)
## [1] "character"

Para transformar o objeto em fator, fazemos:

disciplinas <- factor(disciplinas)
class(disciplinas)
## [1] "factor"
str(disciplinas)
##  Factor w/ 4 levels "brasileira","econometria",..: 4 3 2 3 4 1 3 2 4 1 ...
levels(disciplinas)
## [1] "brasileira"  "econometria" "macro"       "micro"

Variáveis categóricas

Fatores são estruturas úteis que permitem ter maior controle durante a análise dos dados:

disciplinas <- factor(disciplinas, 
                      levels = c("micro","macro", "econometria", 
                                 "brasileira"))
str(disciplinas)
##  Factor w/ 4 levels "micro","macro",..: 1 2 3 2 1 4 2 3 1 4 ...
levels(disciplinas)
## [1] "micro"       "macro"       "econometria" "brasileira"

O pacote forcats

Para entender as funcionalidades do pacote forcats, utilizaremos o banco de dados airquality:

tibble::glimpse(airquality)
## Rows: 153
## Columns: 6
## $ Ozone   <int> 41, 36, 12, 18, NA, 28, 23, 19, 8, NA, 7, 16, 11, 14, 18, 14, …
## $ Solar.R <int> 190, 118, 149, 313, NA, NA, 299, 99, 19, 194, NA, 256, 290, 27…
## $ Wind    <dbl> 7.4, 8.0, 12.6, 11.5, 14.3, 14.9, 8.6, 13.8, 20.1, 8.6, 6.9, 9…
## $ Temp    <int> 67, 72, 74, 62, 56, 66, 65, 59, 61, 69, 74, 69, 66, 68, 58, 64…
## $ Month   <int> 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,…
## $ Day     <int> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,…

O pacote forcats

Estamos interessados em mudar os níveis de um fator:

airquality$Month <- as.factor(airquality$Month)
levels(airquality$Month)
## [1] "5" "6" "7" "8" "9"

Podemos renomear os levels através da função fct_recode():

airquality$Month <- fct_recode(airquality$Month, 
                               "Mai" = "5", "Jun" = "6", 
                               "Jul" = "7", "Ago" = "8", 
                               "Set" = "9")
levels(airquality$Month)
## [1] "Mai" "Jun" "Jul" "Ago" "Set"

O pacote forcats

É possível mudar a ordem em que os levels são apresentados:

airquality$Month <- fct_relevel(airquality$Month, 
                                'Jul', 'Ago', 'Jun', 
                                'Set', 'Mai')
levels(airquality$Month)
## [1] "Jul" "Ago" "Jun" "Set" "Mai"

O pacote forcats

Outra função bastante útil para agrupar categorias é a fct_lump. Considere o seguinte vetor:

letras <- factor(sample(letters[1:10], 100, replace = TRUE))
fct_count(letras)
## # A tibble: 10 × 2
##    f         n
##    <fct> <int>
##  1 a        11
##  2 b        10
##  3 c         8
##  4 d         2
##  5 e        10
##  6 f        13
##  7 g         8
##  8 h         5
##  9 i        17
## 10 j        16

O pacote forcats

A função fct_lump() utiliza o level de menor frequência e categoriza como “Outros”

fct_lump(letras, other_level = "Outros") |>        
  fct_count()
## # A tibble: 9 × 2
##   f          n
##   <fct>  <int>
## 1 a         11
## 2 b         10
## 3 c          8
## 4 e         10
## 5 f         13
## 6 g          8
## 7 i         17
## 8 j         16
## 9 Outros     7

O pacote forcats

Ainda, podemos definir o número de categorias e agregar as demais em “Outros”

fct_lump(letras, n = 4, other_level = "Outros") |>        
  fct_count()
## # A tibble: 5 × 2
##   f          n
##   <fct>  <int>
## 1 a         11
## 2 f         13
## 3 i         17
## 4 j         16
## 5 Outros    43