Objekter (R Objects)

Objekter i R

R bruger objekter til at lagre information. Her er et simpelt objekt, som kun lagrer den numeriske værdi 1:

my_number <- 1

Vi har oprettet et objekt med navnet my_number og tildelt det værdien 1. Tildelingen af værdien 1 blev foretaget med symbolerne <-, som kaldes the assignment operator, hvilket på dansk bliver tildelingsoperator. Man siger, at my_number får værdien 1. Nu indeholder objektet my_number information i form af en numerisk værdi. Lad os spørge R, hvilken type objekt my_number er:

class(my_number)
[1] "numeric"

Ifølge ovenstående tolker R my_number som et numerisk objekt, hvilket virker rimeligt. Lad os gennemføre samme procedure med en tekststreng i stedet:

my_string <- "Hej! Mitt namn är Salvador."
class(my_string)
[1] "character"

Objektet my_string er et character-objekt, hvilket betyder, at det består af tegn og symboler. Disse to eksempler viser, at i det øjeblik vi opretter et objekt, vil R forsøge at gætte, hvilken type information objektet indeholder. Lad os se, hvordan R tolker en numerisk værdi omgivet af anførselstegn:

my_object <- "1"
class(my_object)
[1] "character"

R tolker my_object som en tegnstreng (character-objekt), hvilket forklares af, at tallet 1 var omsluttet af anførselstegn, hvilket betyder, at R antager, at det er en tegnstreng, vi vil lagre.

Al information, som du lagrer i dit Environment, er et objekt. Eksempler på objekter er følgende:

  • Tabeller (dataframes) er objekter.
  • Gemte enkeltværdier (som eksempelvis my_object ovenfor) er et objekt.
  • Resultater fra regressionsmodeller er objekter.

I princippet er alt, hvad du opretter i R, et objekt. Nedenfor gennemgår vi forskellige typer objekter i R.

4.1 Atomic Vectors (Atomvektorer)

Den simpleste type objekt i R er en atomic vector (atomvektor). Atomic vectors bruges altid, når du arbejder i R. Lad os oprette en atomvektor ved hjælp af funktionen [c()](https://rdrr.io/r/base/c.html). Denne funktion kombinerer flere elementer til en vektor. Vi navngiver objektet my_first_vector, og det kommer til at indeholde seks numeriske værdier:

my_first_vector <- c(1, 2, 3, 4, 5, 6)

Vi kan kontrollere, om R betragter my_first_vector som en atomic vector, ved at bruge funktionen [is.vector()](https://rdrr.io/r/base/vector.html):

## is.vector() kontrollerer, om et objekt er en atomic vector
is.vector(my_first_vector)
[1] TRUE

Funktionen [is.vector()](https://rdrr.io/r/base/vector.html) returnerede værdien TRUE, hvilket betyder, at my_first_vector er en atomic vector. Da my_first_vector kun indeholder numeriske værdier, vil R betragte den som en numerisk vektor, hvilket man kan kontrollere ved hjælp af funktionen [is.numeric()](https://rdrr.io/r/base/numeric.html):

## is.numeric() kontrollerer, om en atomic vector er numerisk
is.numeric(my_first_vector)
[1] TRUE

Atomic vectors har kun én dimension. Hver vektor kan kun lagre én type data. For at håndtere alle typer data findes der derfor seks grundlæggende typer atomic vectors:

  • double: numeriske værdier med eller uden decimaler
  • integer: numeriske heltal (ingen decimaler)
  • character: tegn, symboler, tekst
  • logical: JA/NEJ, 0/1, TRUE/FALSE
    • Synonym: logiske værdier (da), boolean (eng), booleske værdier (da).
  • complex og raw vectors findes, men bruges i princippet aldrig.
my_doubles <- c(1.2, 2.4, 32.1)

my_integers <- c(1L, 2L, 3L)

my_characters <- c("A", "B", "Hello", "My phone is dead")

my_logicals <- c(TRUE, TRUE, FALSE, TRUE, FALSE)

Du kan kontrollere, om en vektor er en af ovenstående, ved at bruge funktionerne [is.double()](https://rdrr.io/r/base/double.html), [is.numereric()](https://rdrr.io/r/base/numeric.html), [is.character()](https://rdrr.io/r/base/character.html), [is.logical()](https://rdrr.io/r/base/logical.html). Disse funktioner returnerer værdien TRUE eller FALSE.

Hvis du har brug for at kontrollere, hvilken type vektor et objekt er, kan du bruge funktionen [typeof()](https://rdrr.io/r/base/typeof.html). Nedenfor opretter vi en numerisk vektor med decimaler, og derefter spørger vi, hvilken klasse og type vektoren har.

my_doubles <- c(1.2, 2.4, 32.1)
class(my_doubles)
[1] "numeric"
typeof(my_doubles)
[1] "double"

4.1.0.1 Vektorers længde

Længden af en vektor er ganske enkelt antallet af elementer i den. Lad os oprette en atomvektor med 5 numeriske værdier og kontrollere dens længde:

my_values <- c(1, 2, 3, 4, 5)
length(my_values)
[1] 5

Lad os oprette en vektor med en lang streng for at kontrollere længden:

my_string <- c("Det är roligt att lära sig R!")
length(my_string)
[1] 1

Længden af denne vektor var 1, fordi den indeholder 1 element, nemlig sætningen “Det är roligt att lära sig R!”. Lad os oprette en vektor med to tekststrenge:

my_string <- c("Det är roligt att lära sig R!", "Det kommer ta en vecka att lära sig R")
length(my_string)
[1] 2

Nu har my_string 2 tekststrenge, og derfor har vektoren længden 2.

En atomic vector kan kun lagre én type data. Lad os teste dette ved at oprette en vektor med både numeriske værdier, tekststrenge og logiske værdier.

## Opret en vektor med tekststrenge, numeriske værdier og booleske værdier
mixed <- c("Det är roligt att lära sig R!", 1, 2, TRUE, FALSE)

Vi udskriver resultatet:

mixed
[1] "Det är roligt att lära sig R!" "1"
[3] "2"                             "TRUE"
[5] "FALSE"

Vi kontrollerer vektorens klasse:

## Kontrollér vektorens klasse
class(mixed)
[1] "character"

Bemærk følgende:

  1. Alle elementerne blev udskrevet med anførselstegn, hvilket betyder, at R har konverteret alle elementer til tekststrenge, også tallene, TRUE og FALSE. Dette kaldes coercion (tvungen omdannelse), hvilket betyder, at en datatype automatisk blev omdannet til en anden. Tallet 1 er således ikke længere en numerisk værdi; det repræsenterer blot tegnet 1. TRUE og FALSE er ikke længere booleske værdier; de udgør blot ordene TRUE og FALSE.
  2. Ovenstående forklarer, hvorfor funktionen [class()](https://rdrr.io/r/base/class.html) angiver, at vektoren er af typen character.
  3. Da typen nu er character, kan du ikke længere udføre matematiske beregninger (f.eks. beregne gennemsnit) på denne vektor.

Du skal være eksplicit, når du opretter vektorer i R. Tallene fra 1 til 4 kan oprettes både som numerisk vektor og som character-vektor. For at oprette en character-vektor skal hvert element angives med anførselstegn:

Eksempel 1: Opret numerisk vektor

my_numbers <- c(1, 2, 3, 4)
my_numbers
[1] 1 2 3 4

Eksempel 2: Opret character-vektor

my_characters <- c("1", "2", "3", "4")
my_characters
[1] "1" "2" "3" "4"

Du kan konvertere vektorer mellem forskellige typer med funktionerne [as.character()](https://rdrr.io/r/base/character.html), [as.numeric()](https://rdrr.io/r/base/numeric.html) osv.

Eksempel 3: Konvertér numerisk til character

## Opretter numerisk vektor
my_numbers <- c(1, 2, 3, 4)

## Konverterer numerisk vektor til character

my_characters <- as.character(my_numbers)
## Udskriver resultatet
my_characters
[1] "1" "2" "3" "4"

Derfor kan du konvertere vektorer mellem typer. Lad os prøve det modsatte, dvs. gå fra tegn til numerisk: Eksempel 4: Konvertér tegn til numerisk

my_characters <- c("1", "2", "3", "4")
my_numbers <- as.numeric(my_characters)

## Print it
my_numbers
[1] 1 2 3 4

Dette lykkedes, fordi tallene kom i den rigtige rækkefølge uden anførselstegn. Hvis de nu virkelig er numeriske værdier, burde vi kunne beregne et gennemsnit af tallene:

mean(my_numbers)
[1] 2.5

Nu er vi sikre på, at det blev rigtigt. Bemærk, at konverteringer nogle gange kan give uventede resultater. Derfor er det vigtigt at foretage en form for kontrol for at fastslå, at konverteringen bliver som forventet.

Lad os forsøge at konvertere strengen “Hej” til en numerisk værdi:

## Opret character-vektor
my_characters <- c("Hej")

## Konvertér den til numerisk vektor
my_numbers <- as.numeric(my_characters)
Warning: NAs introduced by coercion
## Udskriv resultatet
my_numbers
[1] NA

Her fik vi i stedet advarslen “NAs introduced by coercion”. NA står for “Not Available” eller “Not Applicable” afhængigt af sammenhængen. I dette tilfælde er det Not Available, hvilket betyder, at værdien mangler. Konverteringen har altså resulteret i, at R har tvunget værdien til NA. Når vi udskriver objektet my_numbers, findes der kun én enkelt værdi, og det er NA. Med andre ord kan R ikke konvertere “Hej” til en numerisk værdi.

4.1.1 Double vector

En double lagrer numeriske værdier. Værdierne kan have decimaler. R gemmer i princippet altid numeriske vektorer som double, selv om de ikke har decimaler. Det kan vi kontrollere nu:

## Opret numerisk vektor uden decimaler
my_numbers <- c(1, 2, 3)
## Kontrollér, om den er en double
is.double(my_numbers)
[1] TRUE
## Opret numerisk vektor med decimaler
your_numbers <- c(1.1, 2.2, 3.3)

## Kontrollér, om den er en double
is.double(your_numbers)
[1] TRUE

Selv om objektet my_numbers kun består af heltal, vil R gemme det som en double. Vi kan kontrollere, at vektoren ikke er et heltal:

is.integer(my_numbers)
[1] FALSE

4.1.2 Integer vector (heltal)

En integer vector lagrer kun heltal. Et heltal er en numerisk værdi uden decimaler. Det er usandsynligt, at du får brug for at arbejde med denne type vektor, da double-vektoren også kan håndtere heltal. Du kan i princippet altid bruge double i stedet for integer. Du behøver yderst sjældent at tage stilling til dette, fordi R gør det automatisk. Hvis du alligevel vil definere en vektor som integer, gør du det ved at tilføje bogstavet L efter tallene:

my_integers <- c(1L, 5L, 3L, 10L)
is.integer(my_integers)
[1] TRUE

Du kan også tvinge en double til integer:

## Opret en double-vektor
my_doubles <- c(1, 2, 3, 4)

## Kontrollér, om den er en double
is.double(my_doubles)
[1] TRUE
## Konvertér double til integer og gem resultatet i et nyt objekt kaldet my_integers
my_integers <- as.integer(my_doubles)

## Kontrollér, om my_integers er en integer-vektor
is.integer(my_integers)
[1] TRUE

Det er meget nyttigt at have forskellige typer vektorer. Forskellige vektorer bruges til forskellige formål. Matematiske operationer er kun mulige på numeriske vektorer og logicals. Vi vil demonstrere dette ved hjælp af funktionen [mean()](https://rdrr.io/r/base/mean.html), som beregner det matematiske gennemsnit af en række numeriske værdier:

## Opretter en double
my_values <- c(5, 10, 15, 20)

## Beregner gennemsnittet og gemmer resultatet i et nyt objekt kaldet my_mean
my_mean <- mean(my_values)

## Udskriver objektet
my_mean
[1] 12.5

Tidligere nævnte vi, at man kan indlejre funktioner i funktioner, hvilket kan spare meget plads. Nu beregner vi gennemsnittet igen uden at gemme nye objekter. Bemærk, at funktionen [c()](https://rdrr.io/r/base/c.html) er indlejret i funktionen [mean()](https://rdrr.io/r/base/mean.html).

mean(c(5, 10, 15, 20))
[1] 12.5

4.1.3 Character vector (strenge)

Tekst og symboler lagres i character-vektorer. Følgende kommando gemmer en tekststreng ved at omslutte den med anførselstegn:

my_string <- c("Detta är en textsträng. Den kan innehålla symboler (@, *, /) och siffror (1, 2, 3)")
my_string
[1] "Detta är en textsträng. Den kan innehålla symboler (@, *, /) och siffror (1, 2, 3)"

Vektoren my_string gemmer en streng, der indeholder symboler, bogstaver og tal. Her følger en character-vektor med to strenge, hvoraf den anden indeholder tal og symboler:

my_string <- c("Detta är den första strängen", "Detta är den andra strängen")
my_string
[1] "Detta är den första strängen" "Detta är den andra strängen"

Som nævnt ovenfor vil tal omgivet af anførselstegn blive tolket som tegn (ikke numeriske værdier). Det fremgår af eksemplet nedenfor, hvor vi også bruger funktionen [paste()](https://rdrr.io/r/base/paste.html) til at udskrive kommentarer i resultaterne:

paste("UTAN CITATTECKEN:")
[1] "UTAN CITATTECKEN:"
my_numbers <- c(1, 2, 3)
typeof(my_numbers)
[1] "double"
my_numbers
[1] 1 2 3
paste("MED CITATTECKEN:")
[1] "MED CITATTECKEN:"
your_numbers <- c("1", "2", "3")
typeof(your_numbers)
[1] "character"
your_numbers
[1] "1" "2" "3"

R viser anførselstegn ved udskrivning af your_numbers for at tydeliggøre, at elementerne er tekststrenge! Alle character-vektorer udskrives med anførselstegn i R.

En tegnstreng indeholder tegn og symboler. Det er ikke muligt at udføre matematiske operationer på tegnstrenge, selv om de indeholder tal. Lad os se to eksempler:

Eksempel 1: Opret en streng med bogstaver

my_string <- "Detta är en sträng"

## Gang den med 2
my_string*2
## Error in my_string * 2 : non-numeric argument to binary operator

Eksempel 2: Opret en streng med et tal

my_string <- "100"

## Gang med 2
my_string*2
## Error in my_string * 2 : non-numeric argument to binary operator

I begge eksempler svarer R, at handlingen ikke kan udføres, fordi vektoren ikke er numerisk. Character-vektorer kan altså indeholde tal, men de behandles ikke som numeriske værdier.

Du skal bruge anførselstegn, når du refererer til elementer i en character vector. Nedenfor oprettes to vektorer, som derefter kombineres til en data frame. Derefter vil vi forsøge at filtrere vores data frame, så den kun indeholder kvinder.

## Opret en vektor, der indeholder køn<
sex <- c("Man", "Woman", "Man", "Woman")

## Opret en vektor, der indeholder målte værdier for blodtryk
blood_pressure <- c(140, 130, 120, 150)

## Saml vektorerne til en dataframe med funktionen data.frame()
my_data_frame <- data.frame(sex, blood_pressure)

## Vis vores data frame
my_data_frame
    sex blood_pressure
1   Man            140
2 Woman            130
3   Man            120
4 Woman            150

Nu filtrerer vi, så kun kvinder er tilbage. Til det bruger vi funktionen [subset()](https://rdrr.io/r/base/subset.html):

only_women <- subset(my_data_frame, sex=="Woman")
## Vis vores data frame
only_women
    sex blood_pressure
2 Woman            130
4 Woman            150

Bemærk, at Woman er angivet med anførselstegn (i funktionen [subset()](https://rdrr.io/r/base/subset.html)) ovenfor, hvilket er et krav, fordi vektoren er en character. Hvis vi vil filtrere på blodtryk, som er en double, bruger vi ikke anførselstegn. Nedenfor filtrerer vi, så kun rækker med normalt blodtryk (mindre end eller lig med 130) bevares:

only_normal_blood_pressure <- subset(my_data_frame, blood_pressure <= 130)

## Vis vores data frame
only_normal_blood_pressure
    sex blood_pressure
2 Woman            130
3   Man            120

4.1.4 Logicals (boolean values, booleske værdier)

Visse variabler er binære af natur. Hvis sådanne variabler kan karakteriseres som TRUE eller FALSE, kaldes de logicals. Om en person er død eller levende, kan betragtes som en logical. Om en person rammes af kræft eller ej, kan også klassificeres som TRUE eller FALSE. R kan også evaluere sammenligninger og returnere TRUE eller FALSE, hvilket fremgår af eksemplet nedenfor:

10>1
[1] TRUE

Det går fint at bruge tallene 1/0 i stedet for TRUE/FALSE. Ordene TRUE og FALSE har en særstilling i sproget R. Hvis disse ord findes i vektorer, tolkes vektorerne automatisk som logicals. R accepterer desuden forkortelserne T og F.

## Opret en vektor med navne
name <- c("Adam", "Umit", "Joanna", "Sarah")

## Opret en boolesk vektor med TRUE/FALSE for, om personen er død
dead <- c(TRUE, FALSE, TRUE, FALSE)

## Opret en boolesk vektor med TRUE/FALSE for, om personen er gift
married <- c(F, T, F, F)

## Saml vektorerne til en data frame
my_data_frame <- data.frame(name, dead, married)

## Udskriv vores data frame
my_data_frame
    name  dead married
1   Adam  TRUE   FALSE
2   Umit FALSE    TRUE
3 Joanna  TRUE   FALSE
4  Sarah FALSE   FALSE

Som det fremgår ovenfor, accepterer R forkortelserne T for TRUE og F for FALSE.

4.1.5 Complex vector, raw vector

Du kommer sandsynligvis aldrig til at bruge disse vektorer i R, hvorfor vi ikke diskuterer dem.

4.1.6 Datoer, tider og tidsintervaller

Det er meget almindeligt at arbejde med datoer, tider og tidsintervaller. R håndterer, ligesom flere andre sprog, datoer og tider som numeriske værdier. Det betyder, at hver dato og hvert tidspunkt tildeles en numerisk værdi, som derefter kan bruges i analyser For at en dato kan tildeles en numerisk værdi, skal der findes en referencedato (en dato at tage udgangspunkt i). I sproget SAS er referencedatoen 1960-01-01 00:00:00 GMT. I R er referencedatoen 1970-01-01 00:00:00 UTC, men den kan justeres af brugeren. Hvilken referencedato der bruges, har som regel ingen betydning.

Datoer lagres i vektorer af klassen POSIXct eller POSIXlt, som faktisk er af typen double. Hvis en vektor er af typen POSIXct eller POSIXt, kan den ligne en character-vektor (fordi der kan være “-” eller “/” i datoen), men de er i virkeligheden numeriske værdier af klassen POSIXct eller POSIXlt.

Nu prøver vi at oprette vektorer, der består af datoer:

## Opret vektor med fødselsdatoer
birth_date <- c("1990-01-01", "1999-01-04", "2002-05-05", "2001-12-12")

## Opret vektor med dødsdatoer
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"

Som vi ser ovenfor, er ingen af vektorerne af typen POSIXct eller POSIXlt (begge er af typen character), hvilket er forventeligt, da vi oprettede vektorerne ved at sætte anførselstegn om datoerne. Vi skal fortælle R, at disse vektorer er datoer, hvilket vi kan gøre med funktioner, der findes i standardinstallationen af R, eller med pakken lubridate, som indeholder enkle og effektive funktioner til håndtering af datoer. Vi begynder med at bruge standardfunktioner til at konvertere vektorerne til datoer.

## Opretter datoobjekter med GMT (Greenwich Mean Time) som tidszone
birth_date <- as.POSIXct(birth_date)
death_date <- as.POSIXct(death_date)
class(birth_date)
[1] "POSIXct" "POSIXt"
class(death_date)
[1] "POSIXct" "POSIXt"

R har nu konverteret vektoren fra character til dato (POSIXct). Vi vil nu bruge funktionen [difftime()](https://rdrr.io/r/base/difftime.html) til at beregne tidsforskellen mellem fødselsdato og dødsdato.

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

Som det fremgår ovenfor, blev tidsforskellen beregnet i dage. Vi kan beregne tidsforskellen i andre enheder på følgende måde:

difftime(death_date, birth_date, units="secs")
Time differences in secs
[1] 476150400 342748800 494211600 312681600
difftime(death_date, birth_date, units="mins")
Time differences in mins
[1] 7935840 5712480 8236860 5211360
difftime(death_date, birth_date, units="hours")
Time differences in hours
[1] 132264  95208 137281  86856
difftime(death_date, birth_date, units="weeks")
Time differences in weeks
[1] 787.2857 566.7143 817.1488 517.0000

R bruger også tidszoner, selv om de fleste brugere ikke tager højde for dette. Eksempler på tidszoner er:

  • CET: Central European Time.
  • CEST: Central European Summer Time.
  • GMT: Greenwich Mean Time

Det kan være kompliceret at håndtere datoer, tidszoner og tidsintervaller med standardpakkerne i R. Derfor udviklede Garrett Grolemund, Hadley Wickham og Vitalie Spinu pakken lubridate, som gør håndteringen meget lettere. Begynd med at installere lubridate:

install.packages("lubridate")

Aktivér derefter pakken:

library(lubridate)
Attaching package: 'lubridate'

The following objects are masked from 'package:base':
    date, intersect, setdiff, union

Lubridate lagrer datoer som antallet af dage siden referencedatoen 1970-01-01 00:00:00 GMT. Du kan få den specifikke dato 18000 dage efter denne referencedato ved at bruge funktionen [as_date()](https://lubridate.tidyverse.org/reference/as_date.html):

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

Lad os lagre nogle datoer ved hjælp af lubridates funktioner. Der findes mange funktioner til dette. Princippet for disse funktioner er følgende:

  1. Identificér, i hvilken rækkefølge tidselementerne år (year, y), måned (month, m), dag (day, d), time (hour, h), minut (minute, m) og sekunder (seconds, s) kommer i datoen.
  2. Brug den funktion, der passer til rækkefølgen af tidselementerne.

I tabellen nedenfor ser du nogle eksempler på forskellige måder at skrive datoen 31. december 2020 på, og hvilken lubridate-funktion der kan indlæse datoen:

Datoformat Rækkefølge af tidselementer Funktion i lubridate
2020-12-31 YYYY-MM-DD ymd()
2020/12/31 YYYY/MM/DD ymd()
20201231 YYYYMMDD ymd()
20-12-31 YY-MM-DD ymd()
201231 YYMMDD ymd()

Eksempler på datoformater og tilsvarende funktioner i lubridate.

Lad os teste det ved at oprette en data frame med tre individer, inklusive deres navn, fødselsdato, dato for første undersøgelse og dødsdato. Alle datoer vil blive skrevet på forskellige måder for at teste funktionen [ymd()](https://lubridate.tidyverse.org/reference/ymd.html):

## Opret vektorer
name <- c("David", "Mohammed", "Christina")
birth_date <- ymd("1990-01-01", "1999-01-04", "2002-05-05")
examination_date <- ymd("1990.01.01", "1999.01.04", "2002.05.05")
death_date <- ymd("2005/02/02", "2009/11/14", "2018/01/01")

## Saml vektorerne til en data frame (tabel)
my_data <- data.frame(name, birth_date, examination_date, death_date)

## Se data frame
my_data
       name birth_date examination_date death_date
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

R genkendte altså forskellige datoformater og konverterede alle vektorerne til datoer. Funktionen [sapply()](https://rdrr.io/r/base/lapply.html) bruges til at anvende en funktion på hver kolonne i en data frame. Vi vil nu bruge [sapply()](https://rdrr.io/r/base/lapply.html) til at kontrollere, hvilken klasse kolonnerne i my_data har:

## Brug sapply() til at anvende funktionen class() på alle kolonner i my_data
sapply(my_data, class)
            name       birth_date examination_date       death_date
     "character"           "Date"           "Date"           "Date"

Lad os ændre rækkefølgen af år, måned og dag i vores datoer. Det er uproblematisk, så længe vi skifter funktion i lubridate:

## Dag, måned, år
dmy("30-01-2000", "25-12-2001")
[1] "2000-01-30" "2001-12-25"
## Måned, dag, år
mdy("12-25-1999", "09-29-2004")
[1] "1999-12-25" "2004-09-29"
## År, måned, dag
ymd("20181230", "20191129")
[1] "2018-12-30" "2019-11-29"

I det næste eksempel lagrer vi en dato, der inkluderer et klokkeslæt. For at læse dette korrekt tilføjer vi bogstaverne h (time), m (minutter) og s (sekunder) på følgende måde:

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

R tildelte datoen tidszonen UTC. R kan håndtere cirka 600 tidszoner, inklusive zonernes sommertider, vintertider og historiske kalendervariationer. Du kan få en liste over alle tidszoner ved at skrive følgende:

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"
 [21] "Africa/Douala"                    "Africa/El_Aaiun"
 [23] "Africa/Freetown"                  "Africa/Gaborone"
 [25] "Africa/Harare"                    "Africa/Johannesburg"
 [27] "Africa/Juba"                      "Africa/Kampala"
 [29] "Africa/Khartoum"                  "Africa/Kigali"
 [31] "Africa/Kinshasa"                  "Africa/Lagos"
 [33] "Africa/Libreville"                "Africa/Lome"
 [35] "Africa/Luanda"                    "Africa/Lubumbashi"
 [37] "Africa/Lusaka"                    "Africa/Malabo"
 [39] "Africa/Maputo"                    "Africa/Maseru"
 [41] "Africa/Mbabane"                   "Africa/Mogadishu"
 [43] "Africa/Monrovia"                  "Africa/Nairobi"
 [45] "Africa/Ndjamena"                  "Africa/Niamey"
 [47] "Africa/Nouakchott"                "Africa/Ouagadougou"
 [49] "Africa/Porto-Novo"                "Africa/Sao_Tome"
 [51] "Africa/Timbuktu"                  "Africa/Tripoli"
 [53] "Africa/Tunis"                     "Africa/Windhoek"
 [55] "America/Adak"                     "America/Anchorage"
 [57] "America/Anguilla"                 "America/Antigua"
 [59] "America/Araguaina"                "America/Argentina/Buenos_Aires"
 [61] "America/Argentina/Catamarca"      "America/Argentina/ComodRivadavia"
 [63] "America/Argentina/Cordoba"        "America/Argentina/Jujuy"
 [65] "America/Argentina/La_Rioja"       "America/Argentina/Mendoza"
 [67] "America/Argentina/Rio_Gallegos"   "America/Argentina/Salta"
 [69] "America/Argentina/San_Juan"       "America/Argentina/San_Luis"
 [71] "America/Argentina/Tucuman"        "America/Argentina/Ushuaia"
 [73] "America/Aruba"                    "America/Asuncion"
 [75] "America/Atikokan"                 "America/Atka"
 [77] "America/Bahia"                    "America/Bahia_Banderas"
 [79] "America/Barbados"                 "America/Belem"
 [81] "America/Belize"                   "America/Blanc-Sablon"
 [83] "America/Boa_Vista"                "America/Bogota"
 [85] "America/Boise"                    "America/Buenos_Aires"
 [87] "America/Cambridge_Bay"            "America/Campo_Grande"
 [89] "America/Cancun"                   "America/Caracas"
 [91] "America/Catamarca"                "America/Cayenne"
 [93] "America/Cayman"                   "America/Chicago"
 [95] "America/Chihuahua"                "America/Coral_Harbour"
 [97] "America/Cordoba"                  "America/Costa_Rica"
 [99] "America/Creston"                  "America/Cuiaba"
[101] "America/Curacao"                  "America/Danmarkshavn"
[103] "America/Dawson"                   "America/Dawson_Creek"
[105] "America/Denver"                   "America/Detroit"
[107] "America/Dominica"                 "America/Edmonton"
[109] "America/Eirunepe"                 "America/El_Salvador"
[111] "America/Ensenada"                 "America/Fort_Nelson"
[113] "America/Fort_Wayne"               "America/Fortaleza"
[115] "America/Glace_Bay"                "America/Godthab"
[117] "America/Goose_Bay"                "America/Grand_Turk"
[119] "America/Grenada"                  "America/Guadeloupe"
[121] "America/Guatemala"                "America/Guayaquil"
[123] "America/Guyana"                   "America/Halifax"
[125] "America/Havana"                   "America/Hermosillo"
[127] "America/Indiana/Indianapolis"     "America/Indiana/Knox"
[129] "America/Indiana/Marengo"          "America/Indiana/Petersburg"
[131] "America/Indiana/Tell_City"        "America/Indiana/Vevay"
[133] "America/Indiana/Vincennes"        "America/Indiana/Winamac"
[135] "America/Indianapolis"             "America/Inuvik"
[137] "America/Iqaluit"                  "America/Jamaica"
[139] "America/Jujuy"                    "America/Juneau"
[141] "America/Kentucky/Louisville"      "America/Kentucky/Monticello"
[143] "America/Knox_IN"                  "America/Kralendijk"
[145] "America/La_Paz"                   "America/Lima"
[147] "America/Los_Angeles"              "America/Louisville"
[149] "America/Lower_Princes"            "America/Maceio"
[151] "America/Managua"                  "America/Manaus"
[153] "America/Marigot"                  "America/Martinique"
[155] "America/Matamoros"                "America/Mazatlan"
[157] "America/Mendoza"                  "America/Menominee"
[159] "America/Merida"                   "America/Metlakatla"
[161] "America/Mexico_City"              "America/Miquelon"
[163] "America/Moncton"                  "America/Monterrey"
[165] "America/Montevideo"               "America/Montreal"
[167] "America/Montserrat"               "America/Nassau"
[169] "America/New_York"                 "America/Nipigon"
[171] "America/Nome"                     "America/Noronha"
[173] "America/North_Dakota/Beulah"      "America/North_Dakota/Center"
[175] "America/North_Dakota/New_Salem"   "America/Nuuk"
[177] "America/Ojinaga"                  "America/Panama"
[179] "America/Pangnirtung"              "America/Paramaribo"
[181] "America/Phoenix"                  "America/Port_of_Spain"
[183] "America/Port-au-Prince"           "America/Porto_Acre"
[185] "America/Porto_Velho"              "America/Puerto_Rico"
[187] "America/Punta_Arenas"             "America/Rainy_River"
[189] "America/Rankin_Inlet"             "America/Recife"
[191] "America/Regina"                   "America/Resolute"
[193] "America/Rio_Branco"               "America/Rosario"
[195] "America/Santa_Isabel"             "America/Santarem"
[197] "America/Santiago"                 "America/Santo_Domingo"
[199] "America/Sao_Paulo"                "America/Scoresbysund"
[201] "America/Shiprock"                 "America/Sitka"
[203] "America/St_Barthelemy"            "America/St_Johns"
[205] "America/St_Kitts"                 "America/St_Lucia"
[207] "America/St_Thomas"                "America/St_Vincent"
[209] "America/Swift_Current"            "America/Tegucigalpa"
[211] "America/Thule"                    "America/Thunder_Bay"
[213] "America/Tijuana"                  "America/Toronto"
[215] "America/Tortola"                  "America/Vancouver"
[217] "America/Virgin"                   "America/Whitehorse"
[219] "America/Winnipeg"                 "America/Yakutat"
[221] "America/Yellowknife"              "Antarctica/Casey"
[223] "Antarctica/Davis"                 "Antarctica/DumontDUrville"
[225] "Antarctica/Macquarie"             "Antarctica/Mawson"
[227] "Antarctica/McMurdo"               "Antarctica/Palmer"
[229] "Antarctica/Rothera"               "Antarctica/South_Pole"
[231] "Antarctica/Syowa"                 "Antarctica/Troll"
[233] "Antarctica/Vostok"                "Arctic/Longyearbyen"
[235] "Asia/Aden"                        "Asia/Almaty"
[237] "Asia/Amman"                       "Asia/Anadyr"
[239] "Asia/Aqtau"                       "Asia/Aqtobe"
[241] "Asia/Ashgabat"                    "Asia/Ashkhabad"
[243] "Asia/Atyrau"                      "Asia/Baghdad"
[245] "Asia/Bahrain"                     "Asia/Baku"
[247] "Asia/Bangkok"                     "Asia/Barnaul"
[249] "Asia/Beirut"                      "Asia/Bishkek"
[251] "Asia/Brunei"                      "Asia/Calcutta"
[253] "Asia/Chita"                       "Asia/Choibalsan"
[255] "Asia/Chongqing"                   "Asia/Chungking"
[257] "Asia/Colombo"                     "Asia/Dacca"
[259] "Asia/Damascus"                    "Asia/Dhaka"
[261] "Asia/Dili"                        "Asia/Dubai"
[263] "Asia/Dushanbe"                    "Asia/Famagusta"
[265] "Asia/Gaza"                        "Asia/Harbin"
[267] "Asia/Hebron"                      "Asia/Ho_Chi_Minh"
[269] "Asia/Hong_Kong"                   "Asia/Hovd"
[271] "Asia/Irkutsk"                     "Asia/Istanbul"
[273] "Asia/Jakarta"                     "Asia/Jayapura"
[275] "Asia/Jerusalem"                   "Asia/Kabul"
[277] "Asia/Kamchatka"                   "Asia/Karachi"
[279] "Asia/Kashgar"                     "Asia/Kathmandu"
[281] "Asia/Katmandu"                    "Asia/Khandyga"
[283] "Asia/Kolkata"                     "Asia/Krasnoyarsk"
[285] "Asia/Kuala_Lumpur"                "Asia/Kuching"
[287] "Asia/Kuwait"                      "Asia/Macao"
[289] "Asia/Macau"                       "Asia/Magadan"
[291] "Asia/Makassar"                    "Asia/Manila"
[293] "Asia/Muscat"                      "Asia/Nicosia"
[295] "Asia/Novokuznetsk"                "Asia/Novosibirsk"
[297] "Asia/Omsk"                        "Asia/Oral"
[299] "Asia/Phnom_Penh"                  "Asia/Pontianak"
[301] "Asia/Pyongyang"                   "Asia/Qatar"
[303] "Asia/Qostanay"                    "Asia/Qyzylorda"
[305] "Asia/Rangoon"                     "Asia/Riyadh"
[307] "Asia/Saigon"                      "Asia/Sakhalin"
[309] "Asia/Samarkand"                   "Asia/Seoul"
[311] "Asia/Shanghai"                    "Asia/Singapore"
[313] "Asia/Srednekolymsk"               "Asia/Taipei"
[315] "Asia/Tashkent"                    "Asia/Tbilisi"
[317] "Asia/Tehran"                      "Asia/Tel_Aviv"
[319] "Asia/Thimbu"                      "Asia/Thimphu"
[321] "Asia/Tokyo"                       "Asia/Tomsk"
[323] "Asia/Ujung_Pandang"               "Asia/Ulaanbaatar"
[325] "Asia/Ulan_Bator"                  "Asia/Urumqi"
[327] "Asia/Ust-Nera"                    "Asia/Vientiane"
[329] "Asia/Vladivostok"                 "Asia/Yakutsk"
[331] "Asia/Yangon"                      "Asia/Yekaterinburg"
[333] "Asia/Yerevan"                     "Atlantic/Azores"
[335] "Atlantic/Bermuda"                 "Atlantic/Canary"
[337] "Atlantic/Cape_Verde"              "Atlantic/Faeroe"
[339] "Atlantic/Faroe"                   "Atlantic/Jan_Mayen"
[341] "Atlantic/Madeira"                 "Atlantic/Reykjavik"
[343] "Atlantic/South_Georgia"           "Atlantic/St_Helena"
[345] "Atlantic/Stanley"                 "Australia/ACT"
[347] "Australia/Adelaide"               "Australia/Brisbane"
[349] "Australia/Broken_Hill"            "Australia/Canberra"
[351] "Australia/Currie"                 "Australia/Darwin"
[353] "Australia/Eucla"                  "Australia/Hobart"
[355] "Australia/LHI"                    "Australia/Lindeman"
[357] "Australia/Lord_Howe"              "Australia/Melbourne"
[359] "Australia/North"                  "Australia/NSW"
[361] "Australia/Perth"                  "Australia/Queensland"
[363] "Australia/South"                  "Australia/Sydney"
[365] "Australia/Tasmania"               "Australia/Victoria"
[367] "Australia/West"                   "Australia/Yancowinna"
[369] "Brazil/Acre"                      "Brazil/DeNoronha"
[371] "Brazil/East"                      "Brazil/West"
[373] "Canada/Atlantic"                  "Canada/Central"
[375] "Canada/Eastern"                   "Canada/Mountain"
[377] "Canada/Newfoundland"              "Canada/Pacific"
[379] "Canada/Saskatchewan"              "Canada/Yukon"
[381] "CET"                              "Chile/Continental"
[383] "Chile/EasterIsland"               "CST6CDT"
[385] "Cuba"                             "EET"
[387] "Egypt"                            "Eire"
[389] "EST"                              "EST5EDT"
[391] "Etc/GMT"                          "Etc/GMT-0"
[393] "Etc/GMT-1"                        "Etc/GMT-10"
[395] "Etc/GMT-11"                       "Etc/GMT-12"
[397] "Etc/GMT-13"                       "Etc/GMT-14"
[399] "Etc/GMT-2"                        "Etc/GMT-3"
[401] "Etc/GMT-4"                        "Etc/GMT-5"
[403] "Etc/GMT-6"                        "Etc/GMT-7"
[405] "Etc/GMT-8"                        "Etc/GMT-9"
[407] "Etc/GMT+0"                        "Etc/GMT+1"
[409] "Etc/GMT+10"                       "Etc/GMT+11"
[411] "Etc/GMT+12"                       "Etc/GMT+2"
[413] "Etc/GMT+3"                        "Etc/GMT+4"
[415] "Etc/GMT+5"                        "Etc/GMT+6"
[417] "Etc/GMT+7"                        "Etc/GMT+8"
[419] "Etc/GMT+9"                        "Etc/GMT0"
[421] "Etc/Greenwich"                    "Etc/UCT"
[423] "Etc/Universal"                    "Etc/UTC"
[425] "Etc/Zulu"                         "Europe/Amsterdam"
[427] "Europe/Andorra"                   "Europe/Astrakhan"
[429] "Europe/Athens"                    "Europe/Belfast"
[431] "Europe/Belgrade"                  "Europe/Berlin"
[433] "Europe/Bratislava"                "Europe/Brussels"
[435] "Europe/Bucharest"                 "Europe/Budapest"
[437] "Europe/Busingen"                  "Europe/Chisinau"
[439] "Europe/Copenhagen"                "Europe/Dublin"
[441] "Europe/Gibraltar"                 "Europe/Guernsey"
[443] "Europe/Helsinki"                  "Europe/Isle_of_Man"
[445] "Europe/Istanbul"                  "Europe/Jersey"
[447] "Europe/Kaliningrad"               "Europe/Kiev"
[449] "Europe/Kirov"                     "Europe/Kyiv"
[451] "Europe/Lisbon"                    "Europe/Ljubljana"
[453] "Europe/London"                    "Europe/Luxembourg"
[455] "Europe/Madrid"                    "Europe/Malta"
[457] "Europe/Mariehamn"                 "Europe/Minsk"
[459] "Europe/Monaco"                    "Europe/Moscow"
[461] "Europe/Nicosia"                   "Europe/Oslo"
[463] "Europe/Paris"                     "Europe/Podgorica"
[465] "Europe/Prague"                    "Europe/Riga"
[467] "Europe/Rome"                      "Europe/Samara"
[469] "Europe/San_Marino"                "Europe/Sarajevo"
[471] "Europe/Saratov"                   "Europe/Simferopol"
[473] "Europe/Skopje"                    "Europe/Sofia"
[475] "Europe/Stockholm"                 "Europe/Tallinn"
[477] "Europe/Tirane"                    "Europe/Tiraspol"
[479] "Europe/Ulyanovsk"                 "Europe/Uzhgorod"
[481] "Europe/Vaduz"                     "Europe/Vatican"
[483] "Europe/Vienna"                    "Europe/Vilnius"
[485] "Europe/Volgograd"                 "Europe/Warsaw"
[487] "Europe/Zagreb"                    "Europe/Zaporozhye"
[489] "Europe/Zurich"                    "Factory"
[491] "GB"                               "GB-Eire"
[493] "GMT"                              "GMT-0"
[495] "GMT+0"                            "GMT0"
[497] "Greenwich"                        "Hongkong"
[499] "HST"                              "Iceland"
[501] "Indian/Antananarivo"              "Indian/Chagos"
[503] "Indian/Christmas"                 "Indian/Cocos"
[505] "Indian/Comoro"                    "Indian/Kerguelen"
[507] "Indian/Mahe"                      "Indian/Maldives"
[509] "Indian/Mauritius"                 "Indian/Mayotte"
[511] "Indian/Reunion"                   "Iran"
[513] "Israel"                           "Jamaica"
[515] "Japan"                            "Kwajalein"
[517] "Libya"                            "MET"
[519] "Mexico/BajaNorte"                 "Mexico/BajaSur"
[521] "Mexico/General"                   "MST"
[523] "MST7MDT"                          "Navajo"
[525] "NZ"                               "NZ-CHAT"
[527] "Pacific/Apia"                     "Pacific/Auckland"
[529] "Pacific/Bougainville"             "Pacific/Chatham"
[531] "Pacific/Chuuk"                    "Pacific/Easter"
[533] "Pacific/Efate"                    "Pacific/Enderbury"
[535] "Pacific/Fakaofo"                  "Pacific/Fiji"
[537] "Pacific/Funafuti"                 "Pacific/Galapagos"
[539] "Pacific/Gambier"                  "Pacific/Guadalcanal"
[541] "Pacific/Guam"                     "Pacific/Honolulu"
[543] "Pacific/Johnston"                 "Pacific/Kanton"
[545] "Pacific/Kiritimati"               "Pacific/Kosrae"
[547] "Pacific/Kwajalein"                "Pacific/Majuro"
[549] "Pacific/Marquesas"                "Pacific/Midway"
[551] "Pacific/Nauru"                    "Pacific/Niue"
[553] "Pacific/Norfolk"                  "Pacific/Noumea"
[555] "Pacific/Pago_Pago"                "Pacific/Palau"
[557] "Pacific/Pitcairn"                 "Pacific/Pohnpei"
[559] "Pacific/Ponape"                   "Pacific/Port_Moresby"
[561] "Pacific/Rarotonga"                "Pacific/Saipan"
[563] "Pacific/Samoa"                    "Pacific/Tahiti"
[565] "Pacific/Tarawa"                   "Pacific/Tongatapu"
[567] "Pacific/Truk"                     "Pacific/Wake"
[569] "Pacific/Wallis"                   "Pacific/Yap"
[571] "Poland"                           "Portugal"
[573] "PRC"                              "PST8PDT"
[575] "ROC"                              "ROK"
[577] "Singapore"                        "Turkey"
[579] "UCT"                              "Universal"
[581] "US/Alaska"                        "US/Aleutian"
[583] "US/Arizona"                       "US/Central"
[585] "US/East-Indiana"                  "US/Eastern"
[587] "US/Hawaii"                        "US/Indiana-Starke"
[589] "US/Michigan"                      "US/Mountain"
[591] "US/Pacific"                       "US/Samoa"
[593] "UTC"                              "W-SU"
[595] "WET"                              "Zulu"
attr(,"Version")
[1] "2022f"

Lad os angive tidszonen til GMT (Greenwich Mean Time):

ymd_hms("2011-06-04 12:00:00", tz="GMT")
[1] "2011-06-04 12:00:00 GMT"

Datoer, tider og tidsintervaller diskuteres i detaljer i senere kapitler.

4.1.7 Factor vector (faktor)

Faktorer er kategoriske variabler, såsom køn, hårfarve, etnicitet, sygdomsstatus osv. En faktor er ganske enkelt en kategorisk variabel, som kan have flere niveauer. Niveauerne kan have en iboende rækkefølge, men det er ikke nødvendigt. Mange nye brugere har svært ved at skelne factor fra character. Den vigtigste praktiske forskel er, at R i beregninger næsten altid bruger factor. Hvis en variabel er af typen character, vil R oftest omdanne den til en factor, før beregningen udføres. Nogle gange skal du selv konvertere en character til factor, hvilket du gør med funktionen [as.factor()](https://rdrr.io/r/base/factor.html).

my_diagnoses <- c("Cancer", "Cancer", "Heart Disease", "Heart Disease", "Heart Disease")

my_diagnoses_character <- as.character(my_diagnoses)

my_diagnoses_factor <- as.factor(my_diagnoses)

Lad os oprette en tabel for hver vektor. Tabellen viser, hvor mange observationer hvert niveau (kategori) har:

table(my_diagnoses_character)
my_diagnoses_character
       Cancer Heart Disease
            2             3
table(my_diagnoses_factor)
my_diagnoses_factor
       Cancer Heart Disease
            2             3

Det er altså muligt at tabulere (oprette en tabel) med både character og factor. Lad os bruge funktionen [levels()](https://rdrr.io/r/base/levels.html) til at se, hvilke niveauer der findes i disse vektorer:

levels(my_diagnoses_character)
NULL
levels(my_diagnoses_factor)
[1] "Cancer"        "Heart Disease"

Som det fremgår ovenfor, mangler en character-vektor levels (niveauer). Funktionen [levels()](https://rdrr.io/r/base/levels.html) returnerer NULL, når den anvendes på en character-vektor. Når vi derimod anvender [levels()](https://rdrr.io/r/base/levels.html) på en factor, får vi at vide, hvilke niveauer faktoren har.

Faktorer har et referenceniveau (reference level)

Alle vektorer af typen factor har et referenceniveau (reference level), som er den kategori/det niveau, som alle øvrige kategorier/niveauer sammenlignes med i forskellige typer beregninger. Referenceniveauet er faktisk det første, der udskrives, når du bruger [levels()](https://rdrr.io/r/base/levels.html). Referenceniveauet for vektoren my_diagnoses_factor er altså Cancer.

Du kan ændre referenceniveauet for en factor, og det er ofte nødvendigt, når man laver deskriptive tabeller, grafer og statistiske modeller. For at forstå dette bruger vi et eksempel med kræftdata. I en undersøgelse ønsker man at sammenligne overlevelsen blandt patienter med lungekræft baseret på, hvilket årstal individerne blev diagnosticeret. Formålet er at afklare, om overlevelsen er blevet bedre gennem årene, og til dette formål skal man lave en logistisk regression, hvor alle kalenderår skal sammenlignes med det sidste år i undersøgelsen. Desværre har R sat det første år (2017) som referenceniveau, som det fremgår nedenfor:

## Opret vektor med diagnoseår
cancer_diagnosis_year <- c("2020", "2022", "2019", "2017", "2022")

## Konvertér vektoren til factor
cancer_diagnosis_year <- as.factor(cancer_diagnosis_year)

## Kontrollér niveauer. Første niveau er referenceniveauet
levels(cancer_diagnosis_year)
[1] "2017" "2019" "2020" "2022"

Vi kan ændre dette ved at bruge funktionen [relevel()](https://rdrr.io/r/stats/relevel.html) på følgende måde:

## Relevel
cancer_diagnosis_year <- relevel(cancer_diagnosis_year, "2022")

## Kontrollér levels igen
levels(cancer_diagnosis_year)
[1] "2022" "2017" "2019" "2020"

4.2 Coercion (tvungen konvertering)

Du har allerede set nogle eksempler på coercion, hvilket betyder, at R tvinger visse konverteringer af datatyper igennem. Den mest almindelige type coercion forekommer i følgende scenarier:

  • Hvis en vektor indeholder et enkelt ikke-numerisk symbol/tegn, konverteres hele vektoren til en vektor af typen character, selv om det egentlig er en numerisk vektor, og tegnet/symbolet er havnet der ved en fejl.
  • Hvis en vektor kun indeholder numeriske værdier, vil R konvertere den til en double.
  • Hvis en vektor kun indeholder 0/1, vil den blive konverteret til en double, selv om den er tænkt som en vektor af typen logical.
  • Hvis en vektor kun indeholder TRUE/FALSE, vil den blive konverteret til en logical.

Du kan altid konvertere vektorer med funktionerne [as.numeric()](https://rdrr.io/r/base/numeric.html), [as.factor()](https://rdrr.io/r/base/factor.html), [as.logical()](https://rdrr.io/r/base/logical.html), [as.character()](https://rdrr.io/r/base/character.html).

Matematisk tolkes TRUE som 1 og FALSE som 0. Det kan bekræftes ved at oprette en vektor med TRUE og FALSE og beregne summen af vektoren med funktionen [sum()](https://rdrr.io/r/base/sum.html):

sum(c(TRUE, TRUE, FALSE, FALSE))
[1] 2

Du kan konvertere 0 og 1 til TRUE og FALSE på følgende måde:

as.logical(c(1, 0, 1, 1))
[1]  TRUE FALSE  TRUE  TRUE

Og omvendt:

as.numeric(c(TRUE, TRUE, FALSE, FALSE))
[1] 1 1 0 0

4.3 Attributes (attributter)

Attributter er yderligere information eller præciseringer, der tilføjes til vektorer eller objekter. Attributter er nyttige i mange sammenhænge. Den mest almindelige attribut i R er names, som indeholder navnene på elementerne i et objekt. I en data frame (tabel) er det ganske enkelt navnene på kolonnerne.

4.3.1 Names

Lad os oprette en data frame med to kolonner (variabler), nemlig køn og blodtryk. Det gøres ved først at oprette to vektorer (gender, blood_pressure), som derefter kombineres til en data frame med funktionen [data.frame()](https://rdrr.io/r/base/data.frame.html):

gender <- c("Man", "Woman", "Man", "Woman")
blood_pressure <- c(140, 130, 120, 150)
my_data_frame <- data.frame(gender, blood_pressure)

Lad os se på vores data frame:

my_data_frame
  gender blood_pressure
1    Man            140
2  Woman            130
3    Man            120
4  Woman            150

Vores data frame har 4 rækker og 2 kolonner (variabler). Lad os kontrollere names (kolonnernes navne) i vores data frame:

names(my_data_frame)
[1] "gender"    "blood_pressure"

Der findes to navneattributter: gender og blood_pressure.

Du kan ændre kolonnernes navne ved at erstatte informationen i names med ny information. Det gøres på følgende måde:

names(my_data_frame) <- c("Sex", "Pressure")
names(my_data_frame)
[1] "Sex"      "Pressure"

Der findes heldigvis enklere metoder til at omdøbe kolonner, og de præsenteres i senere kapitler.

Attributterne kan bruges til at referere til indhold i objekter. Det betyder, at du kan få adgang til specifikke kolonner i en data frame ved at bruge attributten. For at referere til Pressure i my_data_frame bruger du symbolet $ på følgende måde:

my_data_frame$Pressure
[1] 140 130 120 150

På samme måde kan du oprette en ny kolonne. Nu opretter vi kolonnen Pressure_Half ved at dividere Pressure med 2:

my_data_frame$Pressure_Half <- my_data_frame$Pressure/2

## Se vores data frame
my_data_frame
    Sex Pressure Pressure_Half
1   Man      140            70
2 Woman      130            65
3   Man      120            60
4 Woman      150            75

Sådan kan man altså oprette kolonner ud fra eksisterende kolonner.

4.3.2 Dimensions

Lad os kontrollere attributten dim, som er en forkortelse for dimension. Denne funktion returnerer objektets dimensioner, hvilket er antal rækker og antal kolonner for en data frame (tabel):

dim(my_data_frame)
[1] 4 3

Funktionen [dim()](https://rdrr.io/r/base/dim.html) returnerede tallene 4 og 3, som repræsenterer henholdsvis antallet af rækker og kolonner.

4.4 Matrix (matrix)

Eng: singular = matrix, plural = matrices.

Da: singular = matrix, plural = matricer.

En matrix (matrix) er en todimensionel struktur. Du opretter matricer med funktionen [matrix()](https://rdrr.io/r/base/matrix.html). Denne funktion har argumenterne nrow (antal rækker) og ncol (antal kolonner), som angiver antallet af rækker og kolonner. Lad os først oprette en numerisk vektor og derefter en matrix ud fra den:

## Opret vektor med tal
my_vector <- c(1, 2, 3, 4, 5, 6)

## Omdan vektoren til en matrix med 2 rækker og 3 kolonner
my_matrix <- matrix(my_vector, nrow=2, ncol=3)

## Se matrixen
my_matrix
     [,1] [,2] [,3]
[1,]    1    3    5
[2,]    2    4    6

Funktionen matrix() udfylder matrixen oppefra og ned, én kolonne ad gangen. Du kan ændre denne adfærd, så den i stedet udfylder én række ad gangen, med argumentet byrow=TRUE:

my_matrix <- matrix(my_vector, nrow=2, ncol=3, byrow=TRUE)

## Se matrixen
my_matrix
     [,1] [,2] [,3]
[1,]    1    2    3
[2,]    4    5    6

En matrix kan kun indeholde én enkelt type vektor. Det er den store forskel mellem matricer og data frames. En data frame kan indeholde alle typer vektorer (factor, character, numeric, double, integer osv.).

4.5 Array

Et array kan have mere end to dimensioner. Et array kan således betragtes som et objekt, der indeholder flere separate matricer. Funktionen [array()](https://rdrr.io/r/base/array.html) bruger argumentet dim til at angive arrayets struktur. For at oprette et array med 2 rækker, 2 kolonner og 3 dimensioner bruger du følgende kommando:

my_vector <- c(1, 2, 3, 4, 5, 6)
my_array <- array(my_vector, dim=c(2, 2, 2))

## View my_array
my_array
, , 1
     [,1] [,2]
[1,]    1    3
[2,]    2    4
, , 2
     [,1] [,2]
[1,]    5    1
[2,]    6    2

Hvis et array er større end antallet af elementer i den vektor, det er baseret på, vil vektoren blive genbrugt, hvilket fremgår af eksemplet ovenfor (tallene 1 og 2 er genbrugt i den anden matrix' anden kolonne).

4.6 Lists (Lister)

Lister er kraftfulde objekter, fordi de kan lagre alle typer objekter. En liste kan altså indeholde flere vektorer, data frames, matricer og arrays på samme tid. Objekterne må endda have forskellig længde! Lister oprettes med funktionen [list()](https://rdrr.io/r/base/list.html). Lad os oprette en liste med en vektorer af typen character, numeric og logical (bemærk, at vektorerne har forskellig længde):

## Numerisk vektor
my_numbers <- c(1, 2, 3)

## Character-vektor
my_characters <- c("Diabetes", "Cancer", "AIDS", "Heart failure", "Arthritis", "Depression")

## Logical-vektor
my_bools <- c(TRUE, TRUE, FALSE, TRUE)

## Kombinér vektorerne til en liste
my_list <- list(my_numbers, my_characters, my_bools)

## Se listen
my_list
[[1]]
[1] 1 2 3
[[2]]
[1] "Diabetes"      "Cancer"        "AIDS"          "Heart failure"
[5] "Arthritis"     "Depression"
[[3]]
[1]  TRUE  TRUE FALSE  TRUE

Bemærk følgende ovenfor:

  • Vektorerne, der lagres i en liste, kan have varierende længde og datatype.
  • I udskriften ovenfor fremgår det, at listen indeholder 3 objekter, hvilket angives med [1[1], [2[2] og [3[3]. For at referere til objekter i en liste bruges altså dobbelte firkantede parenteser.

En liste kan endda indeholde en data frame. Lad os udvide ovenstående eksempel med en data frame og derefter udskrive listen:

## Numerisk vektor
my_numbers <- c(1, 2, 3)

## Character-vektor
my_characters <- c("Diabetes", "Cancer", "AIDS", "Heart failure", "Arthritis", "Depression")

## Logical-vektor
my_bools <- c(TRUE, TRUE, FALSE, TRUE)

## Data frame
age <- c(1, 2, 3, 4)
sex <- c("male", "female", "male", "female")
my_data_frame <- data.frame(age, sex)

## Kombinér det hele til en liste
my_list <- list(my_numbers, my_characters, my_bools, my_data_frame)

## Se listen
my_list
[[1]]
[1] 1 2 3
[[2]]
[1] "Diabetes"      "Cancer"        "AIDS"          "Heart failure"
[5] "Arthritis"     "Depression"
[[3]]
[1]  TRUE  TRUE FALSE  TRUE
[[4]]
  age    sex
1   1   male
2   2 female
3   3   male
4   4 female

Det første listeobjekt ([1[1]) lagrer værdierne 1, 2 og 3. Det andet listeobjekt ([2[2]) lagrer tegnstrengene Diabetes, Cancer, AIDS osv.

Lister er meget fleksible; de kan faktisk indeholde andre lister. Et eksempel følger:

## Create atomic vector
my_numbers <- c(1, 2, 3)

## Create a list
my_first_list <- list(c("A", "B", "C"), c(100, 200, 300))

## Create a list storing both an atomic vector and a list
my_second_list <- list(my_numbers, my_first_list)

## View my list
my_second_list
[[1]]
[1] 1 2 3
[[2]]
[[2]][[1]]
[1] "A" "B" "C"
[[2]][[2]]
[1] 100 200 300

Nu kan du se, at det nye objekt indeholder tre rækker, men kun to objekter, og det andet objekt ([2[2]) er en liste og indeholder to objekter. Det er vigtigt at bemærke, at en liste kan indeholde alle typer R-objekter, hvilket gør lister nyttige til lagring af data.

4.7 Data frames

Vi har allerede set flere data frames i eksemplerne ovenfor. En data frame ligner et regneark i Excel og Numbers. En typisk data frame har observationer i hver række, og kolonnerne udgør variabler:

Navn Alder Indkomst Uddannelse Kolesterol
Adam 45 324211 Videregående uddannelse 4.5
Zara 51 198765 Folkeskole 7.6
John 49 250643 Gymnasium 3.2

Eksempel på en data frame.

I de fleste tilfælde vil rækkerne udgøre observationer, og kolonnerne vil udgøre måleværdier (variabler) for observationerne. Statistiske modeller, machine learning og andre almindelige funktioner i R kræver ofte, at data findes i en data frame. Nu opretter vi tre vektorer og kombinerer dem til en data frame.

## Opretter en vektor med tallene 1 til 15
variable1 <- 1:15

## Bruger funktionen rnorm() til at generere 15 helt tilfældige værdier
variable2 <- rnorm(15)

## Opretter en vektor med 15 bogstaver </em>
variable3 <- c("A", "B", "W", "C", "D", "E", "A", "B", "C", "D", "E", "U", "O", "L", "E")

## Kombinerer det hele til en data frame med funktionen data.frame()
my_data_frame <- data.frame(variable1, variable2, variable3)

## Se vores data frame
my_data_frame
   variable1   variable2 variable3
1          1  0.61687819         A
2          2 -1.49693238         B
3          3 -0.02426337         W
4          4  0.97459121         C
5          5 -1.03211448         D
6          6 -0.57205032         E
7          7 -0.30575213         A
8          8 -0.77495326         B
9          9 -0.67784625         C
10        10  0.50121613         D
11        11  1.23014030         E
12        12 -1.84284583         U
13        13  0.16945138         O
14        14  0.91849363         L
15        15  0.69476883         E

Hver kolonne i vores data frame indeholder samme type data, og vektorerne har samme længde. Hvis vektorerne ikke har samme længde, vil R genbruge den mindre vektor for at oprette en data frame.

Hvorfor så besværligt?

I ovenstående eksempler har vi oprettet vektorer og data frames manuelt. Det er unægtelig tidskrævende og omstændeligt. Når du arbejder, vil du med stor sandsynlighed importere en færdig data frame, som du derefter analyserer. Grunden til, at vi alligevel har oprettet vektorer og data frames manuelt, er for at demonstrere, hvordan R opfører sig.

Lad os kontrollere strukturen i vores data frame ved hjælp af funktionen [str()](https://rdrr.io/r/utils/str.html):

str(my_data_frame)
'data.frame':   15 obs. of  3 variables:
 $ variable1: int  1 2 3 4 5 6 7 8 9 10 ...
 $ variable2: num  0.6169 -1.4969 -0.0243 0.9746 -1.0321 ...
 $ variable3: chr  "A" "B" "W" "C" ...

Ifølge ovenstående er objektet af typen ‘data.farme’ med 15 observationer og 3 variabler. Det fremgår, at variable1 er af typen integer, variable2 er numeric, og variable3 er character. Når du opretter en data frame, kan du angive, om du vil have R til at tvinge character-vektorer til factors, med argumentet stringsAsFactors på følgende måde:

my_data_frame <- data.frame(variable1, variable2, variable3, stringsAsFactors = TRUE)
str(my_data_frame)
'data.frame':   15 obs. of  3 variables:
 $ variable1: int  1 2 3 4 5 6 7 8 9 10 ...
 $ variable2: num  0.6169 -1.4969 -0.0243 0.9746 -1.0321 ...
 $ variable3: Factor w/ 9 levels "A","B","C","D",..: 1 2 9 3 4 5 1 2 3 4 ...

Nu er variable3 en factor med 9 levels (niveauer).

Ikon af et programvindue med tre farvede knapper og grønne kodelinjer på mørk baggrund

Data frame = df

Det er almindeligt, at data frame forkortes df. Du vil ofte se denne forkortelse, når du arbejder med R.