Datoer, tidspunkter og klokkeslett

Datoer, tidspunkter og klokkeslett i R

Det er vanlig å arbeide med datoer og tider når man gjør dataanalyse. Datoer og tider brukes også til å studere trender, overlevelse og mye mer. Enhver dataanalytiker må kunne håndtere dato- og tidsvariabler. Faktisk kan dato- og tidsvariabler håndteres som numeriske variabler, slik at hver dato/tid kan tildeles en numerisk verdi, som deretter kan brukes i ulike operasjoner. For å tildele en numerisk verdi til en bestemt dato/et bestemt tidspunkt må en annen dato fungere som referansedato eller startpunkt. I R er denne datoen satt til 1970-01-01 00:00:00 GMT. Enhver dato/tid i fremtiden kan deretter beregnes som antall dager/timer/sekunder som har gått siden startpunktet. Selvfølgelig kan du endre referansedatoen, men dette er sjelden nødvendig.

For å arbeide med datoer og tider som numeriske variabler bruker R atomvektorer av klassen POSIXct eller POSIXt, som egentlig er doubles. Selv om disse vektortypene egentlig er numeriske verdier, kan du bruke strenger til å definere dem. La oss begynne med å lage to atomvektorer med datoer:

## Vi lager to enkle tegnvektorer
birth_date <- c("1990-01-01", "1999-01-04", "2002-05-05", "2001-12-12")
death_date <- c("2005-02-02", "2009-11-14", "2018-01-01", "2011-11-09")

class(birth_date)
## [1] "character"
class(death_date)
## [1] "character"

R viser at begge vektorene er av typen character, som vi forventet. La oss konvertere disse tegnvektorene til datovektorer ved hjelp av funksjoner som finnes i base R (dvs. grunnfunksjonene i R):

birth_date <- as.POSIXct(birth_date)
death_date <- as.POSIXct(death_date)
## Se resultat for birth_date
birth_date
## [1] "1990-01-01 CET"  "1999-01-04 CET"  "2002-05-05 CEST" "2001-12-12 CET"
## Se resultat for death_date
death_date
## [1] "2005-02-02 CET" "2009-11-14 CET" "2018-01-01 CET" "2011-11-09 CET"
## Kontroller klasse
class(birth_date)
## [1] "POSIXct" "POSIXt"
## Kontroller klasse
class(death_date)
## [1] "POSIXct" "POSIXt"

Vi kan beregne tidsforskjellen mellom fødsel og død ved hjelp av funksjonen difftime():

difftime(death_date, birth_date)
## Time differences in days
## [1] 5511.000 3967.000 5720.042 3619.000

5511.000 er tidsforskjellen mellom det første elementet i birth_date (1990-01-01) og det første elementet i death_date (2005-02-02 CET). 3967.000 er tidsforskjellen mellom det andre elementet i birth_date (1999-01-04 CET) og det andre elementet i death_date (2009-11-14 CET), og så videre.

R har konvertert tegnstrengene til datotider, med klassene POSIXct og POSIXt. Med POSIXct representeres hver dato som antall sekunder som har gått siden kl. 12:00 UTC (Universal Time Coordinated) den 1. januar 1970. Men difftime() beregner tidsforskjellen i dager, som er en standardinnstilling. Du kan endre dette. Hvis du f.eks. vil ha tidsforskjellen i sekunder, skriver man:

difftime(death_date, birth_date, units="secs")
## Time differences in secs
## [1] 476150400 342748800 494211600 312681600

Se på følgende kommando igjen:

## Resultat for death_date
death_date
## [1] "2005-02-02 CET" "2009-11-14 CET" "2018-01-01 CET" "2011-11-09 CET"

Det fremgår av utskriften at R har lagt til tidssoner; CET er sentraleuropeisk tid. Dette var noe uventet, og faktisk kan base R-funksjoner for håndtering av datoer og tider være kompliserte, eller til og med problematiske. Derfor laget Garrett Grolemund, Hadley Wickham og Vitalie Spinu pakken lubridate , som gjør håndteringen av datoer og tider svært enkel. La oss installere og aktivere pakken:

## Begynn med å installere lubridate
install.packages("lubridate")

## Aktiver pakken slik at funksjonene i den kan brukes
library(lubridate)
## Attaching package: 'lubridate'
## The following object is masked from 'package:base':
##
##     date

Lubridate lagrer datoer som antall dager siden 1970-01-01. Du kan få den spesifikke datoen som ligger 18000 dager etter 1970-01-01 med følgende kommando:

as_date(18000)
## [1] "2019-04-14"

18000 dager etter 1970-01-01 havner vi på datoen 2019-04-04.

La oss lagre noen datoverdier med lubridate. Det finnes mange funksjoner i lubridate for å gjøre dette. Prinsippet for bruken av disse funksjonene er følgende:

  • Angi rekkefølgen for årstall (y), måned (m), dag (d), time (h), minutt (m) og sekunder (s) i datostrengen.
  • Bruk den passende funksjonen, der rekkefølgen på elementene passer til dataene dine.

Eksempel:

  • Vi har datoer med formatet: “1990-01-01”, som innebærer at formatet er “YYYY-MM-DD”. Rekkefølgen er altså Y, M, D.
  • Den passende lubridate-funksjonen heter: ymd().
  • Funksjonen ymd() lager en datovektor ut fra strengen din.

La oss teste det ved å lage en dataframe med 3 personer, inkludert navn, fødselsdato, operasjonsdato og dødsdato. Alle datoene får ulike skilletegn for å teste om funksjonen ymd() kan forstå ulike varianter av datoer:

## Lag vektorene våre (variabler)
names <- c("David", "Mohammed", "Christina")
birth <- ymd("1990-01-01", "1999-01-04", "2002-05-05")
operation <- ymd("1990.01.01", "1999.01.04", "2002.05.05")
death <- ymd("2005/02/02", "2009/11/14", "2018/01/01")

## Kombiner vektorene til en data frame
my_data <- data.frame(names, birth, operation, death)

## Vis data frame
my_data
##       names      birth  operation      death
## 1     David 1990-01-01 1990-01-01 2005-02-02
## 2  Mohammed 1999-01-04 1999-01-04 2009-11-14
## 3 Christina 2002-05-05 2002-05-05 2018-01-01

Som du kan se i utskriften ovenfor, kjente R igjen de ulike datoformene. Nå endrer vi rekkefølgen på år, måned og dag. Når vi gjør dette, må vi bytte funksjon, slik at vi bruker en funksjon som forstår i hvilken rekkefølge år, måned og dag kommer i strengen:

## Datostreng med rekkefølgen dag, måned og år
dmy("30-01-2000", "25-12-2001")
## [1] "2000-01-30" "2001-12-25"
## Datostreng med rekkefølgen måned, dag, år
mdy("12-25-1999", "09-29-2004")
## [1] "1999-12-25" "2004-09-29"
## Datostreng med rekkefølgen år, måned dag
ymd("20181230", "20191129")
## [1] "2018-12-30" "2019-11-29"

Igjen tolket R datoene korrekt. Det finnes mange flere funksjoner i lubridate for å håndtere datoer. Du kan laste ned cheat sheet for lubridate.

I neste eksempel skal vi lagre en dato som inkluderer et klokkeslett. For å tolke dette korrekt bruker vi en funksjon som også kan håndtere h (timer), m (minutter) og s (sekunder):

ymd_hms("2011-06-04 12:00:00")
## [1] "2011-06-04 12:00:00 UTC"

Du kan se at R tildelte datoen tidssonen UTC. R kan håndtere omtrent 600 tidssoner, og for hver av dem finnes det informasjon om tidssonen, sommertid og historiske kalendervariasjoner for området. R tildeler én tidssone per vektor. Du kan få en liste over alle tidssoner ved å kjøre følgende kommando (bare de første 20 tidssonene vises for å spare plass):

OlsonNames()
##   [1] "Africa/Abidjan"                   "Africa/Accra"
##   [3] "Africa/Addis_Ababa"               "Africa/Algiers"
##   [5] "Africa/Asmara"                    "Africa/Asmera"
##   [7] "Africa/Bamako"                    "Africa/Bangui"
##   [9] "Africa/Banjul"                    "Africa/Bissau"
##  [11] "Africa/Blantyre"                  "Africa/Brazzaville"
##  [13] "Africa/Bujumbura"                 "Africa/Cairo"
##  [15] "Africa/Casablanca"                "Africa/Ceuta"
##  [17] "Africa/Conakry"                   "Africa/Dakar"
##  [19] "Africa/Dar_es_Salaam"             "Africa/Djibouti"

La oss lage en datovektor der vi setter tidssonen til US/Stillehavsområdet:

ymd_hms("2011-06-04 12:00:00", tz="US/Pacific")
## [1] "2011-06-04 12:00:00 PDT"

Beregne tidsintervaller i R

La oss lage noen data med 3 individer og deres fødsels- og dødsdatoer:

## Lag vektorer
names <- c("David", "Mohammed")
birth <- ymd("1990-01-01", "1999-01-04")
death <- ymd("2005/02/02", "2009/11/14")

## Kombiner vektorer til dataframe
my_data <- data.frame(names, birth, death)

## Se dataframe
my_data
##      names      birth      death
## 1    David 1990-01-01 2005-02-02
## 2 Mohammed 1999-01-04 2009-11-14

Vi vil lage en ny variabel/vektor/kolonne i vår dataframe my_data. Den nye variabelen, som vi kaller dayslived, skal være tidsforskjellen mellom fødsels- og dødsdato.

## Beregn tidsforskjell ved subtraksjon
my_data$dayslived <- my_data$death-my_data$birth

## Se data
my_data
##      names      birth      death dayslived
## 1    David 1990-01-01 2005-02-02 5511 days
## 2 Mohammed 1999-01-04 2009-11-14 3967 days

Vi kan bruke funksjonen interval() til å definere et tidsintervall, som deretter kan brukes til ulike sammenligninger. La oss lage en tidsintervallvariabel og kalle den time_interval:

my_data$time_interval <- interval(my_data$birth, my_data$death)
my_data

Resultatet blir det samme, noe du kan kontrollere selv.

La oss se om David og Mohammed levde under andre verdenskrig.

## Definer start på andre verdenskrig:
ww2start    <- ymd_hms("1939-01-01 00:00:00")
## Definer slutt på andre verdenskrig:
ww2end      <- ymd_hms("1945-12-31 00:00:00")
## Definer et tidsintervall
ww2interval <- interval(ww2start, ww2end)

#Undersøk om tidsintervallene overlapper (dvs. om David og Mohammed levde under andre verdenskrig:
int_overlaps(my_data$time_interval, ww2interval)
## 1  FALSE
## 2  FALSE

Det ser ut til at ingen av dem levde under andre verdenskrig, siden resultatet var FALSE for både David og Mohammed.

Varigheter

En varighet er tidsforskjellen mellom to tidspunkter. Du beregner varigheter med lubridate ved å subtrahere datoer, slik eksempelet viser:

ymd("2018-01-01") - ymd("1999-01-04")
## Time difference of 6937 days

Perioder

Du kan legge til eller trekke fra perioder ved hjelp av enkle funksjoner, slik:

ymd(20110101) + years(1)
## [1] "2012-01-01"
ymd(20110101) + months(12)
## [1] "2012-01-01"
ymd(20110101) - days(2)
## [1] "2010-12-30"
ymd(20110101) - seconds(2000)
## [1] "2010-12-31 23:26:40 UTC"