Ohjelmointi

R on täysiverinen ohjelmointiympäristö, aivan samoin kuin serkkunsa S.. R:ssä on ohjelmointikielelle välttämättömät ehtorakenteet (if, ifelse, switch) ja toistorakenteet (for, while, repeat). Monessa R- ja S.-oppaassa pääpaino onkin ohjelmoinnissa (esim. R-intro, 2000). Ei kuitenkaan tässä oppaassa. Esitän vain yhden yksinkertaisen näytteen oman funktion kirjoittamisesta -- lisäohjeita ja esimerkkejä löytyy sekä muista oppaista että katsomalla, miten R-funktiot on kirjoitettu. Suuri osa R:n komennoista on näet kirjoitettu R-kielellä ja käyttäjän itse kirjoittama funktio on aivan samassa asemassa ja yhtä tehokas kuin moni R-komento. Kirjoittamalla komentonimen ilman sulkuja, R tulostaa komennon näytölle ihmeteltäväksi.

Esimerkkimme on hyvin lyhyt, mutta voimakas. Kirjoitan pienen funktion, joka simuloi lajin havaittuja runsauksia ekologisella gradientilla. Olettakaamme, että lajin odotettu runsaus $ \mu$ gradientin arvolla x määräytyy gaussilaisen responssimallin mukaan:

$\displaystyle \mu$ = h exp$\displaystyle \left[\vphantom{ -\frac{(x-u)^2}{2t^2} }\right.$ - $\displaystyle {\frac{{(x-u)^2}}{{2t^2}}}$$\displaystyle \left.\vphantom{ -\frac{(x-u)^2}{2t^2} }\right]$ (2)

missä lajin responssifunktion parametrit ovat lajin optimin sijainti gradientilla (u), lajin odotettu runsaus optimissa (h) sekä lajin responssin leveyttä kuvaava parametri (t). Todelliset havainnot eivät kuitenkaan ole virheettömiä, joten meidän on simuloitava satunnaisuutta. R:ssä on suuri joukko funktioita, jotka generoivat satunnaislukuja erilaisista jakaumista. Tässä esimerkissä simuloimme havaittuja runsauksia, joten tarvitsemme Poisson-jakautuneita satunnaislukuja eli funktiota rpois. Muita usein tarvittuja vaihtoehtoja ovat tasainen jakauma (runif) sekä normaalijakauma (rnorm), mutta vaihtoehtoja on paljon lisää. Gaussilainen mallimme antaa odotusarvon $ \mu$, jota käytämme Poisson-jakauman parametrina ja tuotamme satunnaislukuja y eli formaalisemmin y $ \sim$ P($ \mu$).

Meidän tarvitsee kirjoittaa vain pari riviä:

> gausresp <- function(x, h=1, u=0, t=1) {
    mu <-  h*exp(-(x-u)^2/2/t^2) # Yhtälö 2
    y <- rpois(length(mu), mu)   # Poisson satunnaisluku
    y
  }

Funktiolla on neljä parametria, joista vain gradientin arvo (x) on pakollinen ja muille on oletusarvot.

Ensi katsomalta funktio näyttää melko hyödyttömältä, sillä se näyttää hyväksyvän vain yhden gradienttiarvon. Muistakaamme kuitenkin, että jos laskutoimituksen tekijä on vektori, muita tekijöitä kierrätetään eli voimme kutsua funktiota x-vektorilla:

> gausresp(seq(4.5,6.9,length=18), u=5.3, h=8.2)
 [1]  4  6  5  7  4 10  4  3 10  9  7  7  5  6  5  3  2  4

Koska lajin parametrit olivat nimettyjä, saimme antaa ne mielivaltaisessa järjestyksessä eikä meidän tarvinnut antaa parametria t, koska käytimme sen odotusarvoa.

Monessa tilastollisessa ohjelmassa on makroja, mutta R:ssä on funktioita. Makrot ovat eräänlaisia lyhenteitä komennoille, jotta ei tarvitsisi aina kirjoittaa pitkiä, toistuvia komentoketjuja. Suoritettaessa makro laajenee normaaliin istuntoon. Jos meillä olisi ollut ennestään muuttujat mu tai y, makro olisi antanut näille uudet arvot ja alkuperäiset olisivat tuhoutuneet. Funktiolla sen sijaan on yksityinen nimiavaruus, eli voimme turvallisesti käyttää funktiossa samoja nimiä kuin istunnossa. Toisaalta funktio ei palauta mitään ellemme erityisesti pyydä: tämän takia yksinäinen ``y'' viimeisellä rivillä palauttamaan tulokset kutsuvalle ohjelmalle. Sen sijaan muuttujan mu arvoja emme koskaan saa tietää kutsuvassa ohjelmassa. Perustellusti voisi tietysti vaatia, että saisimme tiedon myös mu:n arvoista, tai ainakin käytetyistä x:n arvoista sekä lajin parametreista. Tämä olisi voitu hoitaa palauttamalla luettelo (luku 3.8) yksittäisen y-vektorin sijaan. Tämä olisi tapahtunut korvaamalla viimeinen rivi ``y'' riveillä:

    out <- list(gradient=x, simulated=y, h, u, t)
    out
Virallista luettelomuotoa (§3.8) tarvittiin vain kun haluttiin antaa muuttujalle uusi nimi luettelossa. Jo tällaisenaan funktiomme on etenkin virhejakauman suhteen parempi kuin monet suositut simulointiohjelmat ja helposti kehitettävissä monimutkaisempiin tilanteisiin.


Jari Oksanen 2003-01-21