-
Notifications
You must be signed in to change notification settings - Fork 3
/
05-funktsioonid.Rmd
221 lines (176 loc) · 7.43 KB
/
05-funktsioonid.Rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
# Funktsioonid on R keele verbid {#funs}
Kasutaja ütleb nii täpselt kui oskab, mida ta tahab ja R-s elab kratt, kes püüab ära arvata, mida on vaja teha.
Vahest teeb kah.
Vahest isegi seda, mida kasutaja tahtis.
Mõni arvab, et R-i puudus on veateadete puudumine või krüptilised veateated.
Sama kehtib ka R-i helpi kohta.
Seega tasub alati kontrollida, kas R ikka tegi seda, mida sina talle enda arust ette kirjutasid.
Paljudel juhtudel ütleb (hea) funktsiooni nimi mida see teeb:
```{r}
# create two test vectors
x <- c(6, 3, 3, 4, 5)
y <- c(1, 3, 4, 2, 7)
```
```{r}
# calculate correlation
cor(x, y)
# calculate sum
sum(x)
# calculate sum of two vectors
sum(x, y)
# calculate average
mean(x)
# calculate median
median(x)
# calculate standard deviation
sd(x)
# return quantiles
quantile(x)
# return maximum value
max(x)
# return minimum value
min(x)
```
R-is teevad asju programmikesed, mida kutsutakse **funktsioonideks**.
Te võite mõelda funktsioonist nagu verbist.
Näiteks funktsiooni `sum()` korral loe: "võta summa".
Iga funktsiooni nime järel on sulud.
Nende sulgude sees asuvad selle funktsiooni **argumendid**.
Argumendid määravad ära funktsiooni käitumise.
Et näha, millised argumendid on funktsiooni käivitamiseks vajalikud ja milliseid on üldse võimalik seadistada, kasuta 'help' käsku.
```{r}
?sum
```
Help paneelis paremal all ilmub nüüd selle funktsiooni R dokumentatsioon.
Vaata seal peatükki Usage: `sum(..., na.rm = FALSE)` ja edasi peatükki Arguments, mis ütleb, et `...` (ellipsis) tähistab vektoreid.
sum {base} R Documentation
Sum of Vector Elements
Description:
sum returns the sum of all the values present in its arguments.
Usage
sum(..., na.rm = FALSE)
Arguments
... - numeric or complex or logical vectors.
na.rm - logical. Should missing values (including NaN) be removed?
Seega võtab funktsioon `sum()` kaks argumenti: vektori arvudest (või loogilise vektori, mis koosneb TRUE ja FALSE määrangutest), ning "na.rm" argumendi, millele saab anda väärtuseks kas, TRUE või FALSE.
Usage ütleb ka, et vaikimisi on `na.rm = FALSE`, mis tähendab, et sellele argumendile on antud vaikeväärtus -- kui me seda ise ei muuda, siis jäävad NA-d arvutusse sisse.
Kuna NA tähendab "tundmatu arv" siis iga tehe NA-dega annab vastuseks "tundmatu arv" ehk NA (tundmatu arv + 2 = tundmatu arv).
Seega NA tulemus annab märku, et teie andmetes võib olla midagi valesti.
```{r}
## moodustame vektori
apples <- c(1, 34, 43, NA)
## arvutame summa
sum(apples, na.rm = TRUE)
```
Niimoodi saab arvutada summat vektorile nimega "apples".
Sisestades R käsureale funktsiooni ilma selle sulgudeta saab masinast selle funktsiooni koodi. Näiteks:
```{r}
sum
```
Tulemus näitab, et `sum()` on `Primitive` funktsioon, mis põhimõtteliselt tähendab, et ta põhineb C koodil ja ei kasuta R koodi.
## Kirjutame R funktsiooni
Võib ju väita, et funktsiooni ainus mõte on peita teie eest korduvad vajalikud koodiread kood funktsiooni nime taha.
Põhjus, miks R-s on funktsioonid, on korduse vähendamine, koodi loetavaks muutmine ja seega ka ruumi kokkuhoid.
Koodi funktsioonidena kasutamine suurendab analüüside reprodutseeritavust, kuna funktsioonis olev kood pärineb ühest allikast, mitte ei ole paljude koopiatena igal pool laiali.
See muudab pikad koodilõigud hõlpsalt taaskasutatavaks sest lihtsam on kirjutada lühike funktsiooni nimi ja sisestada selle funktsiooni argumendid.
Koodi funktsioonidesse kokku surumine vähendab võimalusi lollideks vigadeks, mida te võite teha pikkade koodijuppidega manipuleerides.
Seega tasub teil õppida ka oma korduvaid koodiridu funktsioonidena vormistama.
Kõige pealt kirjutame natuke koodi.
```{r}
# two apples
apples <- 2
# three oranges
oranges <- 3
# parentheses around expression assigning result to an object
# ensure that result is also printed to R console
(inventory <- apples + oranges)
```
Ja nüüd pakendame selle tehte funktsiooni `add2()`.
Funktsiooni defineerimiseks kasutame järgmist r ekspressiooni `function( arglist ) expr`, kus "arglist" on tühi või ühe või rohkema nimega argumenti kujul `name=expression`; "expr" on R-i ekspressioon st. kood mida see funktsioon käivitab.
Funktsiooni viimane evlueeritav koodirida on see, mis tuleb välja selle funktsiooni outputina.
All toodud näites on selleks `x + y` tehte vastus.
```{r}
add2 <- function(x, y) {
x + y
}
```
Seda koodi jooksutades näeme, et meie funktsioon ilmub R-i Environmenti, kuhu tekib Functions lahter.
Seal on näha ka selle funktsiooni kaks argumenti, apples ja oranges.
Antud funktsiooni käivitamine annab veateate, sest funktsiooni argumentidel pole väärtusi:
```{r}
## run function in failsafe mode
inventory <- try(add2())
## when function fails, error message is returned
class(inventory)
## print error message
cat(inventory)
```
Andes funktsiooni argumentidele väärtused, saab väljundi:
```{r}
## run function with proper arguments
inventory <- add2(x = apples, y = oranges)
## numeric vector is returned
class(inventory)
## result
inventory
```
**Nüüd midagi kasulikumat!**
Funktsioon standrardvea arvutamiseks (baas R-s sellist funktsiooni ei ole):
`sd()` funktsioon arvutab standardhälbe.
Sellel on kaks argumenti: `r paste(names(formals(sd)), collapse = " and ")`.
Me teame, et SEM=SD/sqrt(N)
kus N = length(x)
```{r}
calc_sem <- function(x) {
stdev <- sd(x)
n <- length(x)
stdev / sqrt(n)
}
```
x hoiab lihtsalt kohta andmetele, mida me tahame sinna funktsiooni suunata.
`sd()`, `sqrt()` ja `length()` on olemasolevad baas R funktsioonid, mille me oma funktsiooni hõlmame.
```{r}
## create numeric vector
numbers <- c(2, 3.4, 54, NA, 3)
calc_sem(numbers)
```
No jah, kui meil on andmetes tundmatu arv (`NA`) siis on ka tulemuseks tundmatu arv.
Sellisel juhul tuleb NA väärtused vektorist enne selle funktsiooni kasutamist välja visata:
```{r}
numbers_filtered <- na.omit(numbers)
calc_sem(numbers_filtered)
```
On ka võimalus funktsiooni sisse kirjutada **NA väärtuste käsitlemine**. Näiteks, üks võimalus on **anda viga** ja funktsioon katkestada, et kasutaja saaks ise ühemõtteliselt oma andmetest NA väärtused eemaldada.
Teine võimalus on funktsioonis **NA-d vaikimisi eemaldada** ja anda selle kohta näiteks teade.
NA-de vaikimisi eemaldamiseks on hetkel mitu võimalust, kasutame kõigepealt nö. valet lahendust:
```{r}
calc_sem <- function(x) {
## kasutame sd funktsiooni argumenti na.rm
stdev <- sd(x, na.rm = TRUE)
n <- length(x)
stdev / sqrt(n)
}
calc_sem(numbers)
```
See annab meile vale tulemuse sest `na.rm = TRUE` viskab küll NA-d välja meie vektorist aga jätab vektori pikkuse muutmata (`length(x)` rida).
Teeme uue versiooni oma funktsioonist, mis viskab vaikimisi välja puuduvad väärtused, kui need on olemas ja annab siis ka selle kohta hoiatuse.
```{r}
## x on numbriline vektor
calc_sem <- function(x) {
## viskame NA väärtused vektorist välja
x <- na.omit(x)
## kui vektoris on NA väärtusi, siis hoiatame kasutajat
if(inherits(na.action(x), "omit")) {
warning("Removed NAs from vector.\n")
}
## arvutame standardvea kasutades filtreeritud vektorit
stdev <- sd(x)
n <- length(x)
stdev / sqrt(n)
}
calc_sem(numbers)
length(numbers)
```
Missugune funktsiooni käitumine valida, sõltub kasutaja vajadusest.
Rohkem infot NA käsitlemise funktsioonide kohta saab `?na.omit` abifailist.
Olgu see õpetuseks, et funktsioonide kirjutamine on järk-järguline protsess ja sellele, et alati saab paremini teha.