Trabalhando com Datas no R

Artigo escrito com a colaboração de Erick Araújo

As datas são objetos frequentes e importantes quando se trabalha com análise de dados. Saber lidar com o seu manuseio é de grande importancia para o trabalho do analista. Esse documento tem como objetivo reunir informações e nortear o leitor quanto as várias possibilidades de manipulação de objetos desse tipo.

O R Base possui algumas funções que permitem a manipulação e o tratamento de objetos do tipo data, porém em alguns contextos, essas funções apresentam limitações e o seu uso é pouco intuitivo. Graças ao Jedi do R Hadley Wickham, essas limitações podem ser contornadas facilmente com o auxílio do pacote lubridate.

O lubridate é um pacote do ecossistema Tidyverse, e talvez o pacote mais completo para se trabalhar com datas no R. Nesse artigo, abordaremos suas principais aplicações, para isso, vamos utilizar um banco de dados com três diferentes formatos de datas e observar como algumas funções se comportam.

Pacotes

library(tidyverse) # Principal pacote do ecossistema tidyverse, usado para diversas manipulações.
library(rhandsontable) # Pacote utilizado para construção de tabelas.
library(lubridate) # Pacote utilizado para manipulação de datas 
                   # (Após o carregamento do tidyverse, não é necessário carregar o lubridate novamente)

Lubridate

as_date()

dados %>% 
  mutate(formato_1 = as_date(formato_1),
         formato_2 = as_date(formato_2),
         formato_3 = as_date(formato_3))
## # A tibble: 5 x 3
##   formato_1  formato_2 formato_3
##   <date>     <date>    <date>   
## 1 2009-02-09 NA        NA       
## 2 2009-02-09 NA        NA       
## 3 2009-02-09 NA        NA       
## 4 2009-02-09 NA        NA       
## 5 2018-04-02 NA        NA

O as_date() é o comando mais básico para se transformar um objeto em uma data no lubridate. Podemos observar que para a nossa primeira variável, a transformação acontece de maneira direta como o esperado.

Para os dois outros casos a função não reconhece os formatos fornecidos dentro dos objetos, retornando um valor ausente.

Para o lubridate, lidar com estruturas pouco usuais de datas não é um problema, e o objetivo de transformação pode ser alcançado com poucas linhas de código:

dados %>% 
  mutate(formato_1 = as_date(formato_1),
         formato_2 = my(formato_2),
         formato_3 = dmy(formato_3))
## # A tibble: 5 x 3
##   formato_1  formato_2 formato_3 
##   <date>     <date>    <date>    
## 1 2009-02-09 NA        2009-02-09
## 2 2009-02-09 NA        2009-02-09
## 3 2009-02-09 NA        2009-02-09
## 4 2009-02-09 NA        2009-02-09
## 5 2018-04-02 NA        2018-04-02

Erro!

O Lubridate possui algumas funções para especificar o formato em que o nosso objeto tipo data foi disposto. Essas funções são:

dmy(), mdy(), myd(), ymd(), ydm(), onde “d”, “m”, “y”, representam o dia, mês e ano respectivamente. Basta especificar a ordem do objeto em questão. Também podemos trabalhar com datas abreviadas como é o caso da coluna ‘formato_2’ do nosso conjunto de dados. Porém o comando reconhecerá apenas a abreviação escrita em inglês.

exemplo4 <- c('feb/2019')

exemplo4 %>% my()
## [1] "2019-02-01"
exemplo5 <- c('February/2019')

exemplo5 %>% my()
## [1] "2019-02-01"

Vamos fazer a tradução do nosso conjunto de dados e aplicar a função para ver seu funcionamento:

dados2
## # A tibble: 5 x 3
##   formato_1  formato_2 formato_3
##   <chr>      <chr>     <chr>    
## 1 2009-02-09 feb/2009  09022009 
## 2 2009-02-09 feb/2009  09022009 
## 3 2009-02-09 feb/2009  09022009 
## 4 2009-02-09 feb/2009  09022009 
## 5 2018-04-02 apr/2018  02042018
dados2 %>% 
  mutate(formato_1 = as_date(formato_1),
         formato_2 = my(formato_2),
         formato_3 = dmy(formato_3))
## # A tibble: 5 x 3
##   formato_1  formato_2  formato_3 
##   <date>     <date>     <date>    
## 1 2009-02-09 2009-02-01 2009-02-09
## 2 2009-02-09 2009-02-01 2009-02-09
## 3 2009-02-09 2009-02-01 2009-02-09
## 4 2009-02-09 2009-02-01 2009-02-09
## 5 2018-04-02 2018-04-01 2018-04-02

Agora nossas três variáveis foram definidas como data corretamente. É muito comum também, em alguns cenários, lidarmos com datas cuja precisão abrange até os segundos, para isso, existem também, no lubridate, funções para trabalhar com datas no formato dttm:

# criando um objeto data com precisão de segundos, objeto dttm:

data_dttm <- c('2009-02-09, 17:12:53')

ymd_hms(data_dttm)
## [1] "2009-02-09 17:12:53 UTC"

É possível também permutar as letras para outras combinações de data e hora. Exemplo: dmy_hms(), ymd_hms() e etc…

Extraindo valores

Extrair valores com o lubridate é bem simples, pois existem funções específicas para cada categoria, vejamos abaixo um exemplo de extração do ano:

dados2 %>% 
  mutate(formato_1 = as_date(formato_1),
         formato_2 = my(formato_2),
         formato_3 = dmy(formato_3),
         ano = year(formato_1))
## # A tibble: 5 x 4
##   formato_1  formato_2  formato_3    ano
##   <date>     <date>     <date>     <dbl>
## 1 2009-02-09 2009-02-01 2009-02-09  2009
## 2 2009-02-09 2009-02-01 2009-02-09  2009
## 3 2009-02-09 2009-02-01 2009-02-09  2009
## 4 2009-02-09 2009-02-01 2009-02-09  2009
## 5 2018-04-02 2018-04-01 2018-04-02  2018

Funções úteis

second() – extrai os segundos.

minute() – extrai os minutos.

hour() – extrai a hora.

wday() – extrai o dia da semana.

mday() – extrai o dia do mês.

month() – extrai o mês.

year() – extrai o ano.

Fuso horário

Existem duas principais funções para se trabalhar com fuso horário no lubridate, with_tz() e force_tz(). Vejamos um exemplo de como usa-la:

# função now(), retorma o momento exato em que o código for executado

exemplo_fuso <- now()

exemplo_fuso
## [1] "2022-03-23 16:14:08 -03"
# Devolve qual seria a data em outro fuso

with_tz(exemplo_fuso, tz = "America/New_York")
## [1] "2022-03-23 15:14:08 EDT"
# Altera o fuso sem mudar o horário

force_tz(exemplo_fuso, tz = "America/New_York")
## [1] "2022-03-23 16:14:08 EDT"

Operações com datas

A função today() retorna um objeto data com os valores do dia em que o código for executado. Vamos criar um vetor com essa função para observar algumas operações:

dados2 <- dados2 %>% 
  mutate(formato_1 = as_date(formato_1),
         formato_2 = my(formato_2),
         formato_3 = dmy(formato_3),
         ano = year(formato_1),
         hoje = today())

dados2
## # A tibble: 5 x 5
##   formato_1  formato_2  formato_3    ano hoje      
##   <date>     <date>     <date>     <dbl> <date>    
## 1 2009-02-09 2009-02-01 2009-02-09  2009 2022-03-23
## 2 2009-02-09 2009-02-01 2009-02-09  2009 2022-03-23
## 3 2009-02-09 2009-02-01 2009-02-09  2009 2022-03-23
## 4 2009-02-09 2009-02-01 2009-02-09  2009 2022-03-23
## 5 2018-04-02 2018-04-01 2018-04-02  2018 2022-03-23

Assim podemos fazer uma subtração direta entre os vetores (Ex: hoje – formato_1), já que estão no formato padrão de datas no R. Ou usar também usar a função interval() que salva o intervalo entre duas datas em um objeto.

dados2 %>% 
  mutate(diferenca = hoje - formato_1)
## # A tibble: 5 x 6
##   formato_1  formato_2  formato_3    ano hoje       diferenca
##   <date>     <date>     <date>     <dbl> <date>     <drtn>   
## 1 2009-02-09 2009-02-01 2009-02-09  2009 2022-03-23 4790 days
## 2 2009-02-09 2009-02-01 2009-02-09  2009 2022-03-23 4790 days
## 3 2009-02-09 2009-02-01 2009-02-09  2009 2022-03-23 4790 days
## 4 2009-02-09 2009-02-01 2009-02-09  2009 2022-03-23 4790 days
## 5 2018-04-02 2018-04-01 2018-04-02  2018 2022-03-23 1451 days
dados2 %>% 
  mutate(intervalo = interval(formato_1, hoje)) %>% select(intervalo)
## # A tibble: 5 x 1
##   intervalo                     
##   <Interval>                    
## 1 2009-02-09 UTC--2022-03-23 UTC
## 2 2009-02-09 UTC--2022-03-23 UTC
## 3 2009-02-09 UTC--2022-03-23 UTC
## 4 2009-02-09 UTC--2022-03-23 UTC
## 5 2018-04-02 UTC--2022-03-23 UTC

Vamos definir um intervalo com o operador %–%, e ainda verificar se existe uma intersecção com a função int_overlaps().

intervalo_1 <- dmy("09-02-2009") %--% dmy("09-02-2010")  

intervalo_2 <- dmy("09-08-2009") %--% dmy("09-08-2010")  

int_overlaps(intervalo_1, intervalo_2)
## [1] TRUE

Duração de um intervalo

dados2 %>% 
  mutate(intervalo = interval(formato_1, hoje),
         duracao_dias = intervalo/ddays()) %>% select(intervalo, duracao_dias)
## # A tibble: 5 x 2
##   intervalo                      duracao_dias
##   <Interval>                            <dbl>
## 1 2009-02-09 UTC--2022-03-23 UTC         4790
## 2 2009-02-09 UTC--2022-03-23 UTC         4790
## 3 2009-02-09 UTC--2022-03-23 UTC         4790
## 4 2009-02-09 UTC--2022-03-23 UTC         4790
## 5 2018-04-02 UTC--2022-03-23 UTC         1451

Além das funções citadas o pacote lubridate oferece várias outras opções de manipulação e manuseio de datas. Visite a documentação do pacote clicando AQUI.

Deixe um comentário

O seu endereço de e-mail não será publicado.