Impliciete lus
Een van de sterke punten van R is dat je in veel gevallen zonder lus constructie toch alle elementen in een vector of een matrix kan bewerken. Je kunt bijvoorbeeld in 1 keer een getal optellen bij een matrix of een vector, zonder dat je een lus moet programmeren waarin je alle elementen van de matrix of vector 1 voor 1 bezoekt om er vervolgens 1 bij op te kunnen tellen, of met 10 te vermenigvuldigen:
> x <- 1:10
> y <- x * 10
> y
[1] 10 20 30 40 50 60 70 80 90 100
Verder kent R nog de functie apply met behulp waarvan we een willekeurige functie (van R, of zelf geschreven) kunnen toepassen op de rijen of kolommen van een matrix. Stel we willen de getallen in de kolommen van matrix QQQ optellen. Het is niet nodig daarvoor een lus te schrijven. We kunnen apply gebruiken:
# eerst even de data binnenhalen
> QQQ<-read.table("http://www.mzandee.nl/ab07/data/data.txt")
# som van alle elementen in elke kolom
> kolsom <- apply(QQQ, 2, sum)
> kolsom
V1 V2 V3
11711.5 4860.0 1064.1
# gemiddelde van alle elementen in elke kolom
> kolgem <- apply(QQQ, 2, mean)
kolgem
V1 V2 V3
177.44697 73.63636 16.12273
Om de functie sum op de rijen toe te passen i.p.v. de kolommen wijzigen we de het argument 2 van apply in een 1 [de eerste index van een matrix geeft de rijen aan, de tweede de kolommen].
Er bestaat ook een functie lapply die het zelfde werkt als apply, maar dan op een lijst in plaats van een matrix. En dan is er nog de functie tapply die op vectoren werkt. De functie tapply heeft een argument nodig waarmee de elementen in de vector worden gegroepeerd, een zg factor. We willen bijvoorbeeld de gemiddelde lichaamslengte weten van personen gegroepeerd op oogkleur:
# eerst even de data binnenhalen
> QQQ<-read.table("http://www.mzandee.nl/ab07/data/gegevens.txt")
> attach(QQQ)
> names(QQQ)
[1] "lichaam" "arm" "pols" "geslacht" "hand" "ogen"
> tapply(lichaam, ogen, mean)
blauw bruin grijs groen zwart
175.7500 178.0769 176.0000 180.6190 154.0000
Het is dus niet nodig om een lus te schrijven waarin we de verschillende elementen in de vector lichaam bezoeken, en afhankelijk van hun waarde in de variabele ogen de gemiddelde lichaamslengte berekenen. Zoals bijvoorbeeld:
> blauw<-bruin<-grijs<-groen<-zwart<-NULL
> for(teller in 1:length(lichaam)){
+ if(ogen[teller]=="blauw") blauw<-c(blauw,lichaam[teller])
+ if(ogen[teller]=="bruin") bruin<-c(bruin,lichaam[teller])
+ if(ogen[teller]=="grijs") grijs<-c(grijs,lichaam[teller])
+ if(ogen[teller]=="groen") groen<-c(groen,lichaam[teller])
+ if(ogen[teller]=="zwart") zwart<-c(zwart,lichaam[teller])
+ }
> c(mean(blauw),mean(bruin),mean(grijs),mean(groen),mean(zwart))
[1] 175.7500 178.0769 176.0000 180.6190 154.0000
Een ander bijzonder krachtig instrument om impliciet lussen mee te programmeren is de functie replicate. Replicate heeft 2 argumenten: het eerste moet een positief geheel getal x zijn. Het tweede argument is de expressie die x keer zal worden uitgevoerd.
We willen bijvoorbeeld een histogram maken van de uitkomst van 1000 experimenten in elk waarvan we de gemiddelde waarde berekenen van 100 worpen met een dobbelsteen:
hist(replicate(1000, mean(sample(1:6, 100, replace=TRUE))))
De functie sample trekt 100 keer random een getal uit de reeks 1, 2, 3, 4 , 5, 6, met teruglegging. We berekenen voor elke 100 trekkingen het gemiddelde, en dat berekenen van het gemiddelde over 100 trekkingen herhalen we 1000 keer.