Avsnitt 1, Ämne 1
Startad

Datum, tidpunkter och klockslag

Datum, tidpunkter och klockslag i R

Det är vanligt att arbeta med datum och tider när man gör dataanalys. Datum och tider används också för att studera trender, överlevnad, och mycket mer. Varje dataanalytiker måste kunna hantera datum- och tidsvariabler. Faktum är att datum- och tidsvariabler kan hanteras som numeriska variabler, så att varje datum/tid kan tilldelas ett numeriskt värde, vilket sedan kan användas i olika operationer. För att tilldela ett numeriskt värde till ett visst datum/tidpunkt så måste ett annat datum fungera som referensdatum eller startpunkt. I R är det datumet inställt på 1970-01-01 00:00:00 GMT. Eventuellt datum/tid i framtiden kan sedan beräknas som antalet dagar/timmar/sekunder som har förflutit sedan startpunkten. Självklart kan du ändra referensdatum, men detta är sällan nödvändigt.

För att arbeta med datum och tider som numeriska variabler använder R atomvektorer av klassen POSIXct or POSIXt, som faktiskt är doubles. Även om dessa vektortyper faktiskt är numeriska värden så kan du använda strängar för att definiera dem. Låt oss börja med att skapa två atomvektorer med datum:

# Vi skapar två enkla teckenvektorer
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 states that both vectors are of class character, which we expected. Let’s convert these character vectors to date vectors by using base R functions:

R hävdar att båda vektorerna är av typen character, som vi förväntade oss. Låt oss konvertera dessa teckenvektorer till datumvektorer med hjälp av funktioner som finns i base R (dvs grundfunktionerna i R):

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

Vi kan beräkna tidsskillnaden mellan födelse och död med hjälp av funktionen difftime()

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

5511.000 är tidsskillnaden mellan det första elementet i birth_date (1990-01-01) och det första elementet i death_date (2005-02-02 CET). 3967.000 är tidsskillnaden mellan det andra elementet i birth_date (1999-01-04 CET) och det andra elementet i death_date (2009-11-14 CET), och så vidare.

R has now converted the character strings into date times, with the classes POSIXct and POSIXt. Using POSIXct, each time is represented by the number of seconds that have passed between the time and 12:00 AM January 1st 1970 (in the Universal Time Coordinated (UTC) zone). However, R printed the time differences in days. This is the default setting in R, but you can change that and specify that you desire the time difference in seconds, as follows:

R har konverterat teckensträngarna till datumtider, med klasserna POSIXct och POSIXt. Med hjälp av POSIXct representeras varje datum som antalet sekunder som har passerat sedan klockan 12:00 UTC (Universal Time Coordinated) den 1 januari 1970. Men difftime() beräknar tidsskillnaden i dagar, vilket är en standardinställning. Du kan ändra detta. Om du t ex vill ha tidsskillnad i dagar så skriver man:

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

Observera följande kommando igen:

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

Det framgår av utskriften att R har lagt till tidszoner; CET är centraleuropeisk tid. Detta var något oväntat och faktum är att base R-funktioner för hantering av datum och tider kan vara komplicerade, eller till och med problematiska. Därför skapade Garrett Grolemund, Hadley Wickham och Vitalie Spinu paketet  lubridate , vilket gör hanteringen av datum och tider mycket enkel. Låt oss installera och aktivera paketet:

# Börja med att installera lubridate
install.packages("lubridate")

# Aktivera paketet så att dess funktioner kan användas
library(lubridate)
## Attaching package: 'lubridate'
## The following object is masked from 'package:base':
## 
##     date

Lubridate lagrar datum som antalet dagar sedan 1970-01-01. Du kan få det specifika datumet för 18000 dagar sedan 1970-01-01 med föjande kommande:

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

18000 dagar efter 1970-01-01 hamnar vi på datum 2019-04-04.

Låt oss lagra några datumvärden med lubridate. Det finns många funktioner i lubridate för att göra detta. Principen för användning av dessa funktioner är följande:

  • Ange ordningen för årtal (y), månad (m), dag (d), timme (h), minut (m) och sekunder (s) i datumsträngen.
  • Använd lämplig funktion, vars ordning på elementen passar dina data.

Exempel:

  • Vi har datum med formatet: “1990-01-01”, vilket innebär att formatet är “YYYY-MM-DD”. Ordningen är alltså Y, M, D.
  • Den lämpliga lubridate funktionen heter: ymd().
  • Funktionen ymd() skapar en datumvektor utifrån din sträng.

Låt oss testa det genom att skapa en dataframe med 3 personer, inklusive deras namn, födelsedatum, datum för operation och dödsdatum. Alla datum kommer att förses med olika separatorer för att testa om funktionen ymd() kan förstå olika varianter av datum:

# Skapa våra vektorer (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")

# Combine the vectors into a data frame
my_data <- data.frame(names, birth, operation, death)

# View the 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 ovan så kände R igen de olika datumformerna. Nu ändrar vi ordningen på år, månad och dag. När vi gör detta måste vi ändra funktion, så att vi använder en funktion som förstår i vilken ordning år, månad och dag kommer i strängen:

# Datumsträng med ordningen dag, månad och år
dmy("30-01-2000", "25-12-2001")
## [1] "2000-01-30" "2001-12-25"
# Datumsträng med ordningen månad, dag, år
mdy("12-25-1999", "09-29-2004")
## [1] "1999-12-25" "2004-09-29"
# Datumsträng med ordningen år, månad dag
ymd("20181230", "20191129")
## [1] "2018-12-30" "2019-11-29"

Återigen, R tolkade datumen korrekt. Det finns många fler funktioner i lubridate för att hantera datum. Du kan ladda ner cheat sheet för lubridate.

I nästa exempel kommer vi att lagra ett datum som inkluderar ett klockslag. För att tolka detta korrekt lägger använder vi en funktion som även kan hantera h (timmar), m (minuter) och s (sekunder):

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

You can see that R assigned this to the time zone UTC. R recognizes roughly 600 time zones; each encodes the time zone, daylight savings time, and historical calendar variations for an area. R assigns one time zone per vector. You can get a list of all time zones by executing the following command (only first 100 time zones displayed below):

Du kan se att R tilldelade datumet tidszonen UTC. R kan hantera ungefär 600 tidszoner, för vilka det finns information om tidzonen, sommartid och historiska kalendervariationer för området. R tilldelar en tidszon per vektor. Du kan få en lista över alla tidszoner genom att köra följande kommando (endast de första 20 tidszonerna visas för att spara utrymme):

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"                

Låt oss ange skapa en datumvektor där vi bestämmer tidszonen till US/Stillahavsområdet:

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

Beräkna tidsintervall i R

Låt oss skapa några data med 3 individer och deras födelse- och dödsdatum:

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

# Kombinera vektorer till 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 vill skapa en ny variabel/vektor/kolumn i vår dataframe my_data. Den nya variabeln, som vi kallar dayslived, bör vara tidsskillnaden mellan födelse och dödsdatum.

# Beräkna tidsskillnad genom subtraktion
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 använda funktionen interval() för att definiera ett tidsintervall, som sedan kan användas för olika jämförelser. Låt oss skapa en tidsintervallvariabel och kalla den time_interval:

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

Resultatet blir det samma, vilket du kan kontrollera själv.

Låt oss se om David och Mohammed levde under andra världskriget.

# Definiera start på andra väldskriget:
ww2start    <- ymd_hms("1939-01-01 00:00:00")
# Definiera slut på andra väldskriget:
ww2end      <- ymd_hms("1945-12-31 00:00:00")
# Definiera ett tidsintervall
ww2interval <- interval(ww2start, ww2end)

#Undersök om tidsintervallerna överlappar (dvs om David och Mohammed levde under andra världskriget:
int_overlaps(my_data$time_interval, ww2interval)
## 1  FALSE
## 2  FALSE

Det verkar som om ingen av dem levde under andra världskriget, eftersom resultatet var FALSE för både David och Mohammed.

Durationer

En duration är tidsskillnaden mellan två tidpunkter. Du beräknar durationer med lubridate genom att subtrahera datum, som exemplet visar:

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

Perioder

Du kan lägga till eller subtrahera perioder med hjälp av enkla funktioner, enligt följande:

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"