Kapitel 10 Funktioner

R giver rig mulighed for at programmere egne funktioner. Det er muligt at lave det meste af det man skal i R uden at kende til funktioner, men når man eksempelvis skal lave mere specifikke arbejdsopgaver eller opgaver der skal gentages mange gange med enkelte modifikationer, er det ideelt at kunne lave sine egne funktioner. Ligeledes er det godt at kende til logikken bag funktioner, hvis man skal evaluere andres kode, hvor man ofte vil se funktioner.

Det meste af det man gør i R bruger eksisterende funktioner. En funktion anvendes på et objekt, der angives i en parentes, altså funktion(objekt). Vi kan eventuelt se hvordan funktionen sd() fungerer ved blot at skrive sd:

sd
function (x, na.rm = FALSE) 
sqrt(var(if (is.vector(x) || is.factor(x)) x else as.double(x), 
    na.rm = na.rm))
<bytecode: 0x7fb6468f3e98>
<environment: namespace:stats>

Her kan vi se, at funktionen tager objektet, betegnet med x, og undersøger om det er en numerisk vektor, og såfremt den er det, tager funktionen kvadratroden af variansen i objektet. Der er i udgangspunktet således ingen grund til, at vi har funktionen sd(), da vi blot kan bruge:

sqrt(var(1:5))
[1] 1.581139

Det er dog blot nemmere at skrive (og læse), når man bruger funktionen sd()

sd(1:5)
[1] 1.581139

Funktionen tager dermed et objekt, i ovenstående eksempel et objekt med tallene i c(1, 2, 3, 4, 5), og applicerer en kommando til objektet. Der er meget få begrænsninger på, hvad der kan laves i funktioner, og vi kan begynde med at lave vores helt egen meget simple funktion. Vi laver i nedenstående en funktion med navnet plus2, der tager et objekt og adderer 2:

plus2 <- function(x) x+2

Funktionen vil således tage vores nummer (x) og addere 2:

plus2(8)
[1] 10

I dette eksempel er der ét input, altså x, men det er muligt at lave funktioner, der kræver flere input. I nedenstående eksempel laver vi en ny funktion, der kræver to input, og med det første tal adderer 2 (som i ovenstående eksempel), og tager produktet af det andet input.

multif <- function(x, y) {
  x <- x + 2
  y <- y^2
  c(x, y)
}

I ovenstående angiver vi, at vi gerne vil have tallene ud i en vektor. I nedenstående eksempel bruger vi tallene 3 og 4, så funktionen returnerer 3 + 2 og 4^2:

multif(3,4)
[1]  5 16

Dette output kan vi gemme i et nyt objekt, eller vi kan - som i nedenstående eksempel - lave andre operationer med det:

2 * multif(3,4)
[1] 10 32

10.1 Loops

Loops er gode at anvende i en funktion, hvis man gentage en bestemt procedure for en række af tal. Hvis vi eksempelvis har tallene fra 1 til 6, og vi skal have det dobbelte af hvert af disse tal, kan vi lave en funktion, der for hvert tal i 1:6 tager tallet og multiplicerer det med 2 - og så viser tallet med print:

for (i in 1:6){
  print(i * 2)
}
[1] 2
[1] 4
[1] 6
[1] 8
[1] 10
[1] 12

Disse for loops kan nemt anvendes sammen med andre funktioner, eksempelvis funktionen plus2(), vi lavede tidligere:

for (i in 1:6){
  print(i * 2 * plus2(3))
}
[1] 10
[1] 20
[1] 30
[1] 40
[1] 50
[1] 60

Der er forskellige typer af loops i R, der ofte bruges i relation til for loops, herunder if, else og while. Det er ikke alle, der er lige store tilhængere af for loops, især da de kan blive komplicerede at skrive og læse, samt - for meget komplicerede opgaver, kan tage en del tid at fuldføre. Derfor bruger en del vektoriserede funktioner såsom sapply() og funktioner i pakker som dplyr.