8 Trabalhando com datas
Datas são um caso a parte no R. Existe uma própria classe para objetos desse tipo, chamada Date
, com D maiúsculo. O R lida com datas no formato AAAA-MM-DD (Ano, Mês e Dia).
Abaixo, definimos um vetor com datas
<- c("2014-07-15", "2018/03/20", "2019-12-31", "20170511")
x as.Date(x)
## [1] "2014-07-15" NA "2019-12-31" NA
class(as.Date(x))
## [1] "Date"
Perceba que o R nativamente não aceita qualquer separador entre o ano, o mês e o dia, apenas o traço. O pacote lubridate
, que faz parte da família tidyverse
, possui uma versão mais generalizável para isso:
library(lubridate)
##
## Attaching package: 'lubridate'
## The following objects are masked from 'package:base':
##
## date, intersect, setdiff, union
::as_date(x) lubridate
## [1] "2014-07-15" "2018-03-20" "2019-12-31" "2017-05-11"
A propósito, dominar o pacote lubridate
, que possui funções muito simples de usar, é a única coisa necessária para saber lidar com datas no R. Por isso, este capítulo se dedica a mostrar as principais funções do pacote.
8.1 Gerar um vetor sequencial de datas
Essa tarefa é feita usando uma função nativa do R chamada seq.Date()
, que possui quatro argumentos principais, sendo que três deles precisam ser especificados.
args(seq.Date)
## function (from, to, by, length.out = NULL, along.with = NULL,
## ...)
## NULL
# gerar vetor de datas separadas por mes
seq.Date(from = as_date("2020-01-01"),
to = as_date("2020-12-01"),
by = "1 month")
## [1] "2020-01-01" "2020-02-01" "2020-03-01" "2020-04-01" "2020-05-01" "2020-06-01" "2020-07-01" "2020-08-01" "2020-09-01"
## [10] "2020-10-01" "2020-11-01" "2020-12-01"
# gerar vetor de datas separadas por dia
seq.Date(from = as_date("2020-01-01"),
to = as_date("2020-01-20"),
by = "1 day")
## [1] "2020-01-01" "2020-01-02" "2020-01-03" "2020-01-04" "2020-01-05" "2020-01-06" "2020-01-07" "2020-01-08" "2020-01-09"
## [10] "2020-01-10" "2020-01-11" "2020-01-12" "2020-01-13" "2020-01-14" "2020-01-15" "2020-01-16" "2020-01-17" "2020-01-18"
## [19] "2020-01-19" "2020-01-20"
# gerar vetor de datas separadas por 3 dias
seq.Date(from = as_date("2020-01-01"),
to = as_date("2020-01-20"),
by = "3 day")
## [1] "2020-01-01" "2020-01-04" "2020-01-07" "2020-01-10" "2020-01-13" "2020-01-16" "2020-01-19"
# gerar um vetor de 7 semanas separados por 1 semana
seq.Date(from = as_date("2020-01-01"),
length.out = 7,
by = "1 week")
## [1] "2020-01-01" "2020-01-08" "2020-01-15" "2020-01-22" "2020-01-29" "2020-02-05" "2020-02-12"
8.2 ‘Parsear’ datas e horários
Para fazer o R converter (ou parsear na linguagem de programação) um string em data, basta usar as funções correspondentes do lubridate.
Por exemplo, no vetor de exemplo x
, definido acima, as datas já estavam definidas no formato correto: AAAA-MM-DD. Aqui no Brasil usamos outro formato: DD/MM/AAAA. O lubridate
possui uma função pronta para essa situação:
# observer como usamos diferentes separadores
<- c("01/12/2019", "20/11/2018", "30011990", "17-03-2000")
datas_brasil # parseando o vetor acima para Data
dmy(datas_brasil)
## [1] "2019-12-01" "2018-11-20" "1990-01-30" "2000-03-17"
Caso o vetor também contenha dados de horário, basta incluir o sufixo referente a hora, minuto e segundo:
dmy_hms("30-09-2019 14:51:39")
## [1] "2019-09-30 14:51:39 UTC"
# sem o segundo
dmy_hm("30-09-2019 14:15")
## [1] "2019-09-30 14:15:00 UTC"
# apenas a hora
dmy_h("30-09-2019 15")
## [1] "2019-09-30 15:00:00 UTC"
8.3 Extrair componentes de uma data
É possível extrair qualquer tipo de componente de uma data ou de um vetor de datas com o lubridate. Veja alguns exemplos:
<- dmy_hms(c("01/12/2019 13:51:15", "20/11/2018 00:00:00", "30011990 080000", "17-03-2000 203000"))
datas_brasil datas_brasil
## [1] "2019-12-01 13:51:15 UTC" "2018-11-20 00:00:00 UTC" "1990-01-30 08:00:00 UTC" "2000-03-17 20:30:00 UTC"
# extrair componentes da data:
# ano
year(datas_brasil)
## [1] 2019 2018 1990 2000
# mes
month(datas_brasil)
## [1] 12 11 1 3
# dia
day(datas_brasil)
## [1] 1 20 30 17
# semana do ano
week(datas_brasil)
## [1] 48 47 5 11
# dia da semana
wday(datas_brasil, label = TRUE)
## [1] dom ter ter sex
## Levels: dom < seg < ter < qua < qui < sex < sáb
# trimestre
quarter(datas_brasil)
## [1] 4 4 1 1
# hora
hour(datas_brasil)
## [1] 13 0 8 20
8.4 Operações matemáticas com datas
Geralmente se está interessado em fazer três tipos de operações matemáticas com datas:
- Adicionar uma quantidade N de dias/meses/anos/etc em uma data:
# adicionar 1 semana nas datas
+ ddays(7) datas_brasil
## [1] "2019-12-08 13:51:15 UTC" "2018-11-27 00:00:00 UTC" "1990-02-06 08:00:00 UTC" "2000-03-24 20:30:00 UTC"
# adicionar 3 meses
+ ddays(90) datas_brasil
## [1] "2020-02-29 13:51:15 UTC" "2019-02-18 00:00:00 UTC" "1990-04-30 08:00:00 UTC" "2000-06-15 20:30:00 UTC"
# adicionar 1 ano
+ dyears(1) datas_brasil
## [1] "2020-11-30 19:51:15 UTC" "2019-11-20 06:00:00 UTC" "1991-01-30 14:00:00 UTC" "2001-03-18 02:30:00 UTC"
- Calcular a diferença de tempo entre duas datas:
No R, subtrair datas segue a mesma sintaxe de subtrair números:
<- dmy_hms("01/09/1993 20:00:00")
data1 <- dmy_hms("24-06-2018 17:00:00")
data2
<- data2 - data1
dif dif
## Time difference of 9061.875 days
Por padrão, o R retorna a diferença em dias, mas em um objeto de classe difftime
.
class(dif)
## [1] "difftime"
Recomenda-se então converter o output para a classe numeric
:
as.numeric(dif)
## [1] 9061.875
Caso se deseje calcular essa diferença em outras unidades de tempo, como meses ou semanas, basta fazer a divisão correspondente:
# conveter para semanas
as.numeric(dif) / 7
## [1] 1294.554
# converter para meses
as.numeric(dif) / 30
## [1] 302.0625
# converter para anos
as.numeric(dif) / 365
## [1] 24.82705
- Arredondar datas:
Para arredondar uma data, por exemplo, retornar o primeiro ou último dia da semana/mês/trimestre/etc de uma data de referência, usa-se as funções ceiling_date()
(arredondar para cima) e floor_date()
(para baixo):
# retornar a primeira data da semana:
floor_date(datas_brasil, "week")
## [1] "2019-12-01 UTC" "2018-11-18 UTC" "1990-01-28 UTC" "2000-03-12 UTC"
# retornar a ultima data do mês
# por padrao, ceiling_date retorna a primeira data do próximo mês,
# por isso é necessario subtrair o resultado por 1
ceiling_date(datas_brasil, "month") - 1
## [1] "2019-12-31 23:59:59 UTC" "2018-11-30 23:59:59 UTC" "1990-01-31 23:59:59 UTC" "2000-03-31 23:59:59 UTC"
# arredondar usando a hora como referencia
floor_date(datas_brasil, "hour")
## [1] "2019-12-01 13:00:00 UTC" "2018-11-20 00:00:00 UTC" "1990-01-30 08:00:00 UTC" "2000-03-17 20:00:00 UTC"