---
title: '7'
output: html_document
---
# Funktsioonid
## Geomeetriline keskmine
Omavahelise kokkukorrutamise tarbeks õnnestus leida funktsioon prod.
```{r}
gm1 <- function(x){
prod(x)^(1/length(x))
}
arvud=c(4, 9)
gm1(arvud)
arvud2=c(1, 2, 32)
gm1(arvud2)
```
Kokku korrutamine konspektis mainitud Recall-i abil
```{r}
kokkukorrutus <- function(x) if(length(x)>1) Recall(c(x[1]*x[2], x[-(1:2)])) else x
kokkukorrutus(arvud)
```
Astendustehte kasutamine nimelise funktsioonina
```{r}
gm2 <- function(x){
"^"(kokkukorrutus(x), 1.0/length(x))
}
gm2(arvud2)
```
Kokkukorrutus for-tsükli abil
```{r}
gm3 <- function(x){
puhver=1
for(arv in x){
puhver<-puhver*arv
}
puhver^(1/length(x))
}
gm3(arvud2)
```
Reduce-funktsiooni proov korrutise leidmiseks
```{r}
Reduce("*", arvud2)
```
## Keskmise ja standardhälbe leidmine
```{r}
analyys1 <- function(x){
vastus=c(mean(x), sd(x))
names(vastus)=c("keskmine", "standardhalve")
vastus
}
analyys1(c(3, 4, 6, 5))
```
Puuduvate väärtustega jäädakse esialgu hätta
```{r}
analyys1(c(3, 4, 6, 5, NA))
```
Puuduvate väärtuste ning komakohtade arvu määramine parameetrite kaudu. Võimalus laduda arve otse väärtuste juurde. Vektoriks tegemine paistab, et võimaldab sisendisse väärtusi segiläbi anda.
Omamoodi harjumatu, et ka väljundvektoris (mitte listis) võivad vastuselementidel olla nimed - aga samas nõnda mugav tulemusi vaadata.
```{r}
analyys2 <- function(..., na.rm=TRUE, komakohti=20){
x=c(...)
vastus=c(round(mean(x, na.rm=na.rm), komakohti),
round(sd(x, na.rm=na.rm), komakohti))
names(vastus)=c("keskmine", "standardhalve")
vastus
}
analyys2(3, 4, 6, 5)
analyys2(c(3, 4, 6, 5), 2, 3)
analyys2(c(3, 4, 6, 5), 2, 3, komakohti=2)
analyys2(3, 4, 6, 5, NA)
analyys2(3, 4, 6, 5, NA, na.rm=FALSE)
```
## Mündi viskamise funktsioon
```{r}
mynt1<-function(kogus){
sample(c("KULL", "KIRI"), kogus, replace=TRUE)
}
mynt1(10)
```
## Andmed sagedustabelina
```{r}
mynt2<-function(kogus){
table(mynt1(kogus))
}
mynt2(10)
```
Funktsioon rle näitab järjest, mitu korda millist tulemust tuli. Et parasjagu soovitakse vaid suurimat järjestikkust pikkust ning pole tähtis, kumb mündi külg sellega oli, siis piisab suurima väärtuse leidmisest.
```{r}
mynt3<-function(kogus){
max(rle(mynt1(kogus))$lengths)
}
mynt3(10)
```
# Funktsioonide töökiirused ja kõlbulikud vahemikud
Rekursiivne väljakutse saab tuhandega hakkama, kuid edasi läheb raskeks
```{r, error=TRUE}
summa1 <- function(v) if(length(v)>1) Recall(c(v[1]+v[2], v[-(1:2)])) else v
summa1(1:1000)
system.time(summa1(1:1000))
summa1(1:10000)
system.time(summa1(1:10000))
```
Plussmärkidega ühendamine kannatab natukene rohkem
```{r}
summa2 <- function(v) Reduce("+", v)
summa2(1:1000)
system.time(summa2(1:1000))
summa2(1:10000)
system.time(summa2(1:10000))
summa2(1:100000)
system.time(summa2(1:100000))
```
Tsükliga on veel kümme miljonit täiesti arvutatav
```{r}
summa3 <- function(v) {
summa <- 0
for(i in 1:length(v)) summa <- summa + v[i]
summa
# tulemuse tagastamine, sama, mis return(summa)
}
summa3(1:1000)
system.time(summa3(1:1000))
summa3(1:10000)
system.time(summa3(1:10000))
summa3(1:100000)
system.time(summa3(1:100000))
summa3(1:1000000)
system.time(summa3(1:1000000))
summa3(1:10000000)
system.time(summa3(1:10000000))
```
Igakord vektori ümber kopeerimine paistab aeganõudev olema
```{r}
summa4 <- function(v) {
summa <- 0
repeat{
summa <- summa + v[1]
v <- v[-1]
if(length(v) == 0) break
}
summa
}
summa4(1:10000)
system.time(summa4(1:10000))
summa4(1:100000)
system.time(summa4(1:100000))
```
Seda sõltumata kasutatavast korduslausest
```{r}
summa5 <- function(v) {
summa <- 0
while(length(v)>0){
summa <- summa + v[1]
v <- v[-1]
}
summa
}
summa5(1:10000)
system.time(summa5(1:10000))
summa5(1:100000)
system.time(summa5(1:100000))
```
Valmisstringi loomine toimib ka vaid lühemate lahenduste korral
```{r, error=TRUE}
summa6 <- function(v) {
txt <- paste(v, collapse="+")
eval(parse(text=txt))
}
summa6(1:1000)
system.time(summa6(1:1000))
summa6(1:10000)
system.time(summa6(1:10000))
```
Ametlik funktsioon kohandatud ka suuremate koguste tarbeks, sada miljonit veel täiesti "söödav"
```{r}
mean(1:1000)
system.time(mean(1:1000))
mean(1:10000)
system.time(mean(1:10000))
mean(1:100000)
system.time(mean(1:100000))
mean(1:1000000)
system.time(mean(1:1000000))
mean(1:10000000)
system.time(mean(1:10000000))
mean(1:100000000)
system.time(mean(1:100000000))
#mean(1:1000000000) #miljard
#system.time(mean(1:1000000000))
#Error: cannot allocate vector of size 3.7 Gb
#In addition: Warning messages:
#1: In mean(1:1e+09) :
# Reached total allocation of 3792Mb: see #help(memory.size)
```
# Vektorite summa funktsioon
Tühja vektori loomiseks olen näinud mitmesuguseid trikke. Nullide rida tundub loogiline. Samas tundub, et olemasolevasse vektorisse saab vajadusel elemente ka juurde "pressida".
```{r, error=TRUE}
veksum1 <- function(a, b){
if(length(a)!=length(b)){
stop("vektorid on erineva pikkusega")
}
vc=rep(0, length(a))
for(i in 1:length(a)){
vc[i]=a[i]+b[i]
}
vc
}
veksum1(c(2, 3), c(3, 4, 5))
veksum1(c(2, 3, 4), c(3, 4, 5))
```
Sama sapply abil
```{r}
veksum2 <- function(a, b){
if(length(a)!=length(b)){
stop("vektorid on erineva pikkusega")
}
sapply(1:length(a), function(koht){a[koht]+b[koht]})
}
veksum2(c(2, 3, 4), c(3, 4, 5))
```
Kiiruste võrdlus
```{r}
system.time(veksum1(1:100000, 1000001:1100000))
system.time(veksum2(1:100000, 1000001:1100000))
```