<- 2
a ^3 a
Antwoorden R
1 Introductie en installatie
a.
b.
<- 9.5
b ^19 b
c.
Om de laatste afstand te berekenen, gebruiken we de stelling van Pythagoras (\(a^2+b^2=c^2\), dus \(c=\sqrt{a^2+b^2}\)). Om te zorgen dat de berekening niet in de environment opgeslagen wordt, moeten we de berekening niet aan een variabele toekennen (we gebruiken dus geen <-
). We typen dus simpelweg \(a+b+c\) om de totaalafstand te laten zien.
<- 3
a <- 4
b <- sqrt(a^2+b^2) # stelling van Pythagoras
c +b+c # geen pijltje betekent dat de uitkomst alleen wordt weergegeven a
d.
Omdat we een script hadden gemaakt met variabelen voor \(a\), \(b\) en \(c\), is het nu makkelijk om deze aanpassing te maken (\(a\) wordt 5 en \(b\) wordt 6). Om de uitkomst in de environment op te slaan gebruiken we <-
om deze in een variabele op te slaan die afstand
heet. Het totaalscript is dan:
<- 5
a <- 6
b <- sqrt(a^2+b^2) # stelling van Pythagoras
c <- a+b+c # sla de uitkomst op in een variabele met <-
afstand
print(paste('Je hebt', afstand, 'stappen gelopen'))
a.
Omdat \(a\) van de vorige opgave nog op 5 stond, is de uitkomst 15. Echter hebben we in de vorige opgave geen \(d\) gedefinieerd, dus krijg je deze uitkomst:
> d+10
Error: object 'd' not found
b.
Om \(d\) op 0 te zetten typen we d <- 0
in de console, en drukken we op enter. De breuk \(a \over d\) geeft de volgende uikomst:
> a/d
[1] Inf
Inf
staat voor ‘infinity’, wat komt doordat we door \(0\) delen!
c.
Eerst voeren we d <- 0.001
uit. Dan berekenen we de breuken:
> a/d
[1] 5000
> a/d^2
[1] 5e+06
Eerst delen we door 0.001, waardoor \(a\) 1000 keer zo groot wordt. Dan delen we door \(0.001^2\), wat ‘1 miljoenste’ is. Hierdoor wordt \(a\) een miljoen keer zo groot. Om dergelijk grote getallen weer te geven wordt de wetenschappelijke notatie gebruik (5e+06
). Het antwoord uit vraag b (delen door 0) kunnen we nu begrijpen. Als we door een steeds kleiner getal delen, wordt de uitkomst groter en groter. Dus als we door 0 delen (een oneindig klein getal!), krijgen we als resultaat oneindig.
2 Programmeren in R
a.
Het resultaat is:
Error in rtree(10) : could not find function "rtree"
De functie rtree bestaat dus helemaal niet in R!
b.
Dit print iets in de console:
Phylogenetic tree with 10 tips and 9 internal nodes.
Tip labels:
t2, t3, t6, t9, t4, t7, ...
Rooted; includes branch lengths.
Kennelijk doet dit package iets met fylogenetische bomen.
c.
De boom ziet er elke keer anders uit. De ‘r’ in de functie zal dus wel voor random (willekeurig) staan.
d.
Deze past het aantal soorten in de willekeurige boom aan.
e.
In de tekst van dit hoofdstuk heb je geleerd dat dit kan met ?rtree
, wat een venster opent in Rstudio met uitleg over je functie. Zo kan je bijvoorbeeld alle tip-levels veranderen:
<- paste("Soort ",1:5)
labels plot(rtree(5,tip.label=labels))
a. Er zijn drie soorten penguins. Er zijn veel manieren om dit te zien. Ten eerste, als je View(penguins)
gebruikt, kun je de verschillende soorten zelf tellen in de eerste kolom. Een andere manier is om de species-kolom uit de dataframe te pakken:
$species penguins
Deze code print de hele eerste kolom, en vat aan het einde samen hoevel verschillende ‘levels’ de data heeft:
Levels: Adelie Chinstrap Gentoo
Hier zie je dus ook dat er drie soorten zijn. Een derde manier is om de functie summary
toe te passen op de kolom, zodat je een tabel te zien krijgt met het aantal soorten, en hoe vaak ze voor komen:
> summary(penguins$species)
Adelie Chinstrap Gentoo
152 68 124
b. Hieronder staat hoe je deze functies kan gebruiken. Je kan ook de functie summary
gebruiken, die geeft in 1 klap een heleboel van deze getallen:
min(penguins$flipper_length_mm,na.rm=T) # T is kort voor TRUE
max(penguins$flipper_length_mm,na.rm=T)
mean(penguins$flipper_length_mm,na.rm=T)
# Je kan ook summary gebruiken, die geeft van alles:
summary(penguins$flipper_length_mm)
c.
<- summary(penguins$sex) # geeft 3 waarden: female, male, en NA
x <- x[3]/(nrow(penguins)) # aantal NAs gedeeld door aantal rijen
fractie <- 100*fractie # omzetten naar percentages
percentage print(percentage)
a. Hiervoor kunnen we dezelfde structuur gebruiken als voor ‘biologen’ in het hoofdstuk:
<- data.frame(temperatuur=c(20, 25, 30, 35, 40),
bacterien groeisnelheid=c(2.0, 2.25, 2.65, 2.35, 2.2))
Alternatief kun je eerst twee vectoren definieren, als je dat overzichtelijker vindt:
<- c(20, 25, 30, 35, 40)
temperatuur <- c(2.0, 2.25, 2.65, 2.35, 2.2)
groeisnelheid <- data.frame(temperatuur,groeisnelheid) bacterien
b. Hoewel je dit zelf ook nog wel kan lezen, zijn biologische datasets hier vaak te groot voor. Zoals de tip zegt, geeft which.max()
de index met de hoogste waarde terug. Deze index kun je dan gebruiken om de corresponderende temperatuur te vinden:
# Vind de index van de maximale groeisnelheid
<- which.max(bacterien$groeisnelheid) # geeft index-waarde '3'
maxgroei_index # Toon de corresponderende temperatuur
$temperatuur[maxgroei_index] # geeft '30', namelijk de temperatuur op positie 3 bacterien
c. Om dit te doen moeten we de kolom ‘groeisnelheid’ tot de macht 10 verheffen:
<- bacterien$groeisnelheid^10
totaalgroei $totaalgroei <- totaalgroei bacterien
d.
$totaalgroei[1] == 1024 # TRUE, het is dus goed gegaan bacterien
e.
plot(bacterien$temperatuur, bacterien$groeisnelheid,
type = "b", col='seagreen', lwd=2,
xlab = "Temperatuur (Celcius)", ylab = "Groeisnelheid (per uur)",
main = "Groeisnelheid vs Temperatuur")
a. In R geeft lengtes>=15
een vector van TRUE
en FALSE
terug. Deze kun je meteen doorgeven aan sum
, en deze geeft dan het totaal aantal:
<- c(12, 18, 7, 21, 15, 16, 14, 10, 20, 17)
lengtes <- sum(lengtes>=15) # groot genoeg
grootgenoeg print(paste("Aantal vissen groter of gelijk aan 15 cm:", grootgenoeg))
b. Vergelijkbaar met de vorige vraag, maar we moeten nog het percentage uitrekenen.
<- c(12, 18, 7, 21, 15, 16, 14, 10, 20, 17)
lengtes <- length(lengtes) # Totaal aantal vissen
totaal_vissen <- sum(lengtes < 15) # Aantal vissen kleiner dan 15 cm
vissen_te_klein <- (vissen_te_klein / totaal_vissen) * 100
percentage_te_klein print(paste("Percentage vissen kleiner dan 15 cm:", percentage_te_klein, "%"))
c. Indexing doen we met vierkante haken, maar in dit geval gebruiken we niet de specifieke posities (1,2,5), maar de conditie (TRUE, FALSE, FALSE, etc.):
<- lengtes[lengtes >= 15]
lengtes_vissen_vrijlaten print(lengtes_vissen_vrijlaten)
d. Om dit te doen ‘loopen’ we over de vector van lengtes, en testen of elke vis aan de voorwaarde voldoet:
for (l in lengtes) {
if (l >= 15) {
print(paste("Vis van", l, "cm is groot genoeg om vrij te laten."))
else {
} print(paste("Vis van", l, "cm is te klein."))
} }
Extra R oefeningen en oefentoets
a.
# waarden instellen
<- 2.5
a <- 11
b <- 0.01
c
# bereken de uitkomst
<- a/b+a*(c+a)
uitkomst
<- 5 a
b. Bij het berekenen van uitkomst worden de parameters a, b, en c
gebruikt om iets te berekenen. Dit komt neer op pasta, groente en pesto combineren in een gerecht. Dat je daarna de pesto aanpast verandert niet je gerecht: die was al klaar.
Na het maken van deze vraag, zou je script er ongeveer zo uit kunnen zien:
a.
<- 14
x <- x + 2.3 x
b.
<- 14
x
for(i in 1:100){
<- x + 2.3
x }
c.
<- 14
x <- 50
n
for(i in 1:n){
<- x + 2.3
x }
d.
<- 14
x <- 50
n
for(i in 1:n){
<- x + 2.3
x <- x / 1.5
x
}print(x)
[1] 4.6
Aan het einde van de loop is x
gelijk aan 4.6
.
e
<- 14
x <- 100
n
for(i in 1:n){
<- x + 2.3
x <- x / 1.5
x
}print(x)
[1] 4.6
Aan het einde van deze loop is x
ook gelijk aan 4.6
!
f. Als we de waarde van x
elke stap printen, zien we daarom d en e hetzelfde antwoord geven:
<- 14
x <- 100
n
for(i in 1:n){
<- x + 2.3
x <- x / 1.5
x cat('In stap', i, 'is de waarde van x', x, '\n')
}
In stap 1 is de waarde van x 10.86667
In stap 2 is de waarde van x 8.777778
In stap 3 is de waarde van x 7.385185
In stap 4 is de waarde van x 6.45679
In stap 5 is de waarde van x 5.83786
In stap 6 is de waarde van x 5.42524
In stap 7 is de waarde van x 5.15016
In stap 8 is de waarde van x 4.966773
In stap 9 is de waarde van x 4.844516
In stap 10 is de waarde van x 4.76301
In stap 11 is de waarde van x 4.708674
In stap 12 is de waarde van x 4.672449
In stap 13 is de waarde van x 4.648299
In stap 14 is de waarde van x 4.6322
In stap 15 is de waarde van x 4.621466
In stap 16 is de waarde van x 4.614311
In stap 17 is de waarde van x 4.609541
In stap 18 is de waarde van x 4.60636
In stap 19 is de waarde van x 4.60424
In stap 20 is de waarde van x 4.602827
In stap 21 is de waarde van x 4.601885
In stap 22 is de waarde van x 4.601256
In stap 23 is de waarde van x 4.600838
In stap 24 is de waarde van x 4.600558
In stap 25 is de waarde van x 4.600372
In stap 26 is de waarde van x 4.600248
In stap 27 is de waarde van x 4.600165
In stap 28 is de waarde van x 4.60011
In stap 29 is de waarde van x 4.600074
In stap 30 is de waarde van x 4.600049
In stap 31 is de waarde van x 4.600033
In stap 32 is de waarde van x 4.600022
In stap 33 is de waarde van x 4.600015
In stap 34 is de waarde van x 4.60001
In stap 35 is de waarde van x 4.600006
In stap 36 is de waarde van x 4.600004
In stap 37 is de waarde van x 4.600003
In stap 38 is de waarde van x 4.600002
In stap 39 is de waarde van x 4.600001
In stap 40 is de waarde van x 4.600001
In stap 41 is de waarde van x 4.600001
In stap 42 is de waarde van x 4.6
In stap 43 is de waarde van x 4.6
In stap 44 is de waarde van x 4.6
In stap 45 is de waarde van x 4.6
In stap 46 is de waarde van x 4.6
In stap 47 is de waarde van x 4.6
In stap 48 is de waarde van x 4.6
In stap 49 is de waarde van x 4.6
In stap 50 is de waarde van x 4.6
In stap 51 is de waarde van x 4.6
In stap 52 is de waarde van x 4.6
In stap 53 is de waarde van x 4.6
In stap 54 is de waarde van x 4.6
In stap 55 is de waarde van x 4.6
In stap 56 is de waarde van x 4.6
In stap 57 is de waarde van x 4.6
In stap 58 is de waarde van x 4.6
In stap 59 is de waarde van x 4.6
In stap 60 is de waarde van x 4.6
In stap 61 is de waarde van x 4.6
In stap 62 is de waarde van x 4.6
In stap 63 is de waarde van x 4.6
In stap 64 is de waarde van x 4.6
In stap 65 is de waarde van x 4.6
In stap 66 is de waarde van x 4.6
In stap 67 is de waarde van x 4.6
In stap 68 is de waarde van x 4.6
In stap 69 is de waarde van x 4.6
In stap 70 is de waarde van x 4.6
In stap 71 is de waarde van x 4.6
In stap 72 is de waarde van x 4.6
In stap 73 is de waarde van x 4.6
In stap 74 is de waarde van x 4.6
In stap 75 is de waarde van x 4.6
In stap 76 is de waarde van x 4.6
In stap 77 is de waarde van x 4.6
In stap 78 is de waarde van x 4.6
In stap 79 is de waarde van x 4.6
In stap 80 is de waarde van x 4.6
In stap 81 is de waarde van x 4.6
In stap 82 is de waarde van x 4.6
In stap 83 is de waarde van x 4.6
In stap 84 is de waarde van x 4.6
In stap 85 is de waarde van x 4.6
In stap 86 is de waarde van x 4.6
In stap 87 is de waarde van x 4.6
In stap 88 is de waarde van x 4.6
In stap 89 is de waarde van x 4.6
In stap 90 is de waarde van x 4.6
In stap 91 is de waarde van x 4.6
In stap 92 is de waarde van x 4.6
In stap 93 is de waarde van x 4.6
In stap 94 is de waarde van x 4.6
In stap 95 is de waarde van x 4.6
In stap 96 is de waarde van x 4.6
In stap 97 is de waarde van x 4.6
In stap 98 is de waarde van x 4.6
In stap 99 is de waarde van x 4.6
In stap 100 is de waarde van x 4.6
De waarde van x
in deze berekening geconvergeerd in 41 stappen al naar 4.6. Daarom is na zowel 50 als na 100 stappen het antwoord 4.6
. Echter zijn dit wel afrondingen, want als je het aantaal decimalen in R op 20 zet met options(digits=20)
, dan zie je dat de waarden eigenlijk 4.6000000147422879238
en 4.6000000000000005329
zijn.
a. Vijf kolommen. Dit is geen CSV (comma-separated-values) bestand, want de kolommen zijn gescheiden door spaties, niet komma’s.
b.
nrow(covid) # 52, dus dat klopt
ncol(covid) # 1, dit is fout! Alle data wordt als 1 kolom ingelezen.
c.
ncol(covid) # 5, precies goed!
nrow(covid) # 53, dat is 1 te veel...
View(covid) # Aha... de kolomnamen worden als "eerste rij" ingelezen...
d.
mean(covid$positieve_testen) # gemiddeld 1563.5 positieve testen per week
e.
head(covid,n=12)
f.
# Lees het bestand covid.txt op de website in met 'read.table'
<- read.table("http://tbb.bio.uu.nl/bvd/bms/data/covid.txt",header=T)
covid str(covid)
# 5 rijen (observaties) en
# 5 kolommen (variables),
# allemaal van type 'int' (integer: gehele getallen)
# deze zelfde informatie kan je ook op andere manieren verkrijgen
nrow(covid) # 52
ncol(covid) # 5
typeof(covid$week) # integer (geheel getal)
g.
# Lees het bestand covid.txt op de website in met 'read.table'
<- read.table("http://tbb.bio.uu.nl/bvd/bms/data/covid.txt",header=T)
covid <- covid[14:19,] # selecteer rij 14:19
covid_subset
<- covid_subset$datapunt # alle x-punten in een vector
x <- covid_subset$positieve_testen # alle y-punten in een vector
y
plot(x,y, type='b',lwd=2, log="y",
xlab="Datapunt", ylab="Aantal positieve testen (log-schaal)",
col="darkblue", main="Aantal positieve Covid-19 testen in Utrecht")
h.
<- read.table("http://tbb.bio.uu.nl/bvd/bms/data/covid.txt",header=T)
covid <- covid$datapunt # alle x-punten in een vector
x <- covid$positieve_testen # alle y-punten in een vector
y
plot(x,y, type='b',lwd=2, log="y",
xlab="Datapunt", ylab="Aantal positieve testen (log-schaal)",
col="darkblue", main="Aantal positieve Covid-19 testen in Utrecht\nDikkere punten geven pieken weer")
<- covid[covid$positieve_testen > 1000,]
covid_subset <- covid_subset$datapunt # alle x-punten in een vector
x <- covid_subset$positieve_testen # alle y-punten in een vector
y
points(x,y, lwd=5, log="y", col="darkblue")
a.
for(i in 1:12){
<- sample(1:6,1) # getal van 1 t/m 6 (dobbelsteen worp)
dobbelsteen if(dobbelsteen>=4) cat(paste("Worp nummer",i,"is",dobbelsteen,"\n"))
}
b.
<- 0
aantal_keren_hoera for(e in 1:100){
<- 0
aantal_keren_6 for(i in 1:12){
<- sample(1:6,1) # getal van 1 t/m 6 (dobbelsteen worp)
dobbelsteen if(dobbelsteen ==6) aantal_keren_6 <- aantal_keren_6 + 1
}if(aantal_keren_6==1) {
cat("Hoera!\n")
<- aantal_keren_hoera + 1
aantal_keren_hoera
}else{
cat("Niet hoera :(\n")
}
}cat("Er is in totaal", aantal_keren_hoera, "keer 'Hoera!' geprint\n")
Oefentoetsje R
a. Een matrix is een tabel met allemaal dezelfde type waarden, terwijl een dataframe voor elke kolom een ander type data kan bevatten.
b. Hoewel er een nummer staat, is x
van het type ‘character’ omdat het tussen aanhalingstekens staat.
c. De tweede waarde van de vector x is 1.5.
<- seq(1,10,by=0.5)
x 2] x[
d. De vector x bevat nu alle gehele getallen van 10 tot en met 1. De eerste waarde van deze vector is 10.
<- 10:1
x 1] x[
e. x[1] weet je niet, want runif geeft willekeurig getallen. Je weet wél dat het getal tussen 0 en 1 zal liggen. x[11] bestaat niet, want er zijn maar 10 getallen gegenereerd R geeft in dit geval ‘NA’ (not available).
f. Om voor ieder persoon de score “per minuut” te berekenen, moeten we de score door het aantal minuten delen (“per” kun je eigenlijk altijd lezen als “gedeeld door”). Dit kunnen we doen door met het dollar-teken de kolommen te pakken, en deze door elkaar te delen. Deze nieuwe vector (hieronder ‘spm’) kan je dan ook als nieuwe kolom aan de dataframe toevoegen:
<- df$score/df$minuten
spm $score_per_minuut <- spm df
g. dieren[2,3:4] geeft rij 2, kolom 3 en 4 terug. Let op: de eerste regel zijn de kolomnamen, dus de 2e rij is niet Joey, maar Roos! Daarom geeft dieren[2,3:4] de waarden “wit” en “energiek”.
h. De waarde begint op 1, en dan loopt de for-loop over de waarden 1, 2 en 3. Deze waarden worden steeds aan a toegevoegd. Dus er wordt eerst 1, dan 2, en dan nog een keer 3 bij a opgeteld. Aan het einde is a dus 1+1+2+3 = 7.
i.
a -> C
b -> B
c -> E
d -> A
e -> D
f -> F
j. Optie d geeft geen serie van 1 t/m 10, maar een vector met daarin alleen 1 en 10.
k. Optie b. In R gebruik je vierkante haken om te ‘indexeren’. Omdat het een vector is heb je geen komma’s nodig om onderscheid te maken tussen rijen en kolommen.
l. Optie b. Drie is niet groter dan vijf, dus zal R ‘FALSE’ teruggeven.
m. Optie d. Vanaf de tweede waarde (20) zijn alle getallen groter dan óf gelijk aan 20. Let op: hier worden deze waarden (nog) niet geselecteerd!
n. Optie h. Vanaf de tweede waarde (20) zijn alle getallen groter dan óf gelijk aan 20. Anders dan de vorige vraag, selecteren we hier deze opties, en krijgen we 20, 30, 40 terug.