R-KIELEN PERUSTEET Jarno Tuimala Helsinki 2010

Koko: px
Aloita esitys sivulta:

Download "R-KIELEN PERUSTEET Jarno Tuimala Helsinki 2010"

Transkriptio

1 R-KIELEN PERUSTEET

2

3 R-KIELEN PERUSTEET Jarno Tuimala Helsinki 2010

4 Jarno Tuimala 1. painos

5 R KIELEN PERUSTEET Lukijalle Tavoitteet Tämä kirja esittelee R-kielen perusteet ja muutamia ohjelmointiin liittyviä erityisseikkoja. Koko kirjan pääpaino on R-kielen esittelyssä, mutta lisäksi tarkastellaan tilastografiikan tuottamista sekä joitakin tilastotieteen menetelmiä. Keskeisenä tavoitteena on, että kirjan luettuasi sinulla on käsitys siitä, miten R-kieltä käytetään, miten sillä voidaan suorittaa suhteellisen yksinkertaisia ohjelmointitehtäviä ja miten sen avulla voidaan tuottaa tilastografiikkaa ja -analyysejä. Kenelle tämä kirja on tarkoitettu Kirja on tarkoitettu kaikille R-kielestä kiinnostuneille. Erityisesti toivon kirjan palvelevan niin menetelmätieteiden kuin soveltavien alojen opiskelijoita yliopistoissa ja ammattikorkeakouluissa. R:n käyttöä on vaikeuttanut hyvän suomenkielisen oppimateriaalin puuttuminen. Toivon tämän kirjan osaltaan parantavan tilannetta. Kirjan näkökulma on soveltajalle suunnattu, ja ohjelmoinnista kiinnostuneen kannattaa laajentaa tietämystään muun muassa R:n mukana tulevista käsikirjoista. Esimerkiksi R:n olio-ohjelmointia ei tässä kirjassa käsitellä lainkaan. Kirja on kirjoitettu Windows-käyttäjän näkökulmasta, mutta monet asiat toimivat samaan tapaan muissakin ympäristöissä. i

6 LUKIJALLE Kirjan rakenne Kirja on jaettu viiteen osaan. Ensimmäinen osa esittelee R:n käytön alkeet, ja toinen osa R-kielen perusteet. R-kielen perusteiden alkupään kappaleet esittelevät soveltajille oleellisen aineksen, ja loppua kohden käydään enenevissä määrin läpi ohjelmointiin liittyviä seikkoja. Kolmannessa osassa tutustutaan grafiikkaan. Pääpaino on perinteisessä tilastografiikassa. Neljäs osa on johdatus R:n tilastollisiin toimintoihin. Viidennessä osassa annetaan muutamia tapausesimerkkejä R:n käytöstä eri aloilla. Lukuohjeita Kirjassa on paljon R-koodia. Koodi, joka kirjoitetaan R:n komentoriville on ladottu tasavälisellä kirjasintyypillä: # Luo vektorin luvuista 1-10 > a<-c(1:10) Merkillä > alkavat rivit sisältävät R-komentoja. Merkillä # alkavat rivit ovat puolestaan kommentteja, eikä R suorita niitä, vaikka ne komentoriville kirjoitettaisiinkin. Ne voi siis huoletta jättää kirjoittamatta. Ne palvelevat vain sitä tarkoitusta, että koodiesimerkit tulevat toisinaan ymmärrettävämmiksi, kun koodirivien välissä on selventäviä kommentteja. R:n tulostus on ladottu niinikään tasavälisellä kirjasintyypillä, mutta koko on tarvittaessa hieman pienempi kuin varsinaisen koodin: > a [1] Kirjan koodiesimerkkejä kannattaa testata itse R:ssä, sillä se edistää oppimista ja koodiesimerkkien eri vaiheiden ymmärtämistä. Samalla kannattaa tutustua myös kaikkien uusien komentojen ohjesivuihin, jotta niiden käyttö tulee tutuksi ja luontevaksi. Kirjan kotisivu Kirjalla on kotisivu, joka sijaitsee Internetissä osoitteessa Sivulta löytyvät kirjan esimerkeissä käytetyt aineistot sekä mahdolliset painovirhekorjaukset. ii

7 R KIELEN PERUSTEET Muu kirjallisuus Tämän kirjan pyrkimyksenä ei ole esitellä edes suurta osaa R:n toiminnallisuudesta, vaan tarkoituksena on toimia johdantona muutamiin keskeisiin seikkoihin. Niinpä lukijan onkin tutustuttava muihin lähteisiin, erityisesti jos on kiinnostunut monimutkaisemmasta ohjelmoinnista tai uusien laajennuspakettien kehittämisestä. Seuraavassa on muutamia hyväksi havaitsemia teoksia, joiden avulla tämän kirjan materiaalia on mahdollista syventää. R:n mukana tulee valikoima erilaisia käsikirjoja, jotka syventävät R:n perusteita, laajennuspakettien kehittämiseen liittyviä seikkoja, aineistojen lukemisen ja kirjoittamisen yksityiskohtia sekä R:n toiminnan yksityiskohtia. Mainittuja kirjoja voi lukea myös Internetissä osoitteessa: Erityisen hyviä ohjelmointiin keskittyviä kirjoja ovat Robert Gentleman. R Programming for Bioinformatics. Computer Science & Data Analysis. Chapman & Hall/CRC, Boca Raton, FL, ISBN John M. Chambers. Software for Data Analysis: Programming with R. Springer, New York, ISBN Grafiikasta ja tilastografiikasta kertovat ymmärrettävästi: Paul Murrell. R Graphics. Chapman & Hall/CRC, Boca Raton, FL, ISBN X Deepayan Sarkar. Lattice: Multivariate Data Visualization with R. Springer, New York, ISBN Hadley Wickham. ggplot: Elegant Graphics for Data Analysis. Use R. Springer, ISBN: Tilastollisiin analyyseihin johdattavia yleisteoksia ovat: Peter Dalgaard. Introductory Statistics with R. Springer, 2nd edition, ISBN Michael J. Crawley. Statistics: An Introduction using R. Wiley, ISBN William N. Venables and Brian D. Ripley. Modern Applied Statistics with S. Fourth Edition. Springer, New York, ISBN Frank E. Harrell. Regression Modeling Strategies, with Applications iii

8 LUKIJALLE to Linear Models, Survival Analysis and Logistic Regression. Springer, ISBN Muita erityisesti R:n käyttöön liittyviä kirjoja voi etsiä osoitteesta jossa sijaitsee jokseenkin kattava lista painetuista oppaista, joissa R:n käyttöä käsitellään. Lisäksi kannattaa tutustua osoitteessa sijaitsevaa listaan käyttäjien kirjoittamista käsikirjoista. Kiitokset Kiitän kaikkia kursseilleni osallistuneita opiskelijoita. Teidän avullanne tämä kirja on hioutunut pikku hiljaa lopulliseen muotoonsa. Tämä kirja on kirjoitettu OpenOffice.org:n Writer-ohjelmalla, ja kuvat on tarvittaessa käsitelty Gimp-ohjelmalla. Käyttöjärjestelmää lukuunottamatta kirja on kokonaisuudessaan laadittu ilmaisilla avoimen lähdekoodin työkaluilla. Ilman niitä tämän kirjan luominen ei olisi ollut mahdolista. Esitänkin kiitokseni kaikille mainittuihin projekteihin panoksensa antaneille. Kirjoittajasta Jarno Tuimala on perinnöllisyystieteen tohtori. Hän on toiminut tutkijana Helsingin yliopistossa ja Työterveyslaitoksella sekä bioinformatiikan asiantuntijana Tieteen Tietotekniikan Keskus CSC:ssä. Tällä hetkellä hän työskentelee tilastotieteilijänä Suomen Punaisen Ristin Veripalvelussa. iv

9 R - KIELEN PERUSTEET R-alkeet Tässä luvussa käydään läpi R:n asentaminen ja laajentaminen sekä yleistä toiminnallisuutta, kuten käytön aloittamiseen ja lopettamiseen liittyvät toimenpiteet ja erilaisten apu- ja ohjetoimintojen käyttö. R-kielen alkeet ja käyttö esitellään luvussa R-kielen perusteet. Halutessaan lukija voi hypätä tämän luvun yli suoraan R-kielen perusteisiin, ja palata tässä esitettyihin asioihin tarvittaessa. Mikä on R? R on avoimen lähdekoodin ohjelmisto ja ohjelmointiympäristö. Avoimen lähdekoodin ohjelmistona se on käyttäjälleen täysin ilmainen. Ohjelmalle ei ole asetettu minkäänlaisia käyttörajoituksia, ja sitä voidaan käyttää myös kaupallisiin tarkoituksiin. Ohjelmiston perustoiminnallisuuden kehittämisestä vastaa ydintiimi, mutta kehitykseen osallistuu myös laaja kansainvälinen yhteisö. R:n toiminnallisuutta on nimittäin mahdollista laajentaa erillisten pakettien avulla, ja suuri osa näistä paketeista on kehitetty ydintiimin ulkopuolella esimerkiksi alan tutkijoiden toimesta. R:llä on tällä hetkellä varsin vakiintunut asema keskeisimpänä uusien tilastollisten menetelmien kehitysalustana. Monet tutkijat jakavat menetelmänsä soveltajien käyttöön R:llä toteutettuna. Esimerkiksi biologisen tietojenkäsittelyn, bioinformatiikan, alalla tämä menettely on nykyisin hyvin yleistä. R on myös ohjelmointikieli, joten sen käyttö koostuu pitkälti erilaisten komentojen kirjoittamisesta. Työskentelytapa voi olla monille aloitteleville käyttäjille outo, ja vaatii hieman totuttelua. R:ään ei ole olemassa samanlaista graafista käyttöliittymää kuin esimerkiksi tilasto-ohjelmisto SPSS:ään, eikä varsinkaan sellaista graafista käyttöliittymää, joka sisältäisi kaiken R:n toiminnallisuuden. 1

10 ALKEET Mitä etuja R:n käytöstä on? R on usein käytössä tutkimusta ja tuotekehitystä tekevissä yksiköissä, erityisesti yliopistoissa ja tutkimuslaitoksissa siksi, että se on täysin ilmainen. R myös toimii Windows-, Macintosh- ja UNIX/Linux -järjestelmissä, joten sitä voidaan käyttää henkilökohtaisista työasemista aina supertietokoneisiin asti. Lisäksi R tarjoaa hyvän ympäristön uusien menetelmien kehitykseen ja sisältää erittäin laajan valikoiman myös sellaisia edistyneitä tilastollisia menetelmiä, joita ei muista ohjelmistoista vielä löydy. R:n graafiset ominaisuudet ovat myös vertaansa vailla. Erityisesti yrityksissä työskenteleville käyttäjille lienee tärkeää, että R toimii myös hyvin yhteen monien ulkoisten ohjelmistojen kanssa. R:stä on esimerkiksi mahdollista ottaa yhteys suoraan moniin tietokantoihin. Haettu aineisto voidaan sitten käsitellä ja analysoida R:ssä, ja tulokset voidaan raportoida vaikkapa PDF-muotoisena asiakirjana. R voidaan valjastaa myös verkkokäyttöön, jolloin asiakkaille voidaan rakentaa reaaliaikainen Internetissä toimiva raportointijärjestelmä. Haittapuolina voisi mainita, että R vaatii hieman perehtymistä. Perusasioiden hallinnan omaksuu suhteellisen nopeasti, ja alussa apuna voi käyttää joitakin yksinkertaisia graafisia käyttöliitymiä. Jos kuitenkin haluaa käyttää edistyksellisempiä tilastollisia työkaluja, on pakko opetella antamaan komentoja R-kielellä. R:n lataaminen ja asentaminen Windows-järjestelmään R:n asennusohjelman (base) voi noutaa jollakin Internet-selaimella ilmaiseksi osoitteesta Asennusohjelma löytyy CRAN (Comprehensive R Archive Network) -linkin takaa vasemmasta sivupalkista. Tämän jälkeen pitää valita latauspaikka. Suomea lähin palvelin, jolta R:n voi ladata sijaitsee Ruotsissa. Ennen varsinaisen asennusohjelman lataamista, pitää vielä valita järjestelmä, esimerkiksi Windows. Tämän jälkeen päätyy sivulle, jolta asennusohjelman voi ladata. Kirjoitushetkellä suora linkki uusimman version, , lataussivulle oli Asennusohjelma sisältää R:n ytimen (komentotulkki ym.) lisäksi kehittäjien ydintiimin keskeisimmiksi katsomat laajennuspaketit. Muut kehittäjäyhteisön tuottamat laajennuspaketit löytyvät CRAN:n contribosiosta. 2

11 R - KIELEN PERUSTEET Asennusohjelman lataamisen jälkeen se ajetaan normaalisti napauttamalla sen ikonia kahdesti hiirellä. Asennuksen aikana muutamia asetuksia kannattaa muuttaa. Jos haluaa käyttää tiettyjä graafisia käyttöliittymiä, kuten R commander -laajennuspakettia, pitää myös tcl/tk valita asennettavaksi: R:n voi asentaa Windows-järjestelmään jopa ilman pääkäyttäjän tunnuksia, kunhan valitsee asennuksen aikana, ettei halua tallentaa versionumeroa rekisteriin: 3

12 ALKEET Asennuksen päätteeksi työpöydälle ilmestyy pikakuvake, josta R:n voi käynnistää. R:n käynnistäminen R:n käynnistäminen tapahtuu samalla tavalla kuin minkä tahansa Windowsohjelman: esimerkiksi kaksoisnapauttamalla sen työpöydällä olevaa ikonia hiirellä. R avautuu oletusarvoisesti suoraan komentoriville (R Console), sillä perusasennus ei sisällä graafista käyttöliittymää: Komentorivi-ikkuna koostuu itse komentorivistä, joka on punainen suurempi kuin (>) -merkki yllä olevassa kuvassa alinna, sekä komentoriviikkunan ylälaidassa olevasta valikkopalkista. Valikkopalkin kautta ei voi suorittaa analyysejä, mutta sitä kautta pääsee esimerkiksi käsiksi ohjetoimintoihin. Komentoriville kirjoitetaan R-kielisiä komentoja. 4

13 R - KIELEN PERUSTEET Käytön aloittaminen ja lopettaminen Työkansion valitseminen R:llä työskennellessä kannattaa omaksua työtapa, jossa kunkin analyysin tai samaan projektiin liittyvät tiedostot ovat yhdessä ja samassa kansiossa. Tällöin R pääsee niihin käsiksi kaikkein yksinkertaisimmin. Ennen varsinaisten analyysien aloittamista on R:lle kuitenkin ensin kerrottava, missä tämä aineiston sisältävä kansio sijaitsee. Tämä tapahtuu valitsemalla valikosta File toiminto Change dir..., minkä jälkeen avautuvasta ikkunasta selataan haluttuun kansioon, ja hyväksytään valinta valitsemalla OK. Työkansio kannattaa perustaa aina, vaikka olisi ainoastaan harjoittelemassa ohjelman käyttöä tai ohjelmoimassa, sillä R:stä poistuttaessa on mahdollisuus tallentaa kaikki ohjelman muistissa olevat aineistot (workspace eli työtila) ja annetut komennot (history eli komentohistoria) omiksi tiedostoikseen. Oletusarvoisesti nämä tallennetaan juuri työkansioon. R:n sulkeminen R:n voi sulkea useallakin tavalla. Windows-järjestelmässä lienee yksinkertaisinta sulkea R ohjelman oikean ylänurkan painikkeella. Toinen vaihtoehto on antaa sulkemiskomento komentoriviltä: > q() Sulkemiskomento on lyhennys englanninkielisestä sanasta quit eli poistu. Komennosta käy hyvin ilmi liki kaikille R-komennoille yhteinen muoto. Ensin on itse komento, ja sen jälkeen tulee kaarisulkupari, joka on aina lisättävä komennon perään. Kaarisulkuparin perusteella on toisaalta helppo tunnistaa komennot, koska ne liittyvät aina elimellisesti toisiinsa. Sulkemiskomennon antamisen jälkeen R kysyy, halutaanko kaikki muistissa olevat tiedot ja komennot tallentaa: 5

14 ALKEET Useimmiten tämä kannattanee, sillä seuraavalla käyttökerralla on mahdollista ladata työtila ja komentohistoria takaisin R:ään, ja jatkaa työskentelyä siitä, mihin viimeksi jäi. Työtila tallentuu työkansioon yhdeksi tiedostoksi nimellä.rdata, ja komentohistoria tallentuu tiedostoksi.rhistory samaan kansioon. Komentohistoria on pelkkää tekstiä, joten halutessaan sitä voi tarkastella jossakin teksturissa, vaikkapa Notepadissa. Työtilan ja komentohistorian lataaminen Kun jatketaan työskentelyä edellisestä kerrasta, voidaan työtila ja komentohistoria ladata File-valikon toiminnoilla Load Workspace ja Load History. Näiden toimintojen käyttö ei kuitenkaan muuta työkansioksi sitä, josta työtila ja komentohistoria ladattiin, vaan tämä täytyy joka tapauksessa tehdä erikseen aina kun käynnistää R:n. Laajennuspaketit Laajennuspakettien asentaminen R:ään on tällä hetkellä saatavissa vähintäänkin parituhatta erilaista laajennuspakettia. Laajennuspaketit ovat R:n tapa tuoda ohjelmaan uutta toiminnallisuutta. Laajennuspaketeissa on erityisesti sellaisia toimintoja, tyypillisesti uusia komentoja, joita ei ydinkehitystiimin toimesta ole toteutettu. Tämä on R:n käyttöä ajatellen sekä selkeä etu, että lievä haitta. Positiivista on, että yhteisön kehittämien laajennuspakettien avulla R:n toiminnallisuus on paljon laajempi kuin ilman niitä, ja käyttäjä pääsee halutessaan käyttämään kehityksen kärkeä edustavia menetelmiä. Haittana on, että laajennuspakettien laatu vaihtelee. Lisäksi laajasta tarjonnasta on toisinaan vaikea löytää juuri oikea paketti, josta haluttu toiminnallisuus löytyy. Suurin osa laajennuspaketeista sijaitsee CRAN:ssa, mutta erityisesti 6

15 R - KIELEN PERUSTEET laboratoriobiologisten aineistojen analysointiin tarkoitetut laajennuspaketit ovat erillisen Bioconductor-projektin tuottamia. Lisäksi uusien pakettien kehitystyöhön perustettu R-forge sisältää laajennuspaketteja, joita muualta vielä löydy. Ennen pakettien asentamista on valittava ne kokoelmat, joista paketteja halutaan asentaan. Tämä tapahtuu valitsemalla valikosta Packages toiminto Select Repositories. Tämä avaa uuden ponnahdusikkunan, josta halutut kokoelmat voi valita. Useampia kokoelmia voi valita pitämällä Ctrlnäppäimen pohjassa samalla kun valitsee hiirellä listasta halutut kokoelmat. Oletusarvoisesti vain CRAN on valittuna: Tämän jälkeen valikosta Packages valitaan toiminto Install package(s)..., minkä jälkeen avautuu uusi ponnahdusikkuna, josta pitää valita pakettien latauspaikka. Jälleen listasta löytyvä Ruotsi on lähinnä Suomea, ja nopeiden yhteyksien päässä. Lopuksi painetaan OK-painiketta valinnan hyväksymiseksi. Kun latauspaikka on valittu, avautuu uusi ponnahdusikkuna, jossa on lueteltu kaikki kokoelmasta löytyvät paketit. Näistä voidaan valita yksi tai useampia asennettavaksi. Kun valinta on hyväksytty OK-painikkeella, R lataa paketit Internetistä, ja asentaa ne automaattisesti. Laajennuspakettien käyttö Laajennuspaketin asentaminen ei yksinään riitä sen käyttämiseksi analyyseissä, vaan paketti on jokaisella käyttökerralla erikseen ladattava. Tämä ei tarkoita, että paketti pitäisi aina hakea uudelleen Internetistä, sillä asennetut paketit säilyvät sillä tietokoneella, jolle ne on asennettu. Sen sijaan paketin lataaminen tarkoittaa, että R:lle kerrotaan minkä paketin komentoja halutaan käyttää. Aiemmin asennettu paketti ladataan joko valikon Packages toiminnolla Load Package tai komennolla library(). Valikkoreittiä käytettäessä valitaan avautuvasta ponnahdusikkunasta 7

16 ALKEET paketti, joka halutaan ladata. Komentoja käytettäessä pitää kaarisulkujen väliin kirjoittaa ladattavan paketin nimi. Esimerkiksi > library(rpart) lataa paketin rpart, joka tulee jokaisen R-asennuksen mukana, mutta jota ei automattisesti ilman eri pyyntöä ladata, kun R avautuu. Komennosta library(rpart) käy ilmi toinen R:n komennoille tyypillinen ominaisuus. Jos komento kertoo mitä tehdään, niin kaarisulkujen välin sijoitettavat lisämääreet, argumentit, kertovat mille tai miten jotakin tehdään. Toisinaan on tarpeen tietää, mitä laajennuspaketteja on juuri sillä hetkellä ladattuna. Tämä onnistuu komennolla > sessioninfo() joka tuottaa alla olevan tulosteen. Tulosteessa on ylinnä R:n versio, ja tietoja itse tietokoneesta sekä käytetyista tekstin, numeroiden ja päivämäärien koodausmuodoista (locale). Alinna on kerrottu R:n ytimeen kuuluvat paketit, jotka on ladattu sekä muut paketit, jotka käyttäjä on itse ladannut. R version ( ) i386-pc-mingw32 locale: [1] LC_COLLATE=Finnish_Finland.1252 LC_CTYPE=Finnish_Finland.1252 [3] LC_MONETARY=Finnish_Finland.1252 LC_NUMERIC=C [5] LC_TIME=Finnish_Finland.1252 attached base packages: [1] stats graphics grdevices utils base datasets methods other attached packages: [1] rpart_ Erityisesti jos haluaa pyytää apua R:n kansainvälisellä postilistalla, on ylläolevan kaltaiset tiedot, mieluiten suoraan R:stä kopioituna, syytä liittää kysymykseensä. 8

17 R - KIELEN PERUSTEET Käsikirjat, ohjetoiminnot ja postilistat R:n mukana tulee laaja valikoima dokumentaatiota, joka koostuu erilaisista käsikirjoista ja laajennuspakettikohtaisista ohjeista ja komentojen kuvauksista. Näihin pääsee helpoiten käsiksi valikon Help valinnalla Html help. Tämä avaa uuden Internet-selainikkunan, sillä dokumentaatio on HTML-muodossa (jonka lukemiseen tarvitaan selain), vaikka se sijaitseekin samalla tietokoneella kuin itse R:n asennuskin: Käsikirjat Käsikirjat löytyvät yllä avatun selainikkunan kohdasta Manuals. Käsikirjat ovat yksinomaan englanninkielisiä, eikä niitä ole saatavilla suomeksi. Käyttäjälle tärkeimmät käsikirjat ovat An Intruduction to R ja R Data Import/Export. Nämä kuvaavat R:n peruskäytön, ja niistä oppii monia erittäin tarpeellisia komentoja. Käyttäjille tarkoitettujen käsikirjojen hankaluutena on, että ne ovat paikoin hieman vaikeaselkoisia erityisesti niille, joilla ei ole aiempaa ohjelmointikokemusta. Käytetty kieli on nimittäin hieman teknistä. Silti 9

18 ALKEET käsikirjoihin tutustuminen on erittäin suositeltavaa, ja niissä annettuja koodiesimerkkejä kannattaa aina kokeilla R:ssä, sillä se usein selventää mitä esimerkissä itse asiassa ollaan tekemässä. Laajannuspakettien ohjeet Laajennuspakettien ohjeet löytyvät Html help -selainikkunan kohdasta Packages. Sen takaa löytyy lista kaikista R:ään asennetuista paketeista. Kunkin paketin nimi toimii edelleen linkkinä listaan paketin sisältämistä komennoista. Jos tietää mistä paketista komento löytyy, sen ohjeet on helppo löytää tätä kautta. Toisinaan paketin komentolistan yläreunasta löytyy linkki Overview, joka voi sisältää erilaisia lisäohjeita, vignettejä. Vignetit ovat usein lyhyitä, vaihe vaiheelta eteneviä esimerkkejä paketin käytöstä johonkin analyysiin. Sinällään ne eivät kuvaa yksittäisten komentojen toimintaa, vaan miten komennnot toimivat yhdessä tietyn päämäärän saavuttamiseksi tai miten paketin kehittäjä on ajatellut komentoja käytettävän. Tarkastellaanpa seuraavaksi esimerkinomaisesti paketista base löytyvän komennon mean() ohjetta, joka on esitetty kokonaisuudessaan seuraavilla sivuilla. 10

19 R - KIELEN PERUSTEET mean {base} R Documentation Arithmetic Mean Description Generic function for the (trimmed) arithmetic mean. Usage mean(x,...) ## Default S3 method: mean(x, trim = 0, na.rm = FALSE,...) Arguments x An R object. Currently there are methods for numeric/logical vectors and date, date-time and time interval objects, and for data frames all of whose columns have a method. Complex vectors are allowed for trim = 0, only. trim the fraction (0 to 0.5) of observations to be trimmed from each end of x before the mean is computed. Values of trim outside that range are taken as the nearest endpoint. na.rm a logical value indicating whether NA values should be stripped before the computation proceeds.... further arguments passed to or from other methods. Value For a data frame, a named vector with the appropriate method being applied column by column. If trim is zero (the default), the arithmetic mean of the values in x is computed, as a numeric or complex vector of length one. If x is not logical (coerced to numeric), numeric (including integer) or complex, NA is returned, with a warning. If trim is non-zero, a symmetrically trimmed mean is computed with a fraction of trim observations deleted from each end before the mean is computed. 11

20 ALKEET References Becker, R. A., Chambers, J. M. and Wilks, A. R. (1988) The New S Language. Wadsworth & Brooks/Cole. See Also weighted.mean, mean.posixct, colmeans for row and column means. Examples x <- c(0:10, 50) xm <- mean(x) 12

21 R - KIELEN PERUSTEET Ylinnä ohjeessa on komennon nimi. Sitä seuraa välittömästi aaltosuluissa sen paketin nimi, josta komento löytyy: mean{base}. Tämän jälkeen ohjeen otsikko (arithmetic mean) kertoo lyhyesti mitä komento tekee. Komento mean() laskee siis lukujen aritmeettisen keskiarvon. Kohdassa Description on annettu pidempi kuvaus siitä, mitä komento tarkalleen ottaen tekee. Nyt toiminta siis tarkentuu: komennolla voidaan laskea myös typistetty eli trimmattu keskiarvo. Usage-kohdassa on kuvattu missä muodossa komento kirjoitetaan komentoriville. Komento on kirjoitettu kokonaan auki siten, että kaarisulkujen sisällä näytetään kaikki mahdolliset argumentit, joita komennolle voi antaa, vaikkeivat ne kaikki olisikaan aina tarpellisia. Komento mean() toimii siis siten, että sille voidaan antaa kolme argumenttia: x, trim ja na.rm. Argumenttien tarkoitus ja toiminta on kuvattu tarkemmin ohjeen Arguments-kohdassa. Kommennon argumentti x on jokin R:n muistissa oleva aineisto (R object), joka voi olla koostua luvuista tai päivämääristä. Argumentillä trim voidaan säätää typistetyn keskiarvon laskemistapaa, ja na.rm kertoo, poistetaanko aineistosta puuttuvat arvot ennen keskiarvon laskemista vai ei. Value-kohdassa on kuvattu mitä komento palauttaa. Esimerkiksi, jos argumentti trim on nolla, lasketaan aritmeettinen keskiarvo, joka palautetaan yhden lukuarvon sisältävänä vektorina. References- ja See Also -kohdat sisältävät viittauksia R:n ulkopuolisiin tietolähteisiin ja muihin R:n ohjeisiin. Ohjeen lopussa oleva Examples-kohta antaa yleensä muutamia esimerkkejä komennon käytöstä. Tässä tapauksessa ensin tallennetaan luvut 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ja 50 vektorimuotoiseen objektiin, jonka nimi on x. Tämän jälkeen vektori x annetaan komennolle mean() argumentiksi, ja lopputuloksena saatava keskiarvo tallennetaan edelleen objektiksi xm. Ohjeen esittelyn yhteydessä esiintyi muutamia sellaisia R-kielelle tyypillisiä termejä, joita ei ole vielä tarkemmin selitetty. Näitä olivat muun muassa argumentti, vektori ja objekti. Jos tämä häiritsee, voi niiden merkityksen jo tässä vaiheessa tarkistaa kirjan seuraavasta osasta, jossa tutustutaan R-kieleen tarkemmin. Haku ohjeista Ohjeista on mahdollista tehdä hakuja. Tämä on erityisen näppärää, jos ei muista tai tiedä sopivan komennon nimeä tai missä paketissa jokin komento sijaitsee. Haku löytyy Help-valikon kohdasta Search Help... 13

22 ALKEET Hakuun voi syöttää minkä tahansa asiasanan, mutta haku kohdistuu vain niihin paketteihin, jotka R:ään on sillä hetkellä asennettu. Haku palauttaa listan paketeista ja komennoista, jotka sopivat hakuun. Esimerkiksi haku sanalla mean palauttaa pitkän listan vaihtoehtoja. Tulokset on ilmoitettu siten, että kutakin hakuun sopivaa komentoa vastaa yksi rivi. Kullakin rivillä on ensin kerrottu laajennuspaketin nimi, sitten varsinaisen komennon nimi ja lopuksi komennon lyhyt kuvaus. Paketin ja komennot nimet on eroteltu toisistaan kahdella kaksoispisteellä. Esimerkiksi edellä käsitellyn komennon mean() tiedot löytyvät seuraavan kuvan riviltä base::mean Arithmetic Mean Jos haku jo asennettujen pakettien ohjeista ei tuota tulosta, voi haun tehdä myös R:n kotisivujen materiaalista, lähinnä postilistojen sisällöstä valitsemalla valikosta Help toiminto search.r-project.org... Esimerkiksi hakusanalla mean tämä palauttaa kirjan kirjoitushetkellä osumaa. Kolmas vaihtoehto sopivien komentojen tai toimintojen etsimiseksi on RSeek. RSeek on R:n funktioihin ja laajennuspaketteihin keskittynyt hakupalvelu, joka sijaitsee Internetissä osoitteessa Palvelu on rakennettu Googlen hakukoneen päälle, mutta etuna on, että se suodattaa tuloksista automaattisesti pois kaikki sellaiset osumat, jotka eivät ole juuri R-kieleen liittyviä. Hakusanalle mean RSeek palauttaa kymmeniä ellei satoja osumia. 14

23 R - KIELEN PERUSTEET Postilistat Jos edellä esitetyt apu- ja ohjetoiminnot eivät tuota tulosta, voi aina kääntyä postilistoille vastaavien avuliaiden ihmisten puoleen. Koska R on avoimen lähdekoodin projekti, joka pyörii vapaaehtoisvoimin, ei R:ään myöskään ole tarjolla virallista teknistä tukea. Teknisen tuen virkaa hoitavat muutamat Internetissä sijaitsevat postilistat, joihin pääsee käsiksi R-projektin etusivun kautta. Postilistoja voi lukea kuka tahansa, mutta postittamista on rajoitettu, ja vain listalle rekisteröityneet voivat lähettää niille viestejä. Jos aikoo todella alkaa käyttää R:ää, kannattaa postilistalle rekisteröityä osoitteessa Lisäksi listaa kannattaa käydä lukemassa ainakin satunnaisesti, sillä toisten esittämiin kysymyksiin ja niihin tulleisiin vastauksiin tutustuminen on todella opettavaista. Pääasiallisena postilistana on R-help, joka on tarkoitettu yleisluontoisille kysymyksille, toisin sanoen R:n ja sen laajennuspakettien käyttöä koskeviin kysymyksiin, jos ne eivät sovi muille postilistoille. Biologisiin sovelluksiin keskittyvällä Bioconductor-projektilla on oma postilistansa, samaten joillakin erikoisaloilla on oma Special Interest Group (SIG) -postilistansa. Tällaisia ovat esimerkiksi epidemiologia, ekologia, taloustieteet ja geotieteet. Ennen postilistalle kirjoittamista kannattaa käydä läpi edellämainitut tietolähteet sekä Help-valikosta löytyvät usein kysytyt kysymykset (FAQ on R ja FAQ on R Windows). Vasta jos näistä ei löydy apua, eikä itse keksi ongelmaan ratkaisua, voi listalle kirjoittaa. Jos ei nimittäin ole tehnyt lainkaan kotitöitään, eikä ole edes yrittänyt omatoimisesti löytää ratkaisua, voi vastaanotto postilistalla olla hieman vastentahtoinen. Ongelma kannattaa kuvata mahdollisimman tarkasti käyttäen apuna koodiesimerkkejä. Koodiesimerkeistä tulisi kirjoittaa sellaisia, että kuka tahansa voisi ajaa ne omassa R:sään tarvitsematta muuta aineistoa. Tämä on toisinaan vaikeaa, mutta helpottaa ja nopeuttaa avun saantia. Kysymykseen pitää myös aina liittää edellä mainittu sessioninfo() -komennon tulostus, sillä jotkin ongelmat voivat olla järjestelmäkohtaisia. Muut yhteisön ylläpitämät ohjeet Edellä mainittujen apu- ja ohjetoimintojen ja postilistojen lisäksi on olemassa muutamia erittäin hyödyllisiä sivustoja, joista voi olla suurta hyötyä R:n käyttöä opetellessa. Mainittakoon ensimmäisenä R Wiki (http://wiki.r-project.org/), 15

24 ALKEET jonka etusivu on kuvattu alla. Se on R-yhteisön ylläpitämä sivusto. Sen tarkoituksena on koota yhteen esimerkiksi erilaisia vinkkejä ja tarkentavia ohjeita, joita ei ole muualta helppo löytää. Tällä hetkellä R Wiki on hieman hajanainen, ja sieltä on vaikea löytää tietoa, mutta sivusto on varmasti tutustumisen arvoinen. Toinen mainitsemisen arvoinen sivusto on R Graph Gallery (http://addictedtor.free.fr/graphiques/), josta löytyy laaja valikoima erilaisia kuvatyyppejä, ja esimerkkejä miten ne voidaan tuottaa R:ssä. Kustakin kuvasta on saatavilla esimerkkikuva, kuvaus siitä mitä kuva esittää, tarkempi lista tarvittavista R-paketeista sekä itse R-kielinen koodi, jolla kuva voidaan tuottaa. Graafiikan tuottaminen R:llä on toisinaan varsin työlästä, ja R Graph Gallery voi helpottaa työskentelyä, kun on saatavilla edes jonkinlainen kuvan raakaversio, jota voi lähteä työstämään mieleisekseen. Graafinen käyttöliittymä R Commander R:ään on saatavilla useampiakin graafisia käyttöliittymiä, mutta seuraavassa tutustutaan niistä vain yhteen, R Commander:iin. R Commander on toteutettu siten, ettei se vaadi tietokoneelta muuta kuin Rasennuksen toimiakseen. Monet muut käyttöliittymät vaativat erillisten lisäohjelmien, kuten Java SDK:n tai Gtk2+:n asentamista. R Commander:in asentaminen ja käynnistäminen R Commander asennetaan suoraan R:stä, joko Packages-valikon toimintoja käyttäen tai komentoriviltä. R Commander:lla on joitakin riippuvuuksia muihin lisäpaketteihin, ja jos nämä vaaditut paketit puuttuvat, ne asennetaan kun R Commander käynnistetään ensimmäisen kerran. Näin käy vain, jos asennus on tehty Packages-valikon kautta. Jos asennus tehdään komentoriviltä, asentuvat sekä R Commander että tarvittavat lisäpaketit automaattisesti komennolla: >install.packages( Rcmdr, dependencies=t) Komento install.packages() tekee saman kuin Packages-valikon toiminto Install Package(s)..., mutta on joustavampi, koska sille voi antaa argumentteja. Tässä argumentti dependencies pyytääkin R:ää asentamaan kaikki ne lisäpaketit, joita Rcmdr-paketti tarvitsee toimiakseen. 16

25 R - KIELEN PERUSTEET Asennuksen jälkeen R Commander ajetaan komentoriviltä komennolla: >library(rcmdr) eli se ladataan käyttöön kuin mikä tahansa Käynnistyttyään R Commander näyttää seuraavalta: laajennuspaketti. R Commander koostuu valikkorivistä, joka on ikkunassa ylinnä sekä kolmesta ikkunasta. Ylinnä on Script Window, johon voi kirjoittaa R-kielisiä komentoja kuten komentoriville. Keskimmäisenä on Output Window, johon 17

26 ALKEET R:n tulostus ilmestyy komentojen suorittamisen jälkeen. Alimpana on Messages-ikkuna, joka kertoo lähinnä varoitus- ja virheilmoitukset, joita komentojen ajaminen saattaa joskus tuottaa. Jo aiemmin käsitelty komento sessioninfo() suoritettaisiin R Commanderissa kirjoittamalla ylimpää ruutuu ko. komento, maalaamalla se kiirellä siniseksi, ja painamalla Script Window:n oikeasta alakulmasta löytyvää Submit-painiketta. Tämän jälkeen tulokset tulostuvat Output Window:hin: 18

27 R - KIELEN PERUSTEET Aineiston luominen taulukkolaskentaohjelmassa Laajempien aineistojen luomiseen on usein näppärää käyttää taulukkolaskentaohjelmaa, kuten Microsoft Officen Excel:iä tai Open Officen Calc:ia. Tällöin kukin muuttuja sijoitetaan taulukkoon omaksi sarakkeekseen, ja havainnot sijoitetaan muuttujien alle riveittäin siten, että kustakin havaintoyksiköstä tehdyt havainnot ovat kaikki samalla rivillä. Esimerkiksi jos keräisimme aineistoa ihmisten pituuksista ja painoista sukupuolen mukaan jaoteltuna, voisi taulukko näyttää Excel:ssä seuraavalta: Kullekin sarakkeelle kannattaa antaa helposti tunnistettava nimi (tässä korostettu), sillä ne muuttuvat suoraan R:ssä vastaavien muuttujien nimiksi. Nimeämisen lisäksi kannattaa huomioida, että data on helpoin tuoda R:ään, jos kunkin sarakkeen nimi vie vain yhden solun. Kahdella sarakkella ei myöskään voi olla samaa nimeä. Aineiston tuonti R:ään leikepöydän kautta Edellä luotu aineisto voidaan tuoda R:ään useallakin tavalla. Jos kyseessä on jokseenkin pieni aineisto, korkeintaan muutamia satoja rivejä ja sarakkeita, voi aineiston maalata Excel:ssä, ja kopioida leikepöydälle. Aineiston voi sitten tuoda R:ään käyttäen R Commander:in valikon Data toimintoa Import Data -> from text file, clipboard or URL... Tämän jälkeen aukeaa uusi ikkuna, jossa kysellään tuotavan tiedoston ominaisuuksia: 19

28 ALKEET Ensimmäisessä kentässä kysytään, minkä nimiseksi objektiksi tuotava tiedosto halutaan R:ssä tallentaa (tässä bmi). Seuraavassa valintalaatikossa kuuluu olla merkki, jos tuotavassa tiedostossa kullakin sarakkeella on nimi. Oletusarvoisesti puuttuvien havaintojen koodina on NA, mutta tarvittaessa sitä voi muuttaa. Aineistoa ollaan tuomassa leikepöydältä, joten seuraavista valinnoista valitaan Clipboard. Kopioitaessa Excel:stä, on sarakkeiden erottimena tabulaattori (Tabs), mutta se voi olla jotakin muutakin. Kun asetukset on muokattu oikeiksi, voidaan painaa ikkunan alareunasta löytyvää OK-painiketta. Tämän jälkeen aineisto tallentuu R:n muistiin nimellä bmi. Nyt eräs R Commanderin eräs hyvä puoli tulee selkeästi esiin. Kun jokin valikkotoiminto on tehty, tulostuu sitä vastaava komento komentoriviikkunaan: 20

29 R - KIELEN PERUSTEET Käyttämämme valikkotoiminto kutsuu siis itseasiassa komentoa read.table(), joka on tarkoitettu juuri taulukkomuotoisten aineistojen lukemiseen R:ään. Valitsemamme aineiston nimi R:ssä (bmi) esiintyy myös komennossa: se on rivillä aivan ensimmäisenä. Komento read.table() saa myös useita argumenttejä, jotka kuvaavat miten tiedosto luetaan. Jotta argumentit osaa valita oikein, pitää tuntea luettavan tiedoston rakenne, esimerkiksi onko sarakkeilla otsikot, ja mitä merkkiä on käytetty sarakkeiden erottimena. Tabulaattorin lisäksi yleinen erotin on anglokaanisissa maissa pilkku ( comma-separated ), mutta koska se on Suomessa desimaalierotin, käytetään sen sijaan usein erottimena puolipistettä (;). Suomessa esimerkiksi Excel:iä käytettäessä tuleekin muistaa, että se tallentaa tiedoston käyttäen puolipistettä sarakkeiden erottimena, vaikka olisikin valittu tallennusmuodoksi vaihtoehto commaseparated text. Tarkastellaanpa komennon read.table() argumentteja hieman tarkemmin. Ensimmäisenä argumenttina on luettavan tiedoston nimi. Tässä tiedoston nimi on clipboard, mikä on erikoistapaus siinä mielessä, että se tarkoittaa juuri Windows:in leikepöydältä lukemista. Jos todella luetaan jostakin tiedostosta, tulee tiedoston nimi kirjoittaa lainausmerkkien sisään pitkässä muodossa eli siten, että myös tiedoston tarkennin on mukana. Jos tiedoston nimi on esimerkiksi pituudet, ja se on tekstimuodossa, jolloin sen tarkemmin on.txt, tulee sen nimi R:ssä kirjoittaa muodossa pituudet.txt. Muut argumentit kuvaavat lähinnä luettavan tiedoston sisällön: header Onko tiedostossa kullakin sarakkeella oma otsikko? Vaihtoehtoina ovat header=t, jolloin kullakin sarakkeella katsotaan olevan otsikko, ja header=f, jolloin otsikoita ei oletetan olevan eli aineisto alkaa luettavan tiedoston ensimmäiseltä riviltä. 21

30 ALKEET sep Mitä merkkiä on käytetty sarakkeiden erottelemiseen? Vaihtoehto sep= \t tarkoittaa tabulaattoria. Muita vaihtoehtoja ovat esimerkiksi pilkku sep=, ja puolipiste sep= ;. na.strings Millä tavalla puuttuvat arvot on koodattu? R:ssä oletuksena on, että jos aineistossa esiintyy merkkiyhdistelmä NA, se tarkoittaa puuttuvaa arvoa. Samaten taulukossa kaikki tyhjät solut koodataan luettaessa automaattisesti puuttuviksi arvoiksi. Siksi kannattaakin heti aineistoa koostettaessa päättää miten puuttuvat arvot, joita ei ole mitattu, erotellaan sellaisista, jotka on mitattu, mutta joista tuloste ei ole saatu. dec Mitä merkkiä on käytetty desimaalierottimena? Suomessa käytetään yleensä pilkkua, ja anglokaanisissa maissa pistettä. Vaihtoehtoja ovat siis lähinnä dec=. ja dec=,. strip.white Jos tekstimuotoisissa kentissä on ennen varsinaista tekstiä tai sen jälkeen välilyöntejä, poistetaanko ne? Vaihtoehdot ovat joko strip.white=true, jolloin vaälilyönnit poistetaan, ja strip.white=false, jolloin välilyöntejä ei poisteta. Komento read.table() voi saada myös muita argumenttejä, joista tärkeimmät on vielä esitelty alla: row.names Onko tiedostossa sarake, joka sisältää kunkin havainnot tunnisteen, rivinimen? Argumentille pitää kertoa sen sarakkeen otsikko tai sijainti numeerisesti vasemmalta oikealle laskettuna, jossa rivinimet sijaitsevat. Esimerkiksi row.names=1 määräisi, että rivinimet luetaan tiedoston ensimmäisestä sarakkeesta. quote Mitä merkkiä käytetään lainausmerkkinä? Jos tiedostossa on kenttiä, joissa on parittomia lainausmerkkejä, kuten ' tai, tiedoston lukeminen ei onnistu ellei lainausmerkkien käyttöä käännetä kokonaan pois. Tämä tapahtuu asettamalla argumentti quote=. Tyypillisesti tällainen tilanne voi tulla eteen molekyylibiologisten aineistojen kanssa, koska monissa geenien nimissä on parittomia yksinkertaisia lainausmerkkejä. 22

31 R - KIELEN PERUSTEET comment.char Mitä merkkiä käytetään kommenttiriveillä? Teksti, joka seuraa kommenttimerkkiä samalla rivillä oletetaan kommentiksi, eikä sitä lueta. Oletusarvoisesti kommenttimerkki on #, mutta kommenttimerkkien käytön voi myös kääntää pois päältä asettamalla argumentiksi comment.char=, jos aineistossa esiintyy #-merkki muussa merkityksessä. Aineiston tuonti R:ään tiedoston kautta Jos aineisto on vähänkään isompi, ei sitä kannata suorituskykysyistä tuoda Windows:in leikepöydän kautta, vaan tallentamalla aineisto ensin tiedostoksi. R Commander osaa lukea suoraan Excel-tiedostoja, mutta muista taulukkolaskentaohjelmista tiedosto kannattaa ensin tallentaa muodossa tab-delimited text eli tekstitiedostoksi, jossa sarakkeiden erottimena on tabulaattori. Oletetaan, että sama aineisto, joka edellä toimme leikepöydän kautta sijaitseekin nyt tiedostossa Book1.xlsx välilehdellä Sheet1. Aineiston tuonti suoraan Excel:stä onnistuu R Commander:in valikosta Data valitsemalla toiminnon Import data -> from Excel, Access or dbbase data set... Tämä avaa uuden ponnahdusikkunan, jossa aineistolle annetaan R:ssä jokin nimi (tässä bmi): Tämän jälkeen valitaan tiedostoselaimella tiedosto Book1.xlsx, ja lopuksi välilehti, jolta aineisto luetaan: 23

32 ALKEET Tämän jälkeen aineiston on R:ssä käytettävissä nimellä bmi. Tekstitiedostosta lukeminen tapahtuu samaan tapaa kuin leikepöydältäkin, mutta leikepöydän sijaan valitaan tiedoston sijainniksi Local File System aiemman Clipboardin sijaan: 24

33 R - KIELEN PERUSTEET Tämän jälkeen valitaan luettava tiedosto tiedostoselaimella, ja aineisto on jälleen käytettävissä R:ssä nimellä bmi. Mitä tehdä R:ään tuodulla aineistolla? Kun aineisto on saatu onnistuneesti tuotua R:ään, kannattaa tarkistaa, että kaikki on mennyt oikein. Aineistoa voi tarkastella taulukkomuodossa, R Commanderin yläreunasta löytyvän View Data Set-painikeen avulla: Se avaa uuden ikkunan, jossa aineisto esitetään: Aineistosta kannattaa visuaalisesti tarkistaa, että sen alkupää on luettu oikein: että sarakkeiden otsikot ovat oikein, että aineistossa on jokseenkin oikea määrä sarakkeita, ja että mahdolliset rivien otsikot on tunnistettu oikein. Taulukkomuotoisen tarkastelun lisäksi kannattaa tarkistaa ainakin aineiston yhteenvetotiedot, jotka saa esille valikosta Statistics valinnalla Summaries -> Active data set. Toiminto tulostaa R Commander:in Output Window:hin lyhyen yhteenvedon kustakin aineiston sarakkeesta: Sukupuoli mies :1 nainen:1 Pituus Min. : st Qu.:170.2 Median :174.5 Mean : rd Qu.:178.8 Max. :183.0 Paino Min. : st Qu.:62.25 Median :66.50 Mean : rd Qu.:70.75 Max. :

34 ALKEET Jos kunkin muuttujan yhteenvetotiedotkin ovat jokseenkin järkeviä, voi olla melko vakuuttunut siitä, että aineiston tuonti on onnistunut. Tämän jälkeen voikin edetä itse analyyseihin tai aineiston visualisointiin, joihin tutustutaan tämän kirjan kolmannessa ja neljännessä osiossa. Kuitenkin ennen niihin siirtymistä voi olla hyödyllistä tutustua osioon kaksi, jossa esitellään R-kielen perusteet. Edellä kuvatuilla tavoilla tuotu aineisto on R:ssä tallennettu data frame:ksi eli datakehikoksi. Erityisesti niihin liittyviin toimintoihin tutustumisesta voi olla hyötyä analyysien tekemisessä. Vaikka R-kielen perusteet alkaa yhden muuttujan aineistojen käsittelyllä, kannattaa tähänkin materiaaliin tutustua, sillä kukin R:ään tuodun taulukon sarake voidaan erottaa omaksi muuttujakseen, ja niitä voidaan siis käsitellä myös yksitellen. 26

35 R KIELEN PERUSTEET R-kieli Tämä luku esittelee R-kielen perusteet. Aluksi käydään läpi kaikille käyttäjille hyödyllisiä ominaisuuksia, mutta loppua kohden painotus muuttuu enemmän ohjelmointiin. Luvun seuraaminen edellyttää, että käytössä on toimiva R-asennus. Asian ymmärtämistä edistää esimerkkien kokeileminen R:ssä. Kun vastaan tulee uusi R-komento, kannattaa sitä vastaava koodiesimerkki kirjoittaa R-komentoriville, jotta näkee mitä käytännössä tapahtuu. Samalla voi tutustua komentoon liittyviin ohjeisiin, sillä niiden lukemista on tarpeen harjoitella, jotta niissä käytetty kieli tulee tutummaksi. Tämä luku on tarkoitettu luettavaksi siinä järjestyksessä, jossa asiat toisiaan seuraavat. Uusia komentoja ja asioita ei välttämättä esitellä ainoastaan niissä kappaleissa, joissa asiaa ensimmäisen kerran käsitellään, vaan pääsääntöisesti asioita ennemminkin syvennetään pikku hiljaa. Komentorivi Käynnistyttyään R aukeaa komentoriville. Komentorivin tunnistaa suurempi kuin -merkistä > kunkin rivin alussa. Merkin jälkeen voi kirjoittaa R-komentoja, jotka sitten suoritetaan painamalla Enter-näppäintä. Komennnon suorittamisen jälkeen R tyypillisesti kirjoittaa jotakin ruudulle, piirtää kuvan tai tuottaa jotakin johonkin tiedostoon, riippuen annetusta komennosta. Kun R on suorittanut annetun komennon loppuun, se on jälleen valmis ottamaan vastaan uusia komentoja, ja näyttää uuden merkillä > alkavan rivin. Toisinaan näkee rivin, joka alkaakin merkillä +. Tällöin R olettaa edellisen rivin komennon jatkuvan vielä uudelle riville. Kyseessä ei siis ole laskutoimituksellinen yhteenlaskutoimitus, vaan R olettaa saavansa lisää komentoja. Jos tilanne on haluttu, syötetään keskeneräinen komento loppuun. Jos tilanne johtuu vahingosta, voi tilanteesta poistua puhtaalle 27

36 PERUSTEET komentoriville painamalla Escape (Esc)-näppäintä. R laskimena R toimii hyvin laskimena. Se sisältää kaikki tavanomaiset laskukoneen toiminnot, kuten yhteenlaskun, vähennyslaskun, kertolaskun ja jakolaskun, mutta myös esimerkiksi potenssiin korotuksen ja luonnollinen logaritmi -funktion. Peruslaskutoimitukset tapahtuvat seuraavasti. Merkillä # alkavat rivit ovat kommentteja, eikä niitä tarvitse kirjoittaa. R tulostaa laskutoimituksen tuloksen riville, joka alkaa rivin numerolla (tässä [1]): # Yhteenlasku >3+2 [1] 5 # Vähennyslasku >3-2 [1] 1 # Kertolasku >3*2 [1] 6 # Jakolasku >3/2 [1] 1.5 # Potenssiin korottaminen >3^2 [1] 9 # Neliöjuuren laskeminen >sqrt(9) [1] 3 # Jakojäännös >9%%4 [1] 1 Luonnollista logaritmia (loge)ja sen eksponenttia (esimerkiksi e 2) varten on olemassa omat komentonsa: > log( ) [1] 1 28

37 R KIELEN PERUSTEET > exp(1) [1] R seuraa normaalia laskujärjestystä, ja jos siitä halutaan poiketa, pitää apuna käyttää sulkuja. Esimerkiksi lausekkeen laskeminen ei onnistu R:ssä seuraavasti: > 2+3/5 [1] 2.6 Tulos 2.6 ei ole oikein, sillä laskujärjestyksen mukaan jakolaskut lasketaan ennen yhteenlaskua, joten laskutoimitus on itse asiassa laskettu = 2.6. Kuten sanottu, apuna pitää käyttää sulkuja. Laskutoimitus: > (2+3)/5 [1] 1 tuottaa nyt oikean tuloksen. Laskutoimituksissa voi käyttää yhdistellen kaarisulkuja () ja aaltosulkuja {}, jos se tekee laskutoimituksesta luettavamman. Sen sijaan usein matemaattisessa tekstissä käytetyt hakasulut [] on R:ssä varattu osaaineistojen poimimiseen alaindeksejä käyttäen, eikä niitä voi käyttää laskutoimituksissa. Suurten lukujen esittämiseen käytetään tieteellistä merkintätapaa. Esimerkiksi luku voidaan merkitä muodossa 1*10 4, mikä esitettäisiin R:ssä muodossa: > 1e4 [1] Vastaavalla tavalla voidaan esittää pieniä lukuja, kuten 0.001: > 1e-4 [1]

38 PERUSTEET Komentojen rakenne R-komennot koostuvat itse komennosta, ja sitä välittömästi seuraavasta kaarisulkuparista. Esimerkiksi laskutoimitusesimerkeissä annettu neliöjuuren laskentatapa käytti komentoa sqrt(). Luku, josta neliöjuuri haluttiin laskea annettiin kaarisulkujen sisäpuolella: >sqrt(9) [1] 3 Kaarisulkujen sisäpuolella olevia lukuarvoja tai tekstiä kutsutaan komennon argumenteiksi. Jos komento kertoo mitä tehdään (tässä otettiin neliöjuuri), kertovat argumentit vastaavasti mille jotakin tehdään (tässä luku 9). Komennosta riippuen argumentit voivat myös kertoa miten, missä tai milloin jotakin tehdään. Komennot ovat merkkikokoriippuvaisia. Isoja ja pieniä kirjaimia ei voi komennoissa sekoittaa miten vain. Esimerkiksi komento (huomaa iso alkukirjain): >Sqrt(9) [1] Error: could not find function "Sqrt" Antaa virheilmoituksen, että komentoa ei löydetä, mikä tyypillisesti viittaa kirjoitusvirheeseen, kuten tässä tapauksessa, tai ettei laajennuspakettia, josta komento löytyy, ole vielä ladattu R:n muistiin. Jälkimmäisestä tapauksesta myöhemmin lisää. Desimaalien määrä luvuissa ja pyöristäminen Oletusarvoisesti R näyttää luvuissa seitsemän desimaalia. Esimerkiksi piin likiarvoksi R antaa: > pi [1] Näytettyjen desimaalien määrään voidaan vaikuttaa muuttamalla R:n asetuksia. Komento options() luettelee kaikkiin komentoihin vaikuttavat globaalit asetukset. Eräs näistä asetuksista on nimeltään digits, joka määrää luvuissa näytettävien desimaalien määrän. Desimaalien määrä voidaan kasvattaa vaikkapa arvoon 15 komennolla. > options(digits=15) 30

39 R KIELEN PERUSTEET Tässä siis options() on komento, ja digits sen argumentti, joka saa arvokseen 15. Kun argumentille annetaan jokin arvo, tulee argumentin nimen ja arvon väliin sijoittaa yksi yhtäsuuruusmerkki. Asetusten muuttamisen jälkeen piin likiarvoksi saadaan: > pi [1] Lukuja voidaan pyöristää alaspäin lähimpään kokonaislukuun komennolla: > floor(pi) [1] 3 Vastaavalla tavalla voidaan pyöristää myös ylöspäin komennolla: > ceiling(pi) [1] 4 Yleisempi tapa pyöristää lukuja on määrätä, kuinka moneen desimaaliin ne pyöristetään. Esimerkiksi komennolla > round(pi, 2) [1] 3.14 voidaan pyöristää piin likiarvo kahteen desimaaliin. Komento round() saa nyt kaksi argumenttia. Ensimmäinen on luku, joka pyöristetään, ja toinen määrittää desimaalien lukumäärän. Jos tarkastellaan komennon ohjetta, huomataan, että komento on muotoa round(x, digits=0). Jos argumentit esitetään samassa järjestyksessä kuin missä ne esiintyvät ohjeessa, siis tässä tapauksessa ensin luku ja sitten desimaalien määrä, ei argumenttien nimiä tarvitse erikseen kirjoittaa. Jos argumenttien järjestys on jokin muu, pitää niiden nimetkin kirjoittaa. Seuraava komento siis toimii oikein: > round(digits=2, x=pi) [1] 3.14 Mutta seuraava ei tee sitä mitä sen olettaisi tekevän: > round(2, pi) [1] 2 Tämä komento itse asiassa pyöristää luvun 2 antaen sille desimaalia, mutta koska sillä ei ole alun alkaenkaan yhtäkään desimaalia, R ilmoittaa tuloksen lukuna 2. 31

40 PERUSTEET Laskentatarkkuus R tallentaa luvut double-muodossa, mikä merkitsee muun muassa, että luvut voidaan esittää korkeintaan viittätoista desimaalia käyttäen. Jos luvussa on enemmän desimaaleja, ei sitä voida enää esittää tarkasti. Asiaa hahmottaa ehkä parhaiten pieni esimerkki. Jos lasketaan yhteen vaikkapa luvut 1 ja 1e-14, voidaan tulos vielä esittää siten, että tulos on tarkka: > [1] Mutta jos lasketaankin yhteen luvut 1 ja 1e-16, on tuloksena luku 1: > [1] 1 Yhteenlaskutoimituksessa toisena osapuolena ollut hyvin pieni desimaaliluku ikään kuin katoaa, koska lukua ei enää pystytä esittämään riittävän tarkasti. Äärettömät luvut Toisinaan laskutoimituksissa syntyy äärettömiä arvoja. Tyypillisesti näin käy, jos jokin luku jaetaan nollalla: > 1/0 [1] Inf R:ssä Inf merkitsee ääretöntä, ja on lyhennys englanninkielisestä sanasta Infinity. Toinen mahdollinen laskutoimituksissa syntyvä tulos on epäluku: > 0/0 [1] NaN NaN on lyhennys englanninkielisistä sanoista Not a Number. Molemmat tapaukset voivat aiheuttaa ongelmia, jos niitä ei ole otettu huomioon laskutoimituksissa. Ongelma tuskin koskee yllä esitetyn kaltaisia yksinkertaisia operaatioita, mutta tällaisia tilanteita voi syntyä, 32

41 R KIELEN PERUSTEET kun käsitellään suurempia aineistoa, jolloin kaikkia yksittäisiä laskutoimituksia ei voida mitenkään tarkistaa käsin. Onneksi R:ssä on olemassa komentoja, joilla voidaan testata, onko syntynyt tulos ääretön tai kenties epäluku. Äärettömyys voidaan testata komennolla: > is.infinite(1/0) [1] TRUE Mikä antaa tulokseksi TRUE eli tulos todella on ääretön. Jos tulos ei ole ääretön, on tuloksena FALSE: > is.infinite(1/1) [1] FALSE Vastaavasti voidaan testata, onko tulos epäluku: >is.nan(0/0) [1] TRUE Lukujen vertailu Lukuarvoja voidaan vertailla niin sanotuilla vertailuoperaattoreilla. Niiden avulla voidaan tutkia, ovatko luvut yhtä- vai erisuuria, ja kumpi luvuista on suurempi kuin toinen. Seuraavassa muutama esimerkki: # Yhtäsuuruus 1==1 [1] TRUE # Erisuuruus 1!=1 [1] FALSE # Suurempi kuin 1>1 [1] FALSE # Pienempi kuin 1<1 [1] FALSE # Suurempi tai yhtäsuuri kuin 1>=1 [1] TRUE 33

42 PERUSTEET # Pienempi tai yhtäsuuri kuin 1<=1 [1] TRUE Vertailuoperaattorit palauttavat aina tulokseksi joko arvon TRUE, jolloin vertailu on tosi tai arvon FALSE, jolloin vertailu ei ole tosi. Vertailuoperaatioita voi myös yhdistellä loogisilla operaattoreilla. Näitä ovat muun muassa ja sekä tai. Loogisten operaattoreiden avulla voidaan suorittaa useampia vertailuja yhdellä kertaa, ja saada niille yhteinen vastaus. Jos esimerkiksi halutaan testata onko 1 yhtä suuri kuin 1 ja samanaikaisesti onko 2 yhtä suuri kuin 2, tämä voidaan toteuttaa R:ssä seuraavasti: >1==1 & 2==2 [1] TRUE Jos sen sijaan riittää, että toinen vertailu on tosi, jotta palautetaan TRUEarvo, voidaan vertailu tehdä tai-operaattorilla: > 1==1 2==3 [1] TRUE Muuttujien ja objektien luominen Edellä R:ää on käsitelty lähinnä laskukoneena, mutta käytännössä suuri osa aineistoista koostuu suuresta määrästä lukuja, totuusarvoja (TRUE / FALSE) tai tekstimuotoisia arvoja. Yksinkertaisin aineistotyyppi on vektori, joka koostuu erillisistä numeroarvoista tai kirjainjonoista. Jos olemme vaikkapa heittäneet noppaa kuusi kertaa, ja saaneet tulokseksi kuusi numeroa, voidaan ne syöttää R:ssä vektoriin. Vektori luodaan komennolla c(). Nopanheiton tulokset, numerot 1, 2, 2, 4, 5, 5, voidaan tallentaa vektoriin komennolla: >c(1, 2, 2, 4, 5, 5) [1] Haittapuolena äskeisessä menettelyssä on, että joudumme syöttämään arvot R:ään aina uudelleen, kun haluamme käsitellä niitä. Tähän on kuitenkin olemassa yksinkertaisempikin ratkaisu. Arvot voidaan nimittäin tallentaa R:n muistiin yhdeksi vektorimuotoiseksi muuttujaksi. Jatkossa aina kun R:n muistiin tallennetaan mitä tahansa, puhutaan objekteista. Nytkin siis nopanheiton tulokset tallennetaan R:n muistiin objektiksi. 34

43 R KIELEN PERUSTEET Nopanheiton tulokset sijoitetaan sopivan nimiseen objektiin käyttämällä sijoitusoperaattoria <-. Tulos voidaan esimerkiksi tallentaa objektiin nimeltä noppa seuraavasti: >noppa <- c(1, 2, 2, 4, 5, 5) Nyt objekti noppa sisältää nopanheiton tulokset, ja ne voidaan milloin tahansa näyttää ruudulla kirjoittamalla objektin nimi komentoriville: > noppa [1] Sijoitusoperaatio on äärimmäisen keskeinen toiminnallisuus. Kerrataanpa siis vielä kerran. Komennossa >noppa <- c(1, 2, 2, 4, 5, 5) noppa on sen objektin nimi, johon sijoitusoperaattorin (<-) oikealla puolella olevat arvot halutaan sijoittaa. Sijoittamiseen tarvitaan nämä kaikki kolme komponenttia: objektin nimi, sijoitusoperaattori ja se mitä objektiin ollaan sijoittamassa. Vektorissa voi lukujen sijaan olla myös tekstiä. Yllä olevan esimerkin tapaan voidaan yhteen vektoriin tallentaa vaikkapa tämän kirjan kirjoittajan etu- ja sukunimet. Kun käsitellään tekstiä, tulee yksittäiset sanat ympäröidä lainausmerkeillä, sillä muutoin R kuvittelee niiden olevan muuttujien nimiä, eikä osaa toimia oikein. Tekstin sijoittaminen vektoriin tapahtuu siis esimerkiksi: >kirjoittaja<-c( Jarno, Tuimala ) Samaan tapaan kuin ylempänä tehtiin numeroille, kukin yksittäinen arvo eroteltiin muista arvoista pilkulla. Jos lainausmerkit unohtuvat, antaa R mitä todennäköisimmin virheilmoitukset: >kirjoittaja<-c(jarno, Tuimala) Error: object 'Jarno' not found Virheilmoituksessa puhutaan nyt objektista, ei funktiosta, joten R on yrittänyt löytää Jarno-nimisen objektin muististaan, mutta sellaista ei ole löytynyt, joten vektoriakaan ei ole voitu luoda. Tekstimuotoisen aineiston tallentamiseen liittyy toinenkin yleinen virhetilanne. Jos yksikin lainausmerkeistä unohtuu, päädytään tilanteeseen, jossa R antaa uuden +-merkillä alkavan rivin, ja odottaa saavansa vielä lisää tietoja: 35

44 PERUSTEET > kirjoittaja<-c("jarno", "Tuimala) + Tilanteesta on poistuttava painamalla Escape (Esc)-näppäintä, ja aloitettava aineiston tallennus uudelleen. Toisinaan on tarpeen muodostaa erilaisia lukusarjoja tai jonoja, mahdollisesti vieläpä siten, että niissä on toistuvia rakenteita. Jos tällaiset lukusarjat ovat kovin pitkiä, ei niitä kannata luoda käsin kirjoittamalla kutakin lukua erikseen vektoriin. Apuna kannattaakin käyttää komentoja rep() ja seq(). Esimerkiksi lukusarja, joka koostuu sadasta ykkösestä, voidaan helposti luoda vektoriksi nimeltä x seuraavasti: >x<-rep(1, 100) Komennossa rep() annetaan ensimmäiseksi argumentiksi toistettavan numeron tai tekstin arvo, ja toiseksi argumentiksi toistokertojen määrä. Vastaavasti, jos on tarpeen luoda vaikkapa sarja numeroita nollasta yhteen siten, että kunkin numeron väli edelliseen verrattuna on 0.1, se onnistuu yksinkertaisimmin seuraavasti: >x<-seq(0, 1, 0.1) Komennossa seq() annetaan ensin numero, josta sarjan luominen aloitetaan, sitten mihin se päätetään, ja lopuksi numeroiden väli. Komennot voidaan myös yhdistää. Jos halutaan vaikkapa toistaa numerot 1 ja 2 juuri tässä järjestyksessä kymmenen kertaa, voidaan ensin luoda vektori, joka sisältää numerot 1 ja 2: >x<-c(1, 2) Ja tämän jälkeen toistaa vektori kymmenen kertaa: >y<-rep(x, 10) Jos tarvitaan vain sarja kokonaislukuja, voidaan se luoda nopeimmin käyttäen kaksoispiste- operaattoria: >1:10 [1] Tämäkin tulos voidaan luonnollisesti tallentaa vektoriksi: > x<-c(1:10) 36

45 R KIELEN PERUSTEET Laskutoimitukset vektoreilla Monet laskutoimitukset toimivat vektoreilla samaan tapaan kuin luvuilla. Jos käytetään vaikkapa summaoperaattoria kahden vektorin yhteenlaskemiseksi, tehdään laskutoimitukset ottamalla ensin kummastakin vektorista ensimmäinen luku, ja laskemalla ne yhteen. Tämän jälkeen summataan seuraavat lukuparit, ja tätä jatketaan kunnes kummatkin vektorit on käyty läpi. Esimerkiksi: > c(1,2)+c(3,4) [1] 4 6 Tällaisiin laskutoimituksiin liittyy kuitenkin pieni riski. Jos vektorit ovat eri mittaisia, käytetään lyhyemmän vektorin arvoja useampaan kertaan, joskin R antaa tällöin varoituksen. Esimerkiksi: > c(1,2)+c(3,4,6) [1] Warning message: In c(1, 2) + c(3, 4, 6) : longer object length is not a multiple of shorter object length Nyt R:n suorittamat laskutoimitukset ovat 1+3, 2+4 ja 1+6. Lyhyemmän ensimmäisen vektorin ensimmäistä arvoa käytettiin laskutoimituksissa kahteen kertaan eli vektorin ikään kuin pyörähti kertaalleen ympäri laskutoimitusten aikana. Hyvin suuri osa R:n komennoista on tarkoitettu vektoreitten käsittelyyn. Vektorin arvoista voidaan esimerkiksi laskea summa: > sum(c(1,2)) [1] 3 tai lukuarvot voidaan kertoa keskenään: >prod(c(2,3)) [1] 6 Kumpikin esimerkki koostuu kahdesta komennosta. Ensin komennolla c() on luotu luvuista vektori, ja sen jälkeen niistä on laskettu summa komennolla sum(). Komentoja voidaan antaa tällä tavoin sisäkkäin useampia samalla rivillä. Toinen tapa on rikkoa lasku kahdeksi erilliseksi komennoksi: 37

46 PERUSTEET >x<-c(1,2) >sum(x) [1] 3 Tässä luodaan ensimmäisellä rivillä luvuista vektori nimeltä x, ja seuraavalla rivillä lasketaan vektorin sisältämien lukujen summa. Vektoreilla tehtävät toimitukset ovat tyypillisesti hyvin nopeita, ja niitä kutsutaan vektoroiduiksi operaatioiksi. Jos jokin tehtävä on mahdollista toteuttaa vektoroituna, se kannattaa, sillä vaihtoehdot, yleensä erilaisten silmukoiden käyttö (näistä lisää myöhemmin), ovat useimmiten paljon hitaampia. Puuttuvien arvojen käsittely Käytännön työssä, erityisesti havainto- tai mittausaineistoja analysoitaessa on usein tärkeää erotella, onko jokin näyte mitattu, mutta sille ei saatu tulosta, vai eikö näytettä ole alunperinkään mitattu, jolloin kyseessä on puuttuva havainto. Mitatuille näytteille kannattaa miltei aina merkitä jokin numeroarvo, esimerkiksi nolla tai mahdollisen detektiorajan puolikas. Mittaamatta jääneille näytteille numeerista arvoa ei kannata kirjata, jolloin nämä kaksi tyyppiä voidaan erotella toisistaan. R:ssä puuttuvat havainnot kirjataan koodilla NA (Not Available). Puuttuvat arvot kuitenkin aiheuttavat hankaluuksia aineiston käsittelyssä. Ne voidaan kuitenkin poistaa aineistosta esimerkiksi ennen keskiarvon laskemista tai muita vastaavia toimituksia. Oletetaan, että edellisessä noppaesimerkissä emme yhdellä heitolla saaneetkaan tulosta. Ehkä noppa jäi syrjälleen seisomaan, eikä tulosta voitu lukea. Tällöin aineisto voisi näyttää esimerkiksi seuraavalta: >noppa2<-c(1, 2, 2, 4, 5, NA) Nyt puuttuva arvo on korvattu NA:lla. Alkuperäisistä tuloksista esimerkiksi keskiarvon laskeminen onnistuu helposti: >noppa <- c(1, 2, 2, 4, 5, 5) >mean(noppa) [1] mutta jos mukana on puuttuvia havaintoja, ei tulos olekaan lukuarvo, vaan puuttuva arvo: >mean(noppa2) [1] NA 38

47 R KIELEN PERUSTEET Ennen keskiarvon laskemista puuttuville arvoille on siis todella tehtävä jotakin. Joissakin komennoissa, kuten esimerkiksi komennossa mean(), on mahdollista määrittää, että puuttuvat arvot poistetaan ennen keskiarvon laskemista: >mean(noppa2, na.rm=true) [1] 2.8 Argumentti na.rm määrää miten puuttuvia arvoja käsitellään. Oletusarvoisesti se saa arvon FALSE, jolloin puuttuvia arvoja ei poisteta ennen laskentaa. Jos arvoksi muuttaa TRUE, kuten yllä on tehty, puuttuvat arvot poistetaan ennen laskentaa. Yleisesti tämä ratkaisu ei kuitenkaan toimi. Kaikki komennot eivät nimittäin tunnista argumenttia na.rm. Tällöin puuttuvat arvot on poistettava erikseen komennolla na.omit(): >noppa3<-na.omit(noppa2) Nyt vektori noppa3 sisältää vain muut kuin puuttuvat arvot: >noppa3 [1] attr(,"na.action") [1] 6 attr(,"class") [1] "omit" ja siitä voidaan laskea keskiarvo: > mean(noppa3) [1] 2.8 Toisinaan on hyödyllistä tietää, mitkä havainnot ovat puuttuvia. Tämän voi tehdä komennolla is.na(): > is.na(noppa2) [1] FALSE FALSE FALSE FALSE FALSE TRUE Jos vektorissa ollut arvo oli NA, se saa tulosteessa arvon TRUE, muutoin FALSE. 39

48 PERUSTEET Osajoukon poimiminen vektorista Vektoreista voidaan poimia osajoukkoja. Jos vektori sisältää vaikkapa kuusi lukuarvoa, kuten aiemmin esitellyssä noppaesimerkissä, voisimme valita niistä halutessamme esimerkiksi ensimmäisen käyttäen alaindeksiä. Alaindeksi merkitään muuttujan perään hakasulkuihin. Ensimmäisen numeron valitseminen muuttujasta noppa tapahtuisi siis seuraavasti: >noppa <- c(1, 2, 2, 4, 5, 5) >noppa[1] [1] 1 Hakasulkujen sisällä ilmoitetaan valittavien lukujen sijainti vektorissa. Yhden ainoan luvun sijaan voidaan siis hakasuluissa käyttää esimerkiksi vektoria: >x<-c(1, 2) >noppa[x] [1] 1 2 R-kielen rikkautena on, että sama asia voidaan toteuttaa monella eri tavalla. Ylläoleva esimerkki käyttäen vektoria alaindeksinä voidaan siis toteuttaa myös esimerkiksi: >noppa[c(1, 2)] [1] 1 2 Tai vaikkapa >noppa[1:2] [1] 1 2 Alaindeksin sisällä on siis mahdollista suorittaa myös komentoja. Alaindeksin avulla voidaan myös poistaa aineistosta puuttuvat havainnot. Luodaan ensin vektori, joka kertoo, onko kyseinen lukuarvo puuttuva vai ei: >noppa2<-c(1, 2, 2, 4, 5, NA) >z<-is.na(noppa2) Tämän jälkeen voidaan tuloksista valita vain ne, jotka eivät ole puuttuvia. Koska edellinen tulos palautti arvon TRUE niille havainnoille, jotka olivat puuttuvia, seuraava komento tulostaa ruudulle vain puuttuvat arvot: 40

49 R KIELEN PERUSTEET > noppa2[z] [1] NA Apuna on onkin käytettävä loogista ei -rakennetta eli alaindeksiin on lisättävä huutomerkki, joka tarkoittaa z-muuttujan negaatiota (TRUEarvoista tulee FALSE ja FALSE-arvoista vastaavasti TRUE), jolloin vain havaitut arvot poimitaan: > noppa2[!z] [1] Alaindeksin avulla on mahdollista myös poistaa arvoja vektorista. Tällöin indeksin eteen sijoitetaan miinusmerkki (-). Esimerkiksi vektorin noppa ensimmäinen havaintoarvo voidaan poistaa operaatiolla: >noppa[-1] [1] Useampien arvojen poistaminen yhtäaikaa toimii myös, kunhan käytetään alaindeksinä vektoria: >x<-c(1, 2) >noppa[-x] [1] Alaindeksissä voidaan käyttää myös vertailuoperaattoreita. Jos esimerkiksi vektorista noppa haluttaisiin poimia kaikki kolmea suuremmat lukuarvot, voidaan tämä toteuttaa luomalla ensin vektori, joka ilmoittaa onko kukin arvo suurempi kuin kolme: >x<-noppa>3 Tämä uutta vektoria voidaan sitten käyttää indeksinä kolmea suurempien arvojen poimimiseksi: >noppa[x] [1] Vektorin pituuden ja arvojen jakauman määrittäminen Vektorin pituus saadaan selville komennolla length(). Esimerkiksi vektorin noppa pituus on kuusi, sillä se sisältää kuusi lukua: 41

50 PERUSTEET >noppa <- c(1, 2, 2, 4, 5, 5) >length(noppa) [1] 6 Pituuden määrittämistä voidaan käyttää apuna esimerkiksi, kun halutaan selvittää kuinka moni vektorin arvoista on suurempi kuin, vaikkapa, kolme. Tällöin testataan ensin vertailuoperaatorilla, mitkä vektorin x arvot ovat kolmea suurempia, poimitaan ne uudeksi vektoriksi y, ja selvitetään lopuksi tämän uuden vektorin pituus: >x<-noppa>3 >y<-noppa[x] >length(y) [1] 3 Sama asia voidaan toteuttaa myös yksinkertaisemmin käyttäen hyväksi R:n ominaisuutta, että TRUE-arvot muunnetaan ykkösiksi ja FALSE-arvot nolliksi, jos niistä lasketaan vaikkapa summa. Vertailuoperaatio >noppa>3 [1] FALSE FALSE FALSE TRUE TRUE TRUE kertoo mitkä arvoista ovat suurempia kuin kolme palauttamalla arvon TRUE kyseisille arvoille. Jos näistä totuusarvoista lasketaan nyt summa: > sum(noppa>3) [1] 3 saadaan selville suoraan kolmosta suurempien arvojen lukumäärä. Vektorin arvojen jakauma taulukon muodossa esitettynä voidaan selvittää komennolla table(): >table(noppa) noppa Tulosteen ylin rivi ( ) kertoo vektorissa esiintyneet eri arvot, ja alempi rivi ( ) niistä kunkin esiintymisien määrän. Vektorin uudelleenkoodaaminen Vektori voidaan koodata uudelleen korvaamalla joitakin sen arvoista toisilla. Tällöin luodaan uusi vektori, johon uudelleenkoodatut arvot 42

51 R KIELEN PERUSTEET tallennetaan. Uudelleenkoodaamiseen on useita tapoja, joista yksinkertaisin lienee komennon ifelse() käyttö. Tällöin luodaan uusi muuttuja, jossa alkuperäinen vektori on muutettu binaariseksi eli kaksiarvoiseksi vektoriksi, jossa vektori sisältää vain kahdenlaisia arvoja. Seuraavassa esimerkissä vektori kertoo, mihin luokkaan yhdeksän tehtyä havaintoa kuuluvat. Numerolla yksi merkityt ovat Espoosta, kakkosella merkityt Helsingistä ja kolmosella merkityt Oulusta: >x<-c(1, 1, 1, 2, 2, 2, 3, 3, 3) Yhtä hyvin voidaan käyttää tekstiä sisältävää vektoria: >x<-c( Espoo, Espoo, Espoo, Helsinki, Helsinki, Helsinki, Oulu, Oulu, Oulu ) Jos haluttaisiin yhdistää espoolaiset ja helsinkiläiset yhdeksi ryhmäksi (uusi koodi on 1) ja jättää oululaiset omaksi ryhmäkseen (uusi koodi on 2) voitaisiin uudelleenkoodaaminen tehdä seuraavasti: >x2<-ifelse(x==3, 2, 1) Nyt uusi vektori x2 sisältää uudelleenkoodatun vektorin: >x2 [1] Komennolla ifelse() on kolme osaa. Ensimmäinen on jonkinlainen vertailu. Yllä verrattiin, onko vektorin x arvo yhtä suuri kuin 3 eli onko havainto Oulusta. Tämän jälkeen seuraavat argumentit kertovat mitä palautetaan, jos vertailu on tosi (tässä siis palautetaan 2), ja mitä palautetaan, jos vertailu ei ole tosi (tässä palautetaan 1). Koska vertailu on tosi vain oululaisille, koodataan kaikki oululaiset uudelleen koodilla 2, ja pääkaupunkiseutua edustaa uudelleenkoodatussa vektorissa arvo 1. Sama voitaisiin tehtä myös tekstiä sisältävälle vektorille seuraavasti: x2<-ifelse(x== Oulu, Oulu, PKS ) Monimutkaisempiin uudelleenkoodauksiin pitää käyttää jotakin muuta menetelmää. Käyttäjällä on paras kontrolli uudelleenkoodauksesta, jos käytetään alaindeksiä. Yllä esitetty koodaus voidaan tehdä myös alaindeksejä käyttäen seuraavasti. Kopioidaan ensin x uudeksi vektoriksi x2: >x2<-x 43

52 PERUSTEET Tämän jälkeen koodataan uudet arvot vektoriin x2. Ensimmäiseksi valitaan vektorista x kaikki kolmea pienemmät arvot: >x2[x<3] [1] Nyt näiden valittujen arvojen tilalle sijoitetaan arvoksi 1: >x2[x<3]<-1 Ja sama toistetaan alkuperäisille arvoille kolme, jotka korvataan uudella arvolla 2: >x2[x==3]<-2 Lopuksi saadaan uudelleenkoodattu vektori x2: >x2 [1] Komentoon ifelse() verrattuna alaindeksin käytön etuna on, että sitä voidaan käyttää vaikka kuinka monen erillisen arvon luomiseen, kun ifelse() soveltui vain kaksiarvoisten muuttujien luomiseen. Myös useampia kuin yksi vektori voidaan koodata uudelleen. Tällöin koodauskomentoon tai operaattoriin lisätään loogisia ehtoja käyttäen vertailuoperaattoreita. Jos koodataan kaksi vektoria, x ja y yhdeksi uudeksi vektoriksi kaksiarvoiseksi vektoriksi, käytetään komentoa ifelse(). Alla olevassa esimerkissä luodaan aluksi koodattavat vektorit, ja sitten muodostetaan uusi vektori siten, että jos x on 1 ja y on kolme, saa uusi vektori arvon 1, ja muille yhdistelmille annetaan uusi arvo 2: >x<-c(1, 2, 3) >y<-c(3, 2, 1) >z<-ifelse(x==1 & y==3, 1, 2) >z [1] Sama voitaisiin tietenkin toteuttaa myös alaindeksejä käyttäen seuraavasti. Luodaan aluksi tyhjä vektori z, joka sisältää aluksi pelkästään puuttuvia arvoja: z<-rep(na, 3) Tämän jälkeen vektori z täytetään uusilla arvoilla käyttäen yhtä aikaa sekä alaindeksiä, vertailuoperaattoria että loogista operaattoria: 44

53 R KIELEN PERUSTEET >z[x==1 & y==3]<-1 >z[x!=1 & y!=3]<-2 >z [1] Jos uusi vektori haluttaisiin luoda uudelleen koodattavien vektorien yhdistelmänä, saattaisi olla helpointa luoda uusi vektori vain yhdistämällä koodattavien vektorien arvot peräkkäin. Tämä onnistuu komennolla paste(). Yhdistämisen jälkeen näin luotu vektori voidaan tietysti edelleen uudelleen koodata vielä toiseksi uudeksi vektoriksi. Yhdistäminen tapahtuu yksinkertaisesti luomalla uusi vektori z, johon komennon paste() tulokset tallennetaan. >z<-paste(x, y, sep=. ) >z [1] "1.3" "2.2" "3.1" Nyt vektorissa z on vektorien x ja y alkuperäisarvot yhdistettynä ja pisteellä erotettuna. Komennon paste() argumentti sep määrittelee yhdistettävien arvojen erottimen. Erotin voi olla myös tyhjä tai välilyönti. Vektorin järjestäminen Vektorin arvot voidaan järjestää suuruus- tai aakkosjärjestykseen kahdella eri tavalla: Komentoa sort() käyttäen havainnot saadaan suoraan järjestykseen, komentoa order() käytettäessä pitää lisäksi käyttää alaindeksiä. Niinpä sort() soveltuukin yksittäisten vektorien järjestämiseen, ja order() lähinnä kokonaisten taulukoiden käsittelyyn, mistä myöhemmin lisää. Luodaan ensin vektori, jonka sisältö on epäjärjestyksessä: > x<-c(1, 2, 5, 4, 3) Vektori voidaan seuraavasti: sitten järjestää kasvavaan > sort(x) [1] Järjestäminen toimii samaa tapaan myös tekstille: 45 suuruusjärjestykseen

54 PERUSTEET >x<-c( Paavo, Uuno, Iivari ) >sort(x) [1] "Iivari" "Paavo" "Uuno" Järjestämisessä tosin kannattaa huomioida, että järjestämistapa voi riippua koneen maa-asetuksista (locale), ja kahdella eri koneella, joista toinen käyttää suomenkielistä ja toinen englanninkielistä järjestelmäversiosta, voi järjestämisen tulos olla erilainen. Komento order() on toinen tapa järjestää vektori, mutta se ei aseta arvoja suoraan oikeaan järjestykseen. Sen sijaan se palauttaa indeksin arvojen oikeasta järjestyksestä. Tämä lienee helpompi hahmottaa tekstimuotoisen vektorin avulla: >x<-c( Paavo, Uuno, Iivari ) >order(x) [1] Komennon tulostusta tulkittaisiin siten, että järjestetyissä arvoissa olisi ensimmäisenä alkuperäisen vektorin kolmas arvo (Iivari), sitten tulisi alkuperäisen vektorin ensimmäinen arvo (Paavo) ja viimeiseksi tuli alkuperäisen vektorin toinen arvo (Uuno). Arvot saadaan tähän järjestykseen yhdistämällä komento order() alaindeksin kanssa: >ind<-order(x) >x[ind] Tai lyhyemmin: >x[order(x)] Lukuarvojen järjestäminen tapahtuu komennolla order() samaan tapaan kuin tekstiaineistonkin. Faktorit Edellä on käsitelty vektoreita, jotka voivat sisältää lukuarvoja, tekstiä tai totuusarvoja (TRUE/FALSE). Toinen erityisesti tilastollisia analyysejä ajatellen erittäin keskeinen muuttuja- tai objektityyppi on faktori. Vektorin ja faktorin ero on lähinnä tekninen, sillä R käsittelee aina lukuarvoja sisältävää vektoria jatkuvana muuttujana eli R olettaa, että numerot järjestyvät tavanomaisesti pienimmästä suurimpaan. Jos vektorin sisältämät lukuarvot kuitenkin kertovat vain mihin ryhmään havainnot 46

55 R KIELEN PERUSTEET kuuluvat, pitää muuttuja syöttää faktoriksi, jotta R käsittelisi sitä oikein. Ongelmien välttämiseksi voi olla helpointa käyttää aina ryhmille jonkinlaisia tekstimuotoisia koodeja, esimerkiksi mies ja nainen vaikkapa koodien 1 ja 2 sijaan. Tällöin luokitteluasteikolliset muuttujat eivät mene sekaisin jatkuvien muuttujien kanssa. Faktoreita voidaan luoda suoraan komennolla factor() tai vektorista tietotyyppiä muuttamalla komennolla as.factor(). Komento as.factor() toimii samaan tapaan niin lukuarvoja kuin tekstiäkin sisältäville vektoreille. Ennen faktorin luomista komento järjestää arvot kasvavaan järjestykseen, ja pienin lukuarvo tai aakkosissa ensimmäisenä tuleva sana tai tekstipätkä tulee faktorin ensimmäiseksi tasoksi. Jos vektori x sisältää lukuarvoja, voidaan se muuttaa faktoriksi xv seuraavasti: >x<-c(1, 2, 5, 4, 3) >xv<-as.factor(x) >xv [1] Levels: Vastaavalla tavalla voidaan tekstimuotoinen vektori muuttaa faktoriksi: > x<-c("paavo", "Uuno", "Iivari") > xv<-as.factor(x) > xv [1] Paavo Uuno Iivari Levels: Iivari Paavo Uuno Komennon as.factor() haittapuolena on ettei sitä käytettäessä ole mahdollista asettaa faktorin tasojen arvoja tai järjestystä. Esimerkiksi lukuarvoja sisältävästä vektorista muunnosta tehtäessä voi olla tarpeen asettaa muodostuvaan faktoriin eri tasoille nimet. Oletetaan, että vektori x sisältää vain kahdenlaisia arvoja, joista 1 tarkoittaa miestä ja 2 naista. Jos tämä vektoria haluttaisiin muuttaa faktoriksi, voitaisiin numerot 1 ja 2 korvata faktorissa selväkielisillä koodeilla mies ja nainen: >x<-c(1, 2, 1, 1, 2, 2) >xv<-factor(x, labels=c("mies", "nainen")) >xv [1] mies nainen mies mies nainen nainen Levels: mies nainen Tässä yhteydessä olisi käytettävä komentoa factor(). Sen toinen argumentti labels kertoo mitkä nimet faktorin tasoille annetaan. Nimeämisessä pitää muistaa, että vektorin x numeroarvot asetetaan ennen 47

56 PERUSTEET faktoriksi muuntamista suuruusjärjestykseen, ja nimet pitää antaa juuri tässä järjestyksessä. Koska nimeäminen menee helposti väärin, kannattaa tulos tarkistaa. Tämä onnistuu vaikkapa laatimalla taulukon alkuperäisen vektorin ja siitä muunnetun faktorin arvoista: >table(x, xv) xv x mies nainen Sarakkeissa ovat faktorin arvot ja riveillä vektorin arvot. Jos muuntaminen ja nimeäminen meni oikein, pitäisi vektorin ja faktorin olla yhteneviä, kuten ne tässä näyttävät olevankin. Jos tavanomainen faktori edustaa luokitteluasteikollista muuttujaa, edustaa järjestetty faktori järjestysasteikollista muuttujaa. Järjestysasteikollisessa muuttujassa tasoilla on jokin järjestys: esimerkiksi tasoja voivat olla vauva, taapero, leikki-ikäinen, koululainen, ja ne menevät intuitiivisesti (ainakin perheellisillä) tähän järjestykseen. Järjestetty faktori luodaan seuraavassa tavanomaisen tekstimuotoisen vektorin perusteella, mutta sama periaate toimii myös lukuarvoja sisältäville vektoreille. Aluksi luodaan siis vektori x: >x<-c( taapero, vauva, leikki-ikäinen, koululainen ) Tavanomainen faktori sijoittaa koululaisen faktorin ensimmäiseksi (perus-) tasoksi: > factor(x) [1] taapero vauva leikki-ikäinen koululainen Levels: koululainen leikki-ikäinen taapero vauva Jotta faktorin tasot saadaan järjestykseen, on tarpeen lisätä komentoon kaksi argumenttia: levels ja ordered. Näiden yhtäaikainen käyttö luo järjestetyn faktorin. Argumentille levels annetaan muodostettavan faktorin tasot siinä järjestyksessä kuin ne oikeasti ovat pienimmästä suurimpaan : >xv<-factor(x, levels=c( vauva, taapero, leikki-ikäinen, koululainen ), ordered=t) > xv [1] taapero vauva leikki-ikäinen koululainen Levels: vauva < taapero < leikki-ikäinen < koululainen Kun järjestetyn faktorin tulostaa kirjoittamalla sen nimen komentoriville, 48

57 R KIELEN PERUSTEET tunnistaa faktorin heti järjestetyksi siitä, että sen tasoja erottavat pienempi kuin (<) merkit. Jos faktoreitten esittely ja vertailu vektoreihin tuntuu nyt käyttötarkoitukseltaan epäselvältä, niin asia selvinnee viimeistään, kun tutustutaan erilaisiin tilastollisiin menetelmiin, kuten lineaariseen regressioon. Erityisesti tilastollisen mallien, jollainen lineaarinen regressiokin siis on, tapauksessa faktoreitten ja vektoreitten välinen ero on tärkeä ja hyvin keskeistä ymmärtää. Objektien nimeäminen Edellä on käsitelty yhdestä muuttujasta, joka voi olla R:ssä vektori tai faktori, koostuvien aineistojen käsittelyä. Ennen siirtymistä laajempien aineistojen käsittelyyn, muutama sananen objektien ja aineistojen nimeämisestä R:ssä. Objektin nimi voi olla miltei miten pitkä hyvänsä, mutta kovin pitkiä nimiä ei kannata käyttää, sillä niiden kirjoittaminen uudelleen on tuskallista ja virhealtista. Nimi on parhaimmillaan sellainen, että siitä helposti tunnistaa mitä objekti sisältää. Nimi voi koostua kirjaimista, numeroista ja muutamista erikoismerkeistä (muun muassa alaviiva ja piste), mutta se ei saa alkaa numerolla. Hyvä nimi voisi siis olla vaikkapa rawdata, mutta nimeä 1.data ei kelpuuteta, koska se alkaa numerolla, ja se antaisi virheilmoituksen. Vektorien yhdistäminen Kaksi vektoria voidaan yhdistää joko suoraan peräkkäin, jolloin tuloksena on yksi alkuperäisiä pidempi vektori, tai taulukoksi, jolloin kukin sarake tai rivi, riippuen yhdistämistavasta, vastaa yhtä alkuperäisistä vektoreista. Peräkkäinen yhdistäminen Vektorien yhdistäminen peräkkäin tapahtuu komennolla c(), jolla vektoreita jo aiemmin luotiinkin. Esimerkiksi vektorit x ja y voidaan yhdistää seuraavasti. Luodaan aluksi vektorit: >x<-c(1, 2, 3) >y<-c(4, 5, 6) 49

58 PERUSTEET ja yhdistetään ne sitten: >z<-c(x, y) >z [1] Yhdistäminen taulukoksi matriisin luominen Usein yksittäiset vektorit kuvaavat eri asioita, kuten henkilöiden painoja ja pituuksia, eikä niiden yhdistäminen peräkkäin ole paras tapa esittää aineisto. Ennemminkin kannattaa esittää aineisto taulukkomuodossa. R:ssä on kaksi keskeistä kaksiulotteisen taulukon tallentamiseen soveltuvaa objektityyppiä, matriisi (matrix) ja datakehikko (data frame). Näiden erona on, että matriisissa kaikkien sarakkeiden tulee sisältää samantyyppistä aineistoa, esimerkiksi lukuja tai tekstiä, mutta matriisiin ei voi yhdistää esimerkiksi yhtä lukuarvosaraketta ja yhtä tekstisaraketta. Datakehikot sen sijaan sallivat eri tyyppisten sarakkeiden yhdistämisen samaan datakehikoon. Kahden tai useamman vektorin yhdistäminen matriisiksi tapahtuu komennolla cbind() tai rbind(), riippuen siitä, halutaan vektorit yhdistää sarake- vai rivi kerrallaan. Esimerkiksi sarakekerrallaan vektoreiden x ja y yhdistäminen onnistuu seuraavasti: >x<-c(1, 2, 3) >y<-c(4, 5, 6) >z<-cbind(x, y) >z x y [1,] 1 4 [2,] 2 5 [3,] 3 6 Tuloksena on siis taulukko, jossa on kaksi saraketta, jotka on nimetty alkuperäisten vektorien mukaan x:ksi ja y:ksi. Riveillä ei ole varsinaisia nimiä, mutta niille on annettu juokseva numero. Jos yhdistäminen tehdään rivi kerrallaan, on tuloksena hieman eri näköinen taulukko, jossa kuitenkin ovat samat luvut: >x<-c(1, 2, 3) >y<-c(4, 5, 6) >z<-rbind(x, y) 50

59 R KIELEN PERUSTEET >z x y [,1] [,2] [,3] Nyt taulukko onkin vaakasuorassa, ja kukin rivi vastaa yhtä alkuperäistä vektoria. Jos yhdistettävät vektorit ovat eri mittaisia, käytetään lyhyemmän arvoja useampaan kertaan, kuten näimme jo pelkkien vektorien tapauksessakin tapahtuvan: >x2<-c(1:4) >y<-c(4, 5, 6) >z<-cbind(x2, y) >z x2 y [1,] 1 4 [2,] 2 5 [3,] 3 6 [4,] 4 4 Warning message: In cbind(x2, y) : number of rows of result is not a multiple of vector length (arg 2) Jos vektorit ovat siis eri mittaisia, R huomaavaisesti huomauttaa asiasta varoituksella, mutta tekee kuitenkin yhdistämisen. Nyt vektorin y ensimmäinen arvo (4) esiintyy luodun taulukon toisessa sarakkeessa kahteen kertaan, koska vektori ikään kuin pyörähti ympäri. Toinen vaihtoehto on ensin luoda tyhjä matriisi komennolla matrix(), ja sitten täyttää se vektoreilla. Tyhjä matriisi luodaan siten, että siihen tulee esimerkiksi yhtä monta saraketta kuin yhdistettäviä vektoreita on, ja rivejä yhtä monta kuin yksittäisessä vektorissa on havaintoarvoja. Sarakkeiden määrä märitellään argumentilla ncol, rivien määrä argumentilla nrow ja matriisiin sijoitettavat arvot argumentilla data. Koska haluamme luoda tyhjän matriisin, kuhunkin taulukon soluun sijoitetaan aluksi puuttuva arvo NA: m<-matrix(ncol=2, nrow=3, data=na) Tämän jälkeen matriisi voidaan täyttää käyttäen alaindeksiä. Ensimmäiseen sarakkeeseen sijoitetaan vektorin x arvot, ja toiseen sarakkeeseen vektorin y arvot: >x<-c(1, 2, 3) >y<-c(4, 5, 6) 51

60 PERUSTEET >m[,1]<-x >m[,2]<-y >m [,1] [,2] [1,] 1 4 [2,] 2 5 [3,] 3 6 Alaindeksien käyttön matriisien ja datakehikoiden kanssa palaamme tarkemmin seuraavissa kappaleissa. Yhdistäminen taulukoksi datakehikon luominen Kahdesta tai useammasta vektorista voidaan luodaan datakehikko komennolla data.frame(). Komennon argumentteina luetellaan yhdistettävät vektorit, ja kustakin vektorista tehdään automaattisesti yksi taulukon sarakkeista: >x<-c(1, 2, 3) >y<-c(4, 5, 6) >z<-data.frame(x, y) >z x y Taulukko on nyt varsin samannäköinen kuin aiemmin komennolla cbind() luotu. Sarakkeilla on nimet, ja riveillä on juokseva numerointi. Erona on, että komento cbind() luo matriisin, ja tässä on luotu datakehikko. Vaikka aineisto näyttääkin samalta, on objektityyppi erilainen, millä voi olla merkitystä joidenkin komentojen toiminnan kannalta: jotkut komennot huolivat vain matriisin, eivät datakehikkoa, joillekin komennoille tällä erolla ei ole merkitystä. Esimerkkejä tällaisista komennoista tullaan näkemään ainakin tämän kirjan grafiikkaa käsittelevässä osassa. Taulukoiden rivien ja sarakkeiden nimet ja nimeäminen Taulukoiden sarakkeille ja riveille voidaan antaa nimet. Kahdelle sarakkelle tai kahdelle riville ei voi antaa samaa nimeä, vaan nimien tulee olla yksilöllisiä. Sen sijaan rivien ja sarakkeiden nimet voivat olla keskenään samanlaisia. Sarakkeiden ja rivien nimeämiseksi on ensin tarkistettava 52

61 R KIELEN PERUSTEET niiden nykyiset nimet. Tähän käytetään komentoja colnames(), joka palauttaa sarakkeiden nimet, ja rownames(), joka palauttaa rivien nimet. Luodaan ensin datakehikko nimeltä z: >x<-c(1, 2, 3) >y<-c(4, 5, 6) >z<-data.frame(x, y) >z x y Datakehikon z sarakkeiden nimet voidaan nyt tarkistaa: >colnames(z) [1] "x" "y" Samaan tapaan voidaan tarkistaa myös z:n rivien nimet: >rownames(z) [1] "1" "2" "3" Riveillä ei vielä ole varsinaisia nimiä, ainoastaan juoksevat numerot, jotka niille on annettu, kun datakehikko luotiin. Jos rivit haluttaisiin nimetä vaikkapa nimillä a, b, ja c, se kävisi seuraavasti. Luodaan ensin tekstivektori, joka sisältää rivien nimet: >nimet<-c("a", "b", "c") >nimet [1] "a" "b" "c" Tämän jälkeen voidaan antaa riveille nimet: >rownames(z)<-nimet Nyt datakehikon z rivien juoksevat numerot on korvattu niille juuri annetuilla nimillä: >z x y a 1 4 b 2 4 c 3 4 Samaan tapaan voidaan myös sarakkeille antaa uudet nimet. Esimerkiksi 53

62 PERUSTEET datakehikon z sarakkeet voitaisiin nimetä pituudeksi ja painoksi: >nimet<-c("pituus", "paino") >colnames(z)<-nimet Osa-aineiston poimiminen taulukosta Osa-aineistojen poimiminen taulukoista, joko matriiseista tai datakehikoista perustuu samaan alaindeksin käytön ideaan kuin vektoreiden tapauksessa. Kun vektoreiden tapauksessa käytettiin vain yhtä alaindeksiä, jota esittämään käytettiin hakasulkuja muuttujan nimen perässä, käytetään taulukoiden tapauksessa hakasuluissa kaksinkertaista alaindeksiä. Luodaan ensin datakehikko z: >x<-c(1, 2, 3) >y<-c(4, 5, 6) >z<-data.frame(x, y) >nimet<-c("a", "b", "c") >rownames(z)<-nimet Tai lyhyemmin vain: > z<-data.frame(x=c(1:3), y=c(4:6)) > rownames(z)<-letters[1:3] Komennossa data.frame() voidaan datakehikon sarakkeille määrätä nimet, kuten tässä on tehty (x ja y). Komento letters() palauttaa englantilaiset kirjaimet aakkosjärjestyksessä. Datakehikon rivien nimeämiseen käytämme kolmea ensimmäistä kirjainta, jotka poimimme alaindeksiä käyttäen. Lopputulos on molemmilla esitetyillä tavoilla sama: >z x y a 1 4 b 2 4 c 3 4 Nyt datakehikosta voidaan poimia yksi rivi sijoittamalla ylhäältä alaspäin laskien sen järjestysnumero tai nimi alaindeksiin. Esimerkiksi ensimmäinen rivi voitaisiin poimia seuraavasti: 54

63 R KIELEN PERUSTEET >z[1,] x y a 1 4 Tulos voidaan luonnollisesti tallentaa myös uudeksi objektiksi: >z2<-z[1,] Nyt alaindeksissä on, erona vektorien käsittelyyn, myös pilkku. Ennen pilkkua luetellaan poimittavat rivit, ja pilkun jälkeen poimitavat sarakkeet. Rivit voidaan luetella järjestysnumeron lisäksi käyttäen rivien nimiä. Ensimmäinen rivi voidaan siis poimia myös: >z["a",] x y a 1 4 Koska kyseessä on rivin nimi, joka on tekstimuodossa, pitää sen ympärille lisäksi sijoittaa lainausmerkit. Sarakkeiden poimimnen tapahtuu samaan tapaan kuin rivienkin, mutta nyt sarakkeet siis luetellaan alaindeksissä pilkun jälkeen: >z[,1] tai >z[,"x"] Molemmat vaihtoehdot palauttavat ensimmäisen sarakkeen sisältämät arvot: [1] Sarakkeisiin voidaan lisäksi viitata erityisellä viittausoperaattorilla, jona toimii dollarin merkki $. Viittausoperaattori sijoitetaan heti taulukon nimen perään, ja sen jälkeen kirjoitetaan sarakkeen nimi. Datakehikon z sarake x saadaan siis poimittua seuraavasti: >z$x [1] Samalla kertaa voidaan poimia useampia rivejä: 55

64 PERUSTEET >z[c(1, 3),] x y a 1 4 c 3 4 tai sarakkeita >z[,c(1, 2)] x y a 1 4 b 2 4 c 3 4 tai sekä rivejä että sarakkeita: >z[c(1, 3), c(1)] [1] 1 3 Taulukosta voidaan poimia rivejä tai sarakkeita myös vertailuoperaattoreita käyttäen. Esimerkiksi, poimitaan datakehikosta z kaikki sellaiset rivit, joilla muuttujan x arvo on suurempi tai yhtäsuuri kuin 2: >zind<-z$x>=2 > zind [1] FALSE TRUE >z[zind,] x y b 2 4 c 3 4 TRUE Tai lyhyemmin vain: >z[z$x>=2,] x y b 2 4 c 3 4 Sama toimenpide voidaan tehdä myös yksinomaan alaindeksejä käyttäen, jos se tuntuu loogisemmalta: >z[z[,1]>=2,] x y b 2 4 c

65 R KIELEN PERUSTEET Edellä käsitellyn alaindeksin lisäksi voidaan osajoukon poimimiseen käyttää komentoa subset(), joka lienee useimpiin tarkoituksiin riittävä. Sen avulla voidaan poimia sekä rivejä että sarakkeita samaan tapaan kuin alaindeksiä käytettäessä, mutta erona on, että poiminnassa pitää käyttää vertailuoperaattoreita. Komennolla subset() voidaan poimia osajoukkoja vektoreista, matriiseista ja datakehikoista. Esimerkiksi ensimmäisen rivin poimiminen datakehikosta z tapahtuu komennolla (poimii rivit, joilla x on yhtäsuuri kuin 1): >subset(z, x==1) x y a 1 4 Ensimmäisen sarakkeen poimiminen puolestaan onnistuu komennolla: >subset(z,,x) x a 1 b 2 c 3 Nyt käytetyssä komennossa ei ole annettu lainkaan argumenttia, joka määrittelisi poimittavat rivit, ja argumentti on korvattu pilkulla. Sama poiminta ehkä helpommin tulkittavissa olevalla tavalla toteutettuna: >subset(x=z, select=x) x a 1 b 2 c 3 R:ssä komennot on aina mahdollista antaa kahdella eri tavalla. Joko niin, että argumenttien saamat arvot annetaan siinä järjestyksessä kuin argumentit on komennon ohjesivulla kuvattu tai käyttäen argumenttien nimiä ja antamalla niille arvot käyttämällä yhtäsuuruus-merkkiä argumentin nimen ja sen saaman arvon välillä. Komennon subset() tapauksessa ensin tulee vektorin tai taulukon nimi, sitten poimittavat rivit ja lopuksi poimittavat sarakkeet. Komento voidaan siis esimerkiksi kirjoittaa kokonaisuudessa joko muodossa: >subset(z, x>=0, select=x) tai >subset(x=z, subset=x>=0, select=x) 57

66 PERUSTEET Molemmat komennot palauttavat datakehikon z ensimmäisen sarakkeen. Taulukoiden järjestäminen Vektorien järjestämisen yhteydessä esiteltiin komento order(), jota käytetään myös taulukoiden järjestämiseen. Taulukon järjestämiseksi komento yhdistetään sopivalla tavalla alaindeksin kanssa. Idea konkretisoituu varmasti parhaiten esimerkin avulla, joten luodaan ensin viisirivinen taulukko nimeltä dat, jossa on kolme saraketta: >dat<-data.frame(x=letters[1:5], y=c(1,3,4,2,5), z=c(6:10)) >dat x y z 1 a b c d e 5 10 Jos taulukon rivit haluttaisiin järjestää sarakkeen y suhteen siten, että y:n arvot tulisivat suuruusjärjestykseen, tämän tapahtuisi esimerkiksi komennolla: >dat[order(dat$y),] x y z 1 a d b c e 5 10 Tulos voidaan tietenkin jälleen tallentaa uuteen objektiin: >dat2<-dat[order(dat$y),] Arvojen saaminen pienenevään järjestykseen tapahtuu samaan tapaan, mutta lisäämällä komentoon order() argumentin decreasing arvoksi TRUE: >dat[order(dat$y, decreasing=true),] x y z 5 e c b d a

67 R KIELEN PERUSTEET Taulukko voidaan järjestää yhtäaikaisesti useammankin sarakkeen suhteen lisäämällä sarakkeet yksittäin komennon order() argumenteiksi, joskaan esimerkkimme tapauksessa tämä ei muuta tulosta: >dat[order(dat$y, dat$z),] x y z 1 a d b c e 5 10 Laskentaa taulukoilla Taulukosta voidaan erottaa joko yksi sarake tai yksi rivi omaksi vektorikseen, ja tehdä jatkokäsittelyt sitä käyttäen. Toisinaan on kuitenkin tehokkaampaa kohdistaa esimerkiksi laskutoimitukset kokonaiseen taulukkoon. Kullekin taulukon riville tai sarakkeelle voidaan laskea sen sisältämien lukuarvojen summa tai keskiarvo. Summan laskemiseen soveltuvat komennot colsums() ja rowsums(), jotka palauttavat sarakkeiden ja rivien summat. Keskiarvojen laskemiseen voidaan vastaavasti soveltaa komentoja colmeans() ja rowmeans(). Muodostetaan ensin esimerkkiä varten taulukko mat: >mat<-data.frame(x=c(1:5), y=c(6:10), z=c(11:15)) >mat x y z Tämän jälkeen voidaan laskea rivien ja sarakkeiden summat ja keskiarvot: >rowsums(mat) [1] > colsums(mat) x y z > rowmeans(mat) [1]

68 PERUSTEET > colmeans(mat) x y z Yleisemmin voidaan taulukon riveihin ja sarakkeisiin kohdistaa mikä tahansa toimenpide käyttäen apuna komentoa apply(). Se kuuluu laajempaan apply-komentojen perheeseen, johon kannattaa tutustua tarkemmin ohjesivuilta. Komennon apply() avulla edellä lasketut keskiarvot voitaisiin esimerkiksi laskea seuraavasti: >apply(x=mat, MARGIN=1, FUN=mean) [1] >apply(x=mat, MARGIN=2, FUN=mean) x y z Komento apply() tarvitsee kolme argumenttia. Argumentti X määrittää sen taulukon nimen, jolle laskentaa tehdään. Argumentti MARGIN määrää tehdäänkö laskentaa riveille vai sarakkeille. Jos se saa arvon 1, tehdään laskenta riveille, arvolla 2 sarakkeille. Argumentti FUN määrää kullekin riville tai sarakkeelle suoritettavan funktion. Taulukoiden yhdistäminen Taulukoita voidaan yhdistää suuremmiksi taulukoiksi jo edellä esitellyillä komennoilla rbind() ja cbind(), jos niissä on sama määrä sarakkeita tai rivejä. Lisäksi komennolla data.frame() voidaan yhdistää useampia taulukoita, jos niissä on sama määrä sarakkeita. Lisäksi taulukoista voidaan muodostaa yhdistelmätaulukoita siten, että yhdistelmätaulukkoon otetaan alkuperäisistä taulukoista vain sellaiset tapaukset (rivit), jotka esiintyvät molemmissa taulukoissa. Tällöin käytetään komentoa merge(). Muodostetaan ensin kaksi taulukkoa mat1 ja mat2, ja nimikoidaan niiden sarakeet ja nimet: >mat1<-data.frame(x=c(1:5), y=c(6:10)) >rownames(mat1)<-letters[1:5] >mat2<-data.frame(z=c(11:15), s=c(16:20)) >rownames(mat2)<-letters[3:7] > mat1 x y a 1 6 b 2 7 c 3 8 d 4 9 e

69 R KIELEN PERUSTEET > mat2 z s c d e f g Nyt taulukoiden sarakkeet voidaan yhdistää komennolla cbind(): > cbind(mat1, mat2) x y z s a b c d e Riveittäin yhdistäminen ei nyt onnistu, koska eri taulukoiden riveillä on eri nimet: > rbind(mat1, mat2) Error in match.names(clabs, names(xi)) : names do not match previous names Jos riveillä olisi samat nimet, ja rivit olisivat kummassakin taulukossa samassa järjestyksessä, onnistuisi riveittäin yhdistäminen komennolla rbind(), kuten yllä on esitetty. Koska riveillä nyt on eri nimet, pitää yhdistämiseen käyttää komentoa merge(): > merge(x=mat1, y=mat2, by.x=0, by.y=0) Row.names x y z s 1 c d e Komento merge() saa neljä argumenttia. Argumentit x ja y määrittävät yhdistettävät taulukot, tässä siis mat1 ja mat2. Argumentit by.x ja by.y määrittävät ne sarakkeet, joiden perusteella yhdistäminen toteutetaan. Jos niiden arvoksi annetaan nolla, kuten tässä, tapahtuu yhdistäminen käyttäen rivinimiä. Argumentti by.x määrittää ensimmäisen taulukon sarakkeen, ja by.y jälkimmäisen taulukon sarakkeen. Sarakkeet voi määrittää myös käyttäen sarakkeen otsikkoa tyyliin by.x="nimi", jossa nimi on siis ensimmäisen taulukon sen sarakkeen nimi, jossa rivien tunnisteet ovat. 61

70 PERUSTEET Eri tyyppisten objektien tallentaminen yhdeksi objektiksi Jo datakehikko voi sisältää eri tyyppistä tietoa eri sarakkeissa. Yksi sarake voi sisältää lukuarvoja, toinen tekstiä, ja kolmas päivämääriä. Datakehikko ei kuitenkaan voi koostua kuin yksittäisten vektorien yhdistelmistä. Esimerkiksi kahta eri kokoista taulukkoa ei voida esittää yhtenä datakehikkona. Tällöin voidaan käyttää tiedon tallentamiseen listaa. Lista koostuu useista erillisistä objekteista, jotka voivat olla keskenään eri typpiä. Yksi listan sisältämä objekti voi esimerkiksi olla matriisi, toinen datakehikko ja kolmas päivämääriä sisältävä vektori. Listoja voidaan muodostaa komennolla list(). Muodostetaan ensin vektori x ja datakehikko mat: >x<-c(1:10) >mat<-data.frame(x=c(1:5), y=c(6:10)) Tämän jälkeen x ja mat voidaan yhdistää yhdeksi listaksi: >l<-list(x, mat) >l [[1]] [1] [[2]] x y Nyt listan sisältämiin objekteihin voidaan viitata alaindeksiä käyttäen: >l[[2]] x y Listaa muodostettaessa objektit voidaan myös nimetä samalla periaatteella kuin datakehikon sarakkeet datakehikkoa luotaessa: >l<-list(x=x, mat=mat) 62

71 R KIELEN PERUSTEET Tämän jälkeen operaattorilla: >l$x [1] listan 4 5 sisältämiin objekteihin voidaan viitata $ Yksittäisen objektin, esimerkiksi datakehikon sarakkeisiin voidaan edelleen viitata lisäämällä perään vielä toinen $-operaattori: >l$mat$x [1] Listan sisältämien objektien nimet voidaan selvittää komennolla names(): > names(l) [1] "x" "mat" Objektityypin selvittäminen Kaikkia komentoja ei voida käyttää kaikille objektityypeille. Niinpä toisinaan tulee tarvetta selvittää mikä objektityyppi on kysessä. Muodostetaan ensin kaksi vektoria, datakehikko ja lista: >x<-c(1:10) >y<-letters >mat<-data.frame(x=c(1:5), y=c(6:10)) >l<-list(x=x, mat=mat) Objektityyppi selvitetään komennolla class(): >class(x) [1] "integer" >class(y) [1] "character" >class(mat) [1] "data.frame" >class(l) [1] "list" Vektorien x ja y tyypiksi palautetaan kokonaisluku (integer) ja teksti (character), vaikke ne ovatkin vektoreita. Datakehikolle ja listalle sen sijaan palautetaan niiden objektityypin englanninkielinen nimi (data.frame ja list). Objektien ominaisuuksien selvittämisessä on hyötyä myös niiden havaintojen, rivien ja sarakkeiden lukumäärän selvittämisestä. Objektin 63

72 PERUSTEET pituus, vektorien tapauksessa yksittäisten arvojen lukumäärä, taulukoiden tapauksessa sarekkeiden lukumäärä ja listojen tapauksessa erillisten komponenttien määrä saadaan selville komennolla length(): > length(x) [1] 10 > length(y) [1] 26 > length(mat) [1] 2 > length(l) [1] 2 Objektin rivien ja sarakkeiden lukumäärä saadaan selville komennolla dim(). Vektoreille ja listoille tätä ei voida käyttää, mutta taulukoille tämä toimii hyvin: > dim(x) NULL > dim(y) NULL > dim(mat) [1] 5 2 > dim(l) NULL Datakehikon mat tapauksessa komento palauttaa ensin rivien lukumäärän (5) ja sitten sarakkeiden lukumäärän (2). Objektien sisään voidaan kurkistaa komennolla str(). Se antaa lyhyen kuvauksen objektin tyypistä, ja eräänlaisian yhteenvetotietoja objektin sisältämistä tiedoista. Esimerkiksi objekti mat on datakehikko, joka koostuu viidestä havainnosta ja kahdesta muuttujasta, joiden nimet ovat x ja y, ja joihin voidaan viitata $-operaattorilla: > str(mat) 'data.frame': 5 obs. of $ x: int $ y: int variables: Samaan tapaan tulkittuna objekti l on lista, joka sisältää kaksi erillistä objektia, x ja mat. Objekti x on kokonaislukuja sisältävä vektori, jossa on kymmenen havaintoa. Objekti mat on datakehikko, joka koostuu viidestä havainnosta ja kahdesta muuttujasta. Sekä itse listan että sen sisältämän matriisin tietoihin voidaan viitata $-operaattorilla: 64

73 R KIELEN PERUSTEET > str(l) List of 2 $ x : int [1:10] $ mat:'data.frame': 5 obs. of 2 variables:..$ x: int [1:5] $ y: int [1:5] Objektityypistä toiseen muuntaminen Objekteja voidaan muuntaa tyypistä toiseen. Jo aiemmin muodostettiin vektorista faktorin komennolla as.factor(). Kaikki tähän käytettävät komennot ovat samaa tyyppiä eli alkavat sanalla as. Tällaisia ovat esimerkiksi as.character(), as.data.frame(), as.factor(), as.matrix(), as.numeric() ja as.vector(). Matriisin muuntaminen datakehikoksi ja datakehikon muuntaminen matriisiksi ovat usein data-analyysin kannalta keskeisiä toimenpiteitä. Datakehikon mat muuntaminen matriisiksi käy seuraavasti: >mat<-data.frame(x=c(1:5), y=c(6:10)) >mat x y >mat2<-as.matrix(mat) >mat2 x y [1,] 1 6 [2,] 2 7 [3,] 3 8 [4,] 4 9 [5,] 5 10 Vastaavasti matriisin mat2 muuntaminen takaisin datakehikoksi tapahtuu komennolla: >mat3<-as.data.frame(mat2) >mat3 x y

74 PERUSTEET Komennot as.character(), as.factor(), as.numeric() ja as.vector() liittyvät numeeristen ja tekstivektoreiden sekä faktoreiden muunnoksiin. Numeerinen vektori x voidaan muuntaa tekstivektoriksi ja takaisin seuraavasti: >x<-c(1:5) >x2<-as.character(x) >x2 [1] "1" "2" "3" "4" "5" >x3<-as.numeric(x2) >x3 [1] Vektori voi sisältää sekä numeerisia arvoja, että tekstiä, ja tällöin muunnos voi osittain onnistua ja osittain epäonnistua. Epäonnistuneiden arvojen osalta muunnoksen jälkeen palautetaan arvoksi NA: >x<-c(1, "a", "b") >as.numeric(x) [1] 1 NA NA Warning message: NAs introduced by coercion Faktori voidaan muuntaa takaisin vektoriksi esimerkiksi: >y<-as.factor(c(1, "a", "b")) >as.vector(y) [1] "1" "a" "b" Jos faktori halutaan muuntaa numeeriseksi vektoriksi, on muunnoksessa lisäksi käytettävä komentoa as.numeric(): > y<-as.factor(c(1, 2, 3, 1.5)) > as.vector(y) [1] "1" "2" "3" "1.5" >as.numeric(as.vector(y)) [1] Huomaa, että tekstivektorin ja numeerisen vektorin erottaa siis siitä, että tekstivektorin ollessa kyseessä, sen arvot luetellaan lainausmerkeissä, numeerisen vektorin arvot ilman lainausmerkkejä. 66

75 R KIELEN PERUSTEET Päivämäärien käsittely Päivämäärien käsittely eroaa tavanomaisten lukuarvoja tai tekstiä sisältävien vektorien käsittelystä. Päivämäärien oikeaoppinen käsittely on tärkeää etenkin, jos niitä käytetään tilastollisissa analyyseissä. Myös tilastollisen grafiikan yhteydessä päivämääriä kannattaa käsitellä kuten seuraavassa esitetään. Aika voidaan esittää monessa eri muodossa. Anglokaanisissa maissahan on tapana esittää päiväys muodossa, jossa ensin mainitaan vuosi, sitten kuukausi ja lopuksi päivä. Suomessa puolestaan päiväys esitetään juuri käänteisessä järjestyksessä: ensin päivä, sitten kuukausi ja lopuksi vuosi. R:ssä nämä päiväykset voitaisiin ensin tallentaa vaikkapa yksinkertaisiksi vektoreiksi d1 ja d2, jossa d1 sisältää anglikaanisen päiväyksen, d2 suomalaisen päiväyksen: >d1<-c(" ") >d2<-c(" ") Päivien, kuukausien ja vuosien erottamiseen käytetyllä merkillä ei ole niin väliä. Edellä mainittujen tavuviivan ja pisteen lisäksi käytössä voi olla myös kenoviiva, mistä esimerkkinä luomme anglokaanisen päiväyksen vektoriin d3: >d3<-c("2010/03/08") Nyt tekstimuotoiset vektorit d1, d2 ja d3 voidaan muuttaa R:ssä päivämääriksi komennolla as.date(). >as.date(x=d1, format="%y-%m-%d") >as.date(x=d2, format="%d.%m.%y") >as.date(x=d3, format="%y/%m/%d") Kaikki palauttavat saman päivämäärän: [1] " " Komento as.date saa kaksi argumenttia: x on sen vektorin nimi, josta muunnos tehdään, ja format kertoo missä muodossa päivämäärä on ilmoitettu. Esimerkissämme vuosi on ilmoitettu pitkässä muodossa, jossa ovat mukana tuhannet ja sadat, joten sitä merkitään %Y:llä. Kuukausi ja päivä ovat tavanomaisessa muodossaan, joten niitä merkitään %m:llä ja %d:llä. Koodit on helppo muistaa, koska ne ovat lyhennyksiä englanninkielisistä vuotta (Year), kuukautta (month) ja päivää (day) tarkoittavista sanoista. 67

76 PERUSTEET Päivämäärien muunnoksiin voidaan käyttää myös komentoa strptime(). Komentojen as.date() ja strptime() erona on, että as.date() muuntaa päivämäärän date-tyyppiseksi objektiksi ja strptime() POSIX-tyyppiseksi objektiksi. R seuraa päivämäärien esittämisessä POSIX-tyyliä, mutta osaa yleensä käsitellä kummalla tahansa tavalla muodostettuja päivämääriä oikein. Komennon strptime() ohjesivulla on lueteltu ne vaihtoehdot, joita päivämäärän formaatin asettamiseen voidaan käyttää. Esimerkiksi Excelissä usein käytetty päivämäärän muoto on 8. maaliskuuta Tallennetaan tämä vektoriin d4: >d4<-c("8. maaliskuuta 2010") Tämä voidaan muuntaa päivämääräksi seuraavasti. Päivän formaatti on %d, ja sitä seuraa yksi piste sekä välilyönti. Kuukauden formaatti on pitkä eli kuukauden nimi on kirjoitettu auki kokonaisuudessaan, mitä vastaa formaatti %B. Lisäksi sen perässä on sijapääte ta, joka pitää ottaa huomioon. Kuukautta erottaa vuodesta välilyönti, ja vuosi on pitkässä muodossa, mitä vastaa formaatti %Y. Tästä voidaan muodostaa komento, joka muuntaa päivämäärän oikeaan muotoon: >as.date(d4, format="%d. %Bta %Y") [1] " " Nykyinen aika ja päiväys voidaan tarkistaa joko komennolla Sys.time() tai komennolla date(). Näiden erona on, että ensimmäinen palauttaa päivämäärän POSIX-muodossa, jälkimmäinen tekstimuotoisena vektorina: > Sys.time() [1] " :43:15 EET" > date() [1] "Mon Mar 08 09:43: " Nämä ovat hyödyllisiä monessakin mielessä. Niillä on esimerkiksi helppo leimata jokin tulostiedosto sen päivämäärän mukaan, jona se on luotu. Myöhemmin tällainen menettely helpottaa tiedostojen erottamista toisistaan. Päivämäärillä voidaan myös laskea. Luodaan ensin päivämäärämuotoinen objekti d4 tekstivektorista d1: >d4<-as.date(x=d1, format="%y-%m-%d") Tämän jälkeen objektilla d4 voidaan tehdä esimerkiksi yhteen- ja 68

77 R KIELEN PERUSTEET vähennyslaskutoimituksia: >d4-7 [1] " " >d4+7 [1] " " Myös kahden päivämäärän välinen erotus on mahdollisia laskea: >d5<-as.date(c(" ")) >d5-d4 Time difference of 7 days Varsinainen päivämääräerojen laskemiseen tarkoitettu funktio on difftime(), ja monimutkaisemmissa operaatioissa kannattaa tutustua siihen tarkemmin. Päivämäärillä voidaan tehdä monia muitakin luvuille soveltuvia operaatioita. Niitä voidaan vertailla loogisilla operaatioilla: >d5>d4 [1] TRUE Tai niiden joukosta voidaan esimerkiksi etsiä viimeisin päiväys käyttäen komentoa max(), joka luvuille palauttaa suurimman luvun: >max(d4, d5) [1] " " Tekstivektoreiden käsittely Tekstimuotoisen aineiston käsittelyyn soveltuvia komentoja on runsaasti. Erityisesti laajempien tekstiaineistojen muokkaamiseen ja analysointiin on myös olemassa laajennuspaketteja, kuten erinomainen tm, johon kannattaa tutustua tarkemmin, jos analysoi tekstiaineistoa enemmänkin. Paketti tm löytyy CRAN:sta. Seuraavassa esitettävät komennot eivät kuitenkaan vaadi tm-paketin asennusta, vaan löytyvät R:n perusasennuksesta. Yksinkertaisen tekstimuotoisen vektorin, tässä txt, kaikki merkit voidaan muuttaa pieniksi tai isoiksi kirjaimiksi komennoilla tolower() ja toupper(): >txt<-c("jarno Tuimala") >tolower(txt) [1] "jarno tuimala" 69

78 PERUSTEET >toupper(txt) [1] "JARNO TUIMALA" Vektorin pituus merkkeinä, välilyönnit mukaan lukien, voidaan laskea komennolla nchar(): >nchar(txt) [1] 13 Mainittakoon tässä yhteydessä, että tekstin leveys graafeissa voidaan laskea komennolla strwidth(). Se on käyttökelpoinen erityisesti, kun halutaan varata graafiin riittävän suuri tila tietylle tekstille. Komento palauttaa tekstin leveyden esimerkiksi tuumina: >strwidth(txt, "inches") [1] Normaalisti tekstimuotoinen vektori tulostetaan lainausmerkkien kanssa: >txt [1] "Jarno Tuimala" Mutta komennolla noquote() lainausmerkit voidaan poistaa: >noquote(txt) [1] Jarno Tuimala Tekstivektori voidaan pilkkoa erilaisiin paloihin, esimerkiksi sanoiksi tai yksittäisiksi kirjaimiksi komennolla strsplit(), joka ottaa kaksi tärkeää argumenttia. Argumentti x määrittää pilkottavan tekstivektorin ja argumentti split puolestaan minkä merkkien kohdalta pilkkominen suoritetaan. Esimerkiksi komento: >strsplit(x=txt, split=" ") [[1]] [1] "Jarno" "Tuimala" pilkkoo tekstivektorin txt välilyöntien kohdalta eli tuloksena saadaan tekstivektorin sisältämät sanat. Sanat on talletettu listaan yhdeksi vektoriksi. Vastaavalla tavalla voidaan tekstivektori pilkkoa myös yksittäisiksi kirjaimiksi käyttäen argumentin split arvona tyhjää: >strsplit(txt, "") [[1]] [1] "J" "a" "r" "n" "o" " " "T" "u" "i" "m" "a" "l" "a" 70

79 R KIELEN PERUSTEET Yksittäisiksi kirjaimiksi pilkkominen voidaan tietysti yhdistää vaikka komentoon table(), jolloin saadaan laskettua kunkin kirjaimen lukumäärä tekstivektorissa: > table(strsplit(txt, "")) a i J l m n o r T u Tekstivektorista voidaan poimia osa käyttäen komentoa substr(). Sillä on kolme pakollista argumenttia, joista x kertoo käsiteltävän vektorin nimen, start sen kohdan vasemmalta oikealle laskettuna, josta poiminta aloitetaan ja stop, joka kertoo sen kohdan, johon poiminta lopetetaan. Esimerkiksi ensimmäiset viisi merkkiä (sana Jarno) voidaan poimia seuraavasti voidaan poimia seuraavasti: >substr(x=txt, start=1, stop=5) [1] "Jarno" Käytännön sovelluksi ajatellen voi olla mielenkiintoista ensin selvittää, missä kohtaa vektoria sijaitsee sanoja erottava välilyönti, ja sitten poimia tekstiä vain tähän välilyöntiin asti. Tällöin tarvitaan avuksi komento grep(), joka etsii tekstivektorista määritellyn tekstin. Sen avulla voidaan esimerkiksi tutkia, löytyykö tekstivektorista välilyöntiä lainkaan: >grep(pattern=" ", x=txt) [1] 1 Argumentti pattern määrittelee etsittävän tekstin ja argumentti x vektorin, josta argumentin pattern määrittelemää tekstiä etsitään. Jos etsittävä teksti löytyy, palauttaa grep() arvon 1 tai toteutustavasta riippuen etsittävän tekstin löytymiskohdan. Koska yllä olevassa esimerkissä etsimme välilyöntiä kokonaisesta vektorista, saimme tulokseksi, että välilyönti löytyy kyseisestä vektorista. Välilyönnin tarkan sijainnin selvittämiseksi vektori on kuitenkin ensin pilkottava yksittäisiksi kirjaimiksi: >txt2<-strsplit(txt, "") >loc<-grep(" ", txt2[[1]]) >loc [1] 6 Nyt komento grep() palauttaa välilyönnin sijainnin vektorissa. Tämä tieto on nyt tallennettu objektiin loc, jota voidaan käyttää apuna, kun tehdään poiminta komentoa substr() käyttäen: 71

80 PERUSTEET >substr(x=txt, start=1, stop=loc-1) [1] "Jarno" Poiminnassa on huomattava, että komento grep() palautti välilyönnin sijainnin, joka on kuudes merkki vasemmalta laskettuna. Niinpä välilyöntiä edeltävän sanan poimimiseksi on välilyönnin sijaintikohdasta vähennettävä yksi, mikä on yllä olevassa esimerkissä tehtykin. Tekstivektorin merkkejä voidaan korvata toisilla komennolla gsub(). Sillä on kolme pakollista argumenttia. Argumentti pattern määrittelee etsittävän tekstinpätkän, replacement millä etsittävä teksti korvataan, ja x mistä vektorista tekstiä etsitään ja korvataan. Esimerkiksi seuraava komento etsii vektorista txt välilyönnit, ja korvaa ne alaviivalla: >gsub(pattern=" ", replacement="_", x=txt) [1] "Jarno_Tuimala" Tällaiselle etsi-korvaa komennolla on tyypillisesti runsaasti käyttöä tekstiaineistojen käsittelyssä. Yhtenä esimerkkinä on pidemmän tekstin pilkkominen sanoiksi, kun tekstin joukossa on välimerkkejä. Luodaan ensin vektori virke: >virke<-c("kello löi jo viisi, lapset herätkää!") Jos kyseinen vektori nyt pilkottaisiin yksittäisiksi sanoiksi, olisi tuloksena sanoja, jotka sisältävät myös välimerkkejä: >strsplit(virke, " ") [[1]] [1] "Kello" "löi" "herätkää!" "jo" "viisi," "lapset" Välimerkit voidaan ensin poistaa vektorista virke komennolla gsub(), minkä jälkeen tulos näyttää siistimmältä: >virke<-gsub(",", "", virke) >virke<-gsub("!", "", virke) >virke [1] "Kello löi jo viisi lapset herätkää" > strsplit(virke, " ") [[1]] [1] "Kello" "löi" "jo" "viisi" "herätkää" "lapset" Komennolla paste() voidaan yhdistää tekstipätkiä toisiinsa. Jos meillä on kaksi vektoria v1 ja v2, joissa olevat sanan osat halutaan yhdistää, tämä 72

81 R KIELEN PERUSTEET voidaan tehdä seuraavasti. Luodaan ensin vektorit: >v1<-c("suden") >v2<-c("korento") Tämän jälkeen vektorit voidaan yhdistää komennolla paste() seuraavasti: >paste(v1, v2) [1] "suden korento" Jos tarkoituksena oli luoda yhdyssana, jäi sanojen väliin nyt ikävä ylimääräinen välilyönti. Se voidaan kuitenkin poistaa käyttämällä argumenttia sep, sillä tekstin pätkien väliin sijoitetaan argumentilla määritelty yhdysmerkki. Jos yhdysmerkkiä ei haluta käyttää lainkaan, se voidaan asettaa tyhjäksi, kuten seuraavassa: >paste(v1, v2, sep="") [1] "sudenkorento" Komennolla paste() voidaan myös luoda pidempiä tekstivektoreita, joissa on toistuvia osia. Luodaan ensin uusi vektori v3: >v3<-c("neidon", "ukon", "suden") Tämän jälkeen kaikki yhdyssanat, joiden jälkimmäisenä osana on korento voitaisiin luoda yhdistämäälä vektori v3 ja v2: > paste(v3, v2, sep="") [1] "neidonkorento" "ukonkorento" "sudenkorento" Joukko-opilliset operaatiot Seuraavassa esiteltävät joukko-opilliset operaatiot, kuten kahden vektorin vertaaminen yhteisten arvojen löytämiseksi, ovat käyttökelpoisia niin lukuarvoja kuin tekstiäkin sisältäville vektoreille. Luodaan esimerkkejä varten ensiksi kaksi vektoria, jotka sisältävät kirjaimia: >j1<-c("a", "b", "c", "d") >j2<-c("c", "d", "e", "f") Näin lyhyistä vektoreista on helppo huomata, että niille yhteisiä kirjaimia ovat c ja d. Tämä voidaan selvittää komennolla intersect(): 73

82 PERUSTEET >intersect(j1, j2) [1] "c" "d" Vektorien yhdistelmä taas näyttäisi sisältävän kaikki kirjaimet a:sta f:ään. Komento union() toteuttaa juuri tällaisen yhdistelmän: >union(j1, j2) [1] "a" "b" "c" "d" "e" "f" Komennolla setdiff() voidaan selvittää, mitkä arvot ovat komennossa ensimmäisenä argumenttina annetussa vektorissa, mutteivat toisena argumenttina annetussa vektorissa: >setdiff(j1, j2) [1] "a" "b" >setdiff(j2, j1) [1] "e" "f" Komento setequal() testaa, ovatko molempien vektorien sisältämät arvot samat. Jos ovat, komento palauttaa arvon TRUE, muutoin FALSE: >setequal(j1, j2) [1] FALSE Komento is.element() käy jokaisen ensimmäisenä argumenttina annetun vektorin arvon läpi, ja tutkii löytyykö se toisena argumenttina annetusta vektorista. Kullekin arvolle palautetaan joko TRUE tai FALSE riippuen siitä, löydettiinkö arvo vai ei: >is.element(j1, j2) [1] FALSE FALSE TRUE TRUE Komennoilla match(), pmatch() ja charmatch() voidaan etsiä vektorista hakua vastaavia osumia. Kukin niistä saa kaksi argumenttia. Ensimmäinen on etsittävä teksti tai lukuarvo ja toinen on sen vektorin nimi, josta tekstiä tai lukuarvoa etsitään. Esimerkiksi seuraavat komennot etsivät kirjaimen a kirjaimia sisältävästä vektorista j1: >match("b", j1) [1] 2 >pmatch("b", j1) [1] 2 >charmatch("b", j1) [1] 2 74

83 R KIELEN PERUSTEET Tässä tapauksessa kaikki antavat saman tuloksen. Erona on, että komento match() on varsin yleinen komento, joka toimii monessa tilanteessa, mutta se ei kuitenkaan kykene löytämään vain osittaisia tekstipätkiä. Tällöin tarvitaan komentoja pmatch() ja charmatch(). Esimerkiksi seuraavassa tilanteessa match() ei löydä sanalle Jar vastinetta vektorista txt, mutta komennot pmatch() ja charmatch() löytävät vastineen vektorin ensimmäisestä sanasta: >txt<-c("jarno", "Tuimala") >match("jar", txt) [1] NA >pmatch("jar", txt) [1] 1 > charmatch("jar", txt) [1] 1 Komentojen pmatch() ja charmatch() eroihin ei ole tarpeen tutustua tässä tarkemmin, mutta enne komentojen laajamittaisempaa soveltamista niiden ohjesivuihin, erityisesti esimerkkeihin kannataa perehtyä. Toistuvien arvojen käsittely Aineistossa esiintyy usein toistuvia arvoja. Niiden käsittely on toisinaan aineiston analyysiä ajatellen keskeistä, toisinaan toistuvia arvoja joudutaan käsittelemään muista syistä. Luodaan ensi esimerkkejä varten pieni aineisto, joka koostuu yhdestä vektorista v: > v<-c(1:5, 4:1) Vektorissa esiintyvät erilaiset arvot voidaan selvittää komennolla unique(). Se palauttaa kunkin arvon vain kertaalleen mainittuna. Esimerkiksi vektorissa v esiintyy vain lukuarvoja väliltä 1-5: >unique(v) [1] Toinen tärkeä toistuvien arvojen käsittelyyn soveltuva komento on duplicated(). Se palauttaa kullekin vektorin arvolle totuusarvo, siis joko TRUE tai FALSE sun mukaan, esintyykö sama arvo aineistossa yhden vain useampia kertoa. Jos sama arvo esiintyy useampia kertoja, sen ensimmäiselle esiintymiselle annetaan automaattisesti arvo FALSE, ja kaikille sen jälkeen tuleville saman arvon esiitymiselle arvo TRUE. Esimerkiksi vektorille v: 75

84 PERUSTEET >duplicated(v) [1] FALSE FALSE FALSE FALSE FALSE TRUE TRUE TRUE TRUE Komennolla rle() voidaan selvittää, kuinka monta kertaa kukin kahden arvon väli aineistossa esiintyy. Esimerkiksi väli ja ovat tässä tapauksessa eri asioita. Esimerkiksi vektorille v komento palauttaa: >rle(v) Run Length Encoding lengths: int [1:9] values : int [1:9] Toistuvia arvoja sisältävien rivien poistaminen taulukosta on eräs keskeisimpiä esiteltyjen komentojen käyttökohteita. Muodostetaan ensi taulukko dat: >dat<-data.frame(v=v, y=c(1:9)) >dat v y Jos nyt haluttaisiin poistaa kaikki rivit, joilla sarakkeen v arvo on toistunut, yhdistettäisiin komento duplicated() alaindeksiin. Lisäksi komennon duplicated() antamasta tuloksesta on otettava negaatio käyttämällä!operaattoria. Näin menetellään, koska ensimmäistä kertaa esiintyvät arvot, jotka haluamme säästää, saavat arvon FALSE, vaikka alaindeksillä poimintaa varten niiden pitäisi saada arvo TRUE. Muodostetaan ensin vektori ind, joka kertoo, onko arvo toistuva: >ind<-duplicated(dat$v) >ind [1] FALSE FALSE FALSE FALSE FALSE TRUE TRUE TRUE TRUE Tämän jälkeen poistetaan toistuvia arvoja sisältävät rivit taulukosta: 76

85 R KIELEN PERUSTEET >dat[!ind,] v y Jos alaindeksin sisältä jättää vektoria ind edeltävän huutomerkin vahingossa pois, saa väärän tuloksen, joten hommassa kannattaa olla tarkkana: > dat[ind,] v y Jos toistuvat arvot muodostavat jonkinlaisia ryhmiä esimerkiksi siten, että kustakin tiettyyn kokeeseen osallistuneesta koehenkilöstä on otettu useita mittauksia, voidaan mitauksista myös laskea vaikkapa summa tai keskiarvo kullekin koehenkilölle. Komentoa aggregate() voidaan käyttää tarkoitukseen. Seuraavalla komennolla voitaisiin laskea datakehikon dat muuttujalle y keskiarvo kullekin muutujan v määrittelemälle ryhmälle. Argumentti x määrittelee sen vektorin, josta keskiarvo lasketaan, argumentti by puolestaan määrittelee ryhmittelymuttujan ja argumentti FUN sen funktion, jota laskennassa käytetään. Lopputuloksena on datakehikko, jossa on yhtä monta riviä kuin aineistossa oli ryhmiä. Sarakkeessa x on kunkin ryhmän keskiarvo. Sarake Group.1 puolestaan kertoo mistä ryhmästä on kullakin rivillä kyse. > aggregate(x=dat$y, by=list(dat$v), FUN=mean) Group.1 x Komennolla aggregate() voidaan laskea keskiarvon kaltaisia yhteenvetotietoja käyttäen yhtäaikaa myös useampia luokittelemuuttujia. Luodaan esimerkkiä varten datakehikkoa, jossa on kaksi luokittelevaa muuttujaa, x ja y. Muuttuja z sisältää itse mittaustulokset, joista halutaan laskea keskiarvon kussakin ryhmässä: 77

86 PERUSTEET >dat2<-data.frame(x=rep(1:2, 4), y=rep(1:4, 2), z=c(1:8)) >dat2 x y z Tämän jälkeen ryhmäkohtaiset keskiarvot voidaan laskea antamalla muuttujat x ja y komennon aggregate() argumentissa by: > aggregate(x=dat2$z, by=list(dat2$x, dat2$y), FUN=mean) Group.1 Group.2 x Nyt tuloksessa on kaksi Group-saraketta, jotka kertovat ryhmittelyn, ja ryhmäyhdistelmien keskiarvot löytyvät jälleen sarakkeesta x. Lisäpaketin doby komento summaryby() tarjoaa vielä komentoa aggregate() monipuolisemmat mahdollisuudet luoda erilaisia yhteenvetoja, sillä siinä voidaan laskea yhtäaikaa useampia ryhmäkohtaisia arvoja, kuten keskiarvo, keskihajonta ja summa. Nämä voitaisiin laskea datakehikolle dat seuraavasti: >library(doby) >summaryby(z~x+y, data=dat2, FUN=c(mean, sd, sum)) x y z.mean z.sd z.sum Komennolla library(doby) on ensin otettu lisäpaketti käyttöön, sillä muutoin komento ei toimi. Itse komento summaryby() koostuu kolmesta argumentista. Ensimmäisenä on niin sanottu kaavamuotoinen esitys siitä mitä halutaan laskea. Samaa muotoa käytetään myös tilastollisten analyysien yhteydessä, ja sen rakenne selitetään niden yhteydessä tarkemmin. Kissanhäntämerkin (~) vasemmalla puolella on sen sarakkeen nimi, jossa yhteenvetotiedoiksi muodostettavan muuttujan arvot sijaitsevat. Kissanhäntämerkin oikealla puolella on lueteltu, plus (+) 78

87 R KIELEN PERUSTEET -merkein yhdistettynä ne luokittelumuuttujat, joiden suhteen yhteenvetotiedot halutaan laskea. Argumentti data kertoo sen datakehikon nimen, josta kaavamuotoisessa esityksessä mainitut sarakkeet löytyvät. Lopuksi argumentti FUN luettelee vektorissa niiden komentojen nimet, joita laskennassa halutaan käyttää. Tulos on datakehikko, joka tässä tapauksessa koostuu muuttujista x ja y, jotka kertovat luokan, jolle yhteenvetotieto on laskettu. Itse yhteenvetotiedot löytyvät z-alkuisista sarakkeista. Esimerkiksi sarakkeessa z.mean on ryhmäkohtaisia keskiarvoja, ja sarakkeesta z.sum löytyy ryhmäkohtaisia summia. Taulukkomuotoisen aineiston lukeminen tiedostosta Osiossa R alkeet on kuvattu muutamia tapoja tuoda aineistoa R:ään. Alkeissa esitetyt lähestymistavat soveltuvat erityisesti taulukomuotoisen aineiston lukemiseen, mikä lieneekin yleisin muoto, erityisesti tilastollisia lukuarvoja sisältävän aineiston analyysejä ajatellen. Seuraavassa perehdytään hieman tarkemmin erilaisten aineistojen lukemiseen, ja erityisesti kerrataan alkeissa esitellyn komennon read.table() toiminta. Useinmiten tilastollinen aineisto on tallennettu muotoon, jossa kullakin rivillä on yhtä monta havaintoa ja kussakin sarakkeessa yhtä monta riviä. Toisin sanoen aineisto on ikään kuin suorakaiteen muotoinen. Tällaisia tiedostoja on helppo lukea sisään komennolla read.table(). Seuraavassa käytetään esimerkkinä kirjan kotisivuilta löytyvää tiedostoa rairuoho.txt. Se on myös esitetty kokonaisuudessaan seuraavan sivun kuvassa. Aineisto koostuu 13 muuttujasta (sarakkeesta), joista kustakin on 48 havaintoa. Ensimmäisellä rivillä on kunkin sarakkeen otsikko, mutta riveille ei ole annettu otsikoita. Sarakkeiden erottimena on käytetty tabulaattoria, minkä voi havaita tarkastelemalla tekstitiedostoa jossakin tekstieditorissa, kuten Windows:in Notepad:ssä. Desimaalierottimena on käytetty pistettä. 79

88 PERUSTEET Edellä luetellut tiedot riittävät, jotta aineisto saadaan luettua oikein komennolla read.table(). Tässä tapauksessa aineiston lukemiseen riittää, kun luettaessa käytetään kolmea argumenttia. Luetaan aineisto tiedostosta rairuoho.txt datakehikoksi dat siten, että kullakin sarakkeella on otsikko (argumentti header) ja että sarake-erottimena on tabulaattori (argumentti sep): >dat<-read.table("rairuoho.txt", header=t, sep="\t") Esitelty komento riittää sellaisenaan useimpien taulukkomuotoisten tiedostojen lukemiseen. Jos kullakin rivillä on oma nimi, kuten tiedoston laugesen4.txt tapauksessa: 80

89 R KIELEN PERUSTEET voidaan rivien nimet lukea suoraan datakehikon rivinimiksi lisäämällä komentoon read.table() argumentin row.names, joka kertoo monennessako tiedoston sarakkeessa rivien nimet sijaitsevat. Esimerkiksi tiedostossa laugesen4.txt rivien nimet ovat ensimmäisessä sarakkeessa, joten aineisto voidaan lukea komennolla: >dat<-read.table("laugesen4.txt", row.names=1) header=t, sep="\t", Kuten R alkeet -osiossa on tarkemmin selitetty, voi komennolla read.table() lukea erilaisia taulukkomuotoisia tiedostoja siitä riippumatta, mikä niiden sarake- tai desimaalierotin on. Tällöin komennon argumentit on vain muutettava sopiviksi. Se ei kuitenkaan sovellu sellaisten taulukkomuotoisten aineistojen lukemiseen, joissa ei ole selkeää sarake-erotinta, vaan sarakkeet ovat muotoiltu jo valmiiksi pystyriveihin. Esimerkki tällaisesta aineistosta löytyy tiedostosta läänit.txt: Etelä-Suomen lääni 41.3 % Länsi-Suomen lääni 35.3 % Itä-Suomen lääni 10.7 % Oulun lääni 8.8 % Lapin lääni 3.5 % Ahvenanmaa 0.5 % Tällaisen tiedoston lukemiseksi tarvitaan komentoa read.fwf(). Jos aineiston yrittää tuoda komennolla read.table(), on tuloksena väärin muotoiltu aineisto, joka koostuu neljästä sarakkeesta V1-V4: >dat<-read.table("läänit.txt") 81

90 PERUSTEET >dat V1 V2 V3 V4 1 Etelä-Suomen lääni 41.3 % 2 Länsi-Suomen lääni 35.3 % 3 Itä-Suomen lääni 10.7 % 4 Oulun lääni 8.8 % 5 Lapin lääni 3.5 % 6 Ahvenanmaa 0.5 % Warning message: In scan(file, what, nmax, sep, dec, quote, skip, nlines, na.strings, : number of items read is not a multiple of the number of columns Komennolla read.fwf() tiedoston lukeminen oikein onnistuu. Luettavan tiedoston nimen lisäksi komennolle on annettava argumentti widths, joka ilmoittaa kunkin luettavan kentän leveyden merkkeinä. Tässä tapauksessa läänin nimi on viimeisen välilyönnin kanssa pituudeltaan 19 merkkiä, ja läänin väkilukua kuvaava prosenttiosuus koko väestöstä on pituudeltaan neljä merkkiä: >dat<-read.fwf("läänit.txt", widths=c(19, 4)) >dat V1 V2 1 Etelä-Suomen lääni Länsi-Suomen lääni Itä-Suomen lääni Oulun lääni Lapin lääni Ahvenanmaa 0.5 Toisinaan tiedoston alussa on joitakin rivejä komentteja tai muita selityksiä, joita ei haluta lukea aineistoon mukaan. Esimerkki tällaisesta muutoin taulukkomuotoisesta tiedostosta on burtin.txt. Sen kaksi ensimmäistä riviä ovat selite ja sitä seuraava tyhjä rivi, jota seuraavat sarakkeiden otsikot. Jos seliterivien yli ei hypätä, menee aineiston lukeminen sekaisin, ja voi päättyä virheilmoitukseen, kuten tässä: > read.table("burtin.txt", sep="\t", header=t) Error in read.table("burtin.txt", sep = "\t", header = T) : more columns than column names Niinpä aineistoa luettaessa onkin komennolle read.table() annettava yksi lisäargumentti skip, joka määrittää niiden tiedoston alussa olevien rivien lukumäärä, joiden yli halutaan hypätä: >dat<-read.table("burtin.txt", sep="\t", header=t, skip=2) 82

91 R KIELEN PERUSTEET Jos seliterivit alkavat kommenttimerkillä, joka on oletusarvoisesti #, hypätään niiden yli automaattisesti. Esimerkki tällaisesta tiedostosta on haircolor.txt. Sen lukeminen onnistuu siis tavanomaisesti komennolla: >dat<-read.table("haircolor.txt", sep="\t", header=t) Tekstimuotoisen aineiston lukeminen Seuraavassa esiteltäviä komentoja voidaan käyttää myös taulukkomuotoisten aineistojen lukemiseen, mutta ne soveltuvat erityisen hyvin pelkästä tekstistä koostuvien aineistojen käsittelyyn. Tekstiä sisältävästä tiedostosta, kuten seuraavissa esimerkeissä käytettävästä tiedostosta esipuhe.txt, voidaan lukea tietty määrä merkkejä komennolla readchar(). Se vaatii kaksi argumenttia, luettavan tiedoston nimen ja luettavien merkkien määrän. Esimerkiksi tiedostosta esipuhe.txt voitaisiin lukea kymmenen ensimmäistä merkkiä komennolla: >dat<-readchar("esipuhe.txt", 10) >dat [1] "Tavoitteet" Tuloksena on tekstimuotoinen vektori. Tekstitiedosto voidaan lukea myös rivi kerrallaan komennolla readlines(). Oletusarvoisesti luetaan kaikki tiedoston rivit, mutta argumentilla n voidaan asettaa luettavien rivien lukumäärä. Seuraavalla komennolla voidaan lukea tiedoston esipuhe.txt kaikki rivit vektoriin dat: >dat<-readlines("esipuhe.txt") Tämän jälkeen yksittäiset rivit voidaan erottaa vektorista tavanomaisesti alaindeksi käyttäen. Ensimmäinen rivi saadaan siis erotettua muista komennolla: >dat[1] [1] "Tavoitteet" Edellisiä komentoja joustavampi, mutta myös hieman vaikeammin käytettävä on scan(), jolla voidaan lukea hyvin monipuolisesti miltei minkälaisia tiedostoja vain, mutta luetun aineiston jatkokäsittely sopivaan muotoon onkin sitten usein vaikeampaa. Komennolle on annettava ainakin kaksi argumenttia, luettavan tiedoston nimi ja missä muodossa aineisto luetaan. Esimerkiksi tiedosto esipuhe.txt voidaan lukea puhtaana tekstinä seuraavasti: 83

92 PERUSTEET >dat<-scan("esipuhe.txt", "raw") tai >dat<-scan("esipuhe.txt", "character") Kumpikin komento tuottaa saman tuloksen eli yksittäisiksi sanoiksi pilkotun tekstivektorin. Jos aineisto on laaja, voi olla helpointa tarkastella vain sen alku- tai loppupäätä. Nämä saadaan tulostettua ruudulle komennoilla head() ja tail(). Esimerkiksi edellä luetun tekstivektorin dat sisältö näyttää seuraavalta: > head(dat) [1] "Tavoitteet" "Tämä" [5] "R-kielen" "perusteet" "kirja" > tail(dat) [1] "avulla" "voidaan" [4] "tilastografiikkaa" "ja" "esittelee" "tuottaa" "-analyysejä." Muiden ohjelmien datatiedostojen lukeminen R osaa lukea monien muiden tilasto-ohjelmistojen, kuten SPSS ja SAS tuottamia tiedostoja suoraan. Tarvittavat komennot ovat saatavilla laajennuspaketissa foreign. SPSS-tiedostojen lukeminen on yksinkertaista. Tiedosto burtin.sav sisältää Burtinin antibioottiaineiston SPSS-muodossa. Se voidaan lukea suoraan R:n datakehikoksi komennolla >dat<-read.spss("burtin.sav", to.data.frame=true) On tärkeää muistaa käyttää argumentin to.data.frame arvona TRUE, sillä muutoin aineisto luetaan listaksi, minkä käsittely on hieman datakehikkoa työläämpää. SAS-tiedostojen lukeminen ei onnistu, elleivät ne ole XPORT-muodossa. XPORT-muotoisten tiedostojen lukeminen onnistuu komennolla read.xport(). Harva kuitenkaan tallentaa aineistoaan tässä muodossa, vaan SAS:n binaarimuodossa, jolloin tiedoston päättenä on sas7bdat. Binaarimuotoisten tiedostojen lukemiseen tarvitaan joko SAS-asennus tai tiedosto pitää muuttaa tekstimuotoon jollakin sopivalla apuohjelmalla, kuten SAS Universal Viewer. Tekstimuotoinen tiedosto voidaan sitten lukea normaalisti komennolla read.table(). 84

93 R KIELEN PERUSTEET Aineiston kirjoittaminen levylle Yksinkertaisin tapa kirjoittaa aineisto tai tuloksia tiedostoon on käyttää komentoa sink(). Se tallentaa kaiken ruudulle kirjoitetun tai tulostetun tekstin sellaisenaan määriteltyyn tiedostoon. Luetaan esimerkkiä varten ensin Burtinin antibioottiaineisto objektiin dat: >dat<-read.table("burtin.txt", sep="\t", header=t, skip=2) Aineisto voidaan nyt kirjoittaa vaikkapa tiedostoon seuraavasti. Ensin avataan tiedosto sink-koe.txt komennolla: sink-koe.txt >sink("sink-koe.txt") Tämän jälkeen tulostetaan aineisto tiedostoon kirjoittamalla sen nimi komentoriville: >dat ja lopuksi suljetaan yhteys tiedostoon komennolla >sink() Jos tarkastelee tiedostoa sink-koe.txt jossakin tekstieditorissa, huomaa varmasti, että se on nyt fixed width-muodossa, eikä sen lukeminen takaisin R:ään ole enää välttämättä yksinkertaista. Komento sink() soveltuukin parhaiten erilaisten analyysien tulosten kirjoittamiseen tiedostoihin, muttei aineistojen kirjoittamiseen. Taulukkomuotoinen aineisto voidaan kirjoittaa tiedostoon komennolla write.table(). Objektin dat kirjoittaminen levylle tapahtuu komennolla: >write.table(dat, "burtin-koe.txt", row.names=true, col.names=true) sep="\t", quote=f, Komennossa on kuusi argumenttia. Ensimmäinen on kirjoitettavan objektin nimi (dat), ja seuraava on sen tiedoston nimi, johon halutaan kirjoittaa (burtin-koe.txt). Argumentti sep määrittelee sarake-erottimen (tässä tabulaattori), ja argumentti quote määrittelee sijoitetaanko tekstikentät lainausmerkkeihin (tässä: ei käytetä lainausmerkkejä). Argumentit row.names ja col.names määrittävät, kirjoitetaanko tiedostoon objektissa mahdollisesti olevat rivi- ja sarakenimet (tässä: kirjoitetaan). Komennoilla write() ja cat() on mahdollista kirjoittaa tiedostoon varsin vapaasti kaikenlaista. Komento write() itse asiassa kutsuu 85

94 PERUSTEET taustalla komentoa cat(), joten niitä voidaan hyvin käyttää yhdessä. Komennolle write() on annettava kaksi argumenttia: kirjoitetta objekti ja sen tiedoston nimi, johon objekti kirjoitetaan. Esimerkiksi seuraava komento kirjoittaa tiedostoon write-koe.txt tekstin Terve Maailma!: >write("terve Maailma!", "write-koe.txt") Jos jo olevassa olevaan tiedostoon halutaan lisätä tekstiä, pitää komentoon write() lisätä argumentti append=true, jotta tiedostoa ei ylikirjoiteta, vaan kirjoitettava objekti lisätään siihen viimeiseksi. Esimerkiksi tiedostoon write-koe.txt voidaan lisätä rivi, jolla teksti "Hyvää huomenta Suomi!" seuraavalla komennolla: >write("hyvää huomenta Suomi!", "write-koe.txt", append=t) Tämän jälkeen tiedosto write-koe.txt sisältää siis seuraavat rivit: Terve Maailma! Hyvää huomenta Suomi! Komentojen write() ja paste() yhdisteleminen sopivalla tavalla antaa laajat mahdollisuudet erilaisten tekstimuotoisten aineistojen kirjoittamiseen levylle. Tiedosto- ja hakemisto-operaatiot Ennen työskentelyn aloittamista työhakemisto on muutettava osoittamaan sinne, missä analyyseissä käytettävät aineistot sijaitsevat, sillä tämä helpottaa työskentelyä. Tämän kirjan osiossa R alkeet on esitelty työhakemiston vaihtaminen graafista käyttöliittymää käyttäen. Sama toimenpide voidaan kuitenkin tehdä myös komentoriviltä komennolla setwd(). Esimerkiksi seuraava komento muuttaa työhakemiston Ckiintolevyn users-hakemistoon: >setwd("c:/users") Työhakemiston sijainti voidaan tarkistaa komennolla >getwd() [1] "C:/users" Työhakemistossa olevat tiedostot voidaan luetella komennolla 86

95 R KIELEN PERUSTEET >dir() [1] "Book1.xlsx" [4] "esipuhe.txt" [7] "läänit.txt" "burtin.sav" "burtin.txt" "haircolor.txt" "laugesen4.txt" "rairuoho.txt" Komento dir() palauttaa tavanomaisen tekstivektorin. Jos halutaan luetella esimerkiksi vain kaikki hakemistossa sijaitsevat SPSS-tiedostot, voidaan komennossa dir() käyttää argumenttia pattern. Koska kaikki SPSS-tiedostot päättyvät päätteeseen.sav, voidaan ne luetella komennolla: >dir(pattern=".sav") [1] "burtin.sav" Komennolla file.info() saadaan tiedostoista selville perusinformaatiota: >file.info("burtin.sav") size isdir mode mtime burtin.sav 1635 FALSE :26:01 ctime burtin.sav :26:01 atime exe burtin.sav :26:01 no Size kertoo tiedoston koon tavuina, isdir onko tiedosto hakemisto, mode kertoo luku- ja kirjoitusoikeudet ja exe onko tiedosto ajettava ohjelma. Viimeisimmän tallennusajan kertoo mtime, luomisajan ctime, and viimeisimmän lukuajankohdan atime. Tarvittaessa tiedoston luku- ja kirjoitusoikeuksia voi muokata komennolla Sys.chmod(), mutta asiaan ei perehdytä tässä sen tarkemmin. Uusi hakemisto voidaan luoda komennolla dir.create(). Esimerkiksi nykyiseen työhakemistoon voidaan luoda uusi hakemisto testit komennolla: >dir.create("testit") Hakemisto (tai tiedosto) voidaan tuhota komennolla unlink(). Edellä luotu hakemisto testit voidaan siis poistaa nykyisestä työhakemistosta komennolla: >unlink("testit", recursive=true) Argumentti recursive määrittelee, että kaikki hakemiston alla olevat hakemistot ja tiedostot on myös poistettava. Uusi tyhjä tiedosto voidaan luoda komennolla file.create(). 87

96 PERUSTEET Esimerkiksi tiedosto nimeltä testi1.txt luodaan nykyiseen työhakemistoon komennolla: >file.create("testi1.txt") Tiedoston olemassaoloa voidaan tutkia komennolla file.exists(), joka palauttaa arvon TRUE, jos tiedosto on olemassa, muutoin se palauttaa arvon FALSE: >file.exists("testi1.txt") [1] TRUE Tiedosto voidaan nimetä uudelleen komennolla file.rename(). Esimerkiksi tiedosto testi1.txt voidaan nimetä uudelleen nimellä poista.txt seuraavasti: >file.rename("testi1.txt", "poista.txt") Tiedoston kopiointi toiselle nimelle tapahtuu komennolla file.copy(). Esimerkiksi tiedosto poista.txt voidaan kopioida tiedostoksi poista2.txt: >file.copy("poista.txt", "poista2.txt") R osaa näyttää tekstitiedostoja esikatseluna ilman että niitä on ennen sitä erityisesti ladattu. Tämä tapahtuu komennolla file.show(). Esimerkiksi Burtinin aineisto tiedostosta burtin.txt voidaan esikatsella seuraavasti: >file.show("burtin.txt") Tämä avaa uuden ikkunan, jossa tiedoston sisältö näytetään. Pakattu tiedosto voidaan avata esimerkiksi komennolla unzip(), jos pakatu tiedosto on ZIP-muodossa. Esimerkiksi työhakemistossa oleva tiedosto rairuoho.zip voidaan purkaa komennolla >unzip("rairuoho.zip") Tiedostojen lataaminen Internetistä Mikä tahansa tiedosto voidaan ladata Internetistä komennolla download.file(), kunhan tiedoston Internet-osoite on tiedossa. Esimerkiksi kirjoittamani englanninkielisen Bioconductor-oppaan voi ladata työhakemistoon komennolla: 88

97 R KIELEN PERUSTEET >download.file("http://koti.mbnet.fi/tuimala/oppaat/r2.pdf", destfile="r2.pdf", mode="wb") Ensimmäinen argumentti kertoo ladattavan tiedoston sijainnin eli sen Internet-osoitteen. Argumentti destfile määrittelee tallennettavan tiedoston nimen ja argumentti mode miten tiedosto siirretään Internetistä levylle (tässä: binaarimuodossa). Tiedostoja voidaan siitää pelkkänä tekstinä, mikä soveltuu lähinnä puhtasti tekstiä sisältäville tiedostoille tai binaarimuodossa, mitä tulisi käyttää miltei kaikille muille tiedostotyypeille. Tekstimuotoinen siirtotapa on oletuksena, mutta esimerkiksi PDF-tiedostot eivät aukea oikein, jos ne siirretään tesktimuodossa. Toisinaan aineisto sijaitsee tiedostossa, joka pitää ladata Internetistä. Tiedosto voidaan tietysti ladata ensin selaimella paikalliselle koneelle, ja sitten lukea sieltä, mutta komento read.table() osaa lukea tiedostoja myös Internetistä. Esimerkiksi tiedosto burtin.txt voidaan hakea tämän kirjan kotisivuilta komennolla: >read.table("http://koti.mbnet.fi/tuimala/oppaat/r/data/burti n.txt", header=t, sep="\t", skip=2) Kaikki komennot eivät kuitenkaan ymmärrä Internet-osoitteita. Tällainen on esimerkiksi read.spss(). Helpointa lienee ladata tarvittava tiedosto levylle selaimella tai komennolla download.file() ja sitten lukea se sisään normaalisti. Tietokantayhteydet R osaa lukea aineistoa monista erilaisista tietokannoista. Joillekin tietokannoille on oma laajennuspaketti, jonka avulla tietokannan käsittely onnistuu. Tällaisia ovat RMySQL, RPostgreSQL, ROracle ja RSQLite. Lisäksi tietokantayhteyksien käyttö vaatii yleensä vastaavan tietokannan paikallisen asennuksen sekä laajennuspaketin DBI. Poikkeuksena on RSQLite, joka sisältää sekä itse tietokantamoottorin, että komennot, joilla tietokantaa voidaan käsitellä. Lisäksi tietokantojen käsittelyyn voidaan käyttää ODBC-yhteyttä, joka vaatii RODBC-laajennuspaketin asentamista. Windows-järjetelmissä RODBC-paketin avulla voidaan aineistoa lukea myös esimerkiksi Access-tietokannoista ja Excel-lomakkeista. Seuraavassa käytetään esimerkkinä lähinnä RSQLite-tietokantaa, sillä sen käyttö on mahdollista siellä missä R:nkin, silä se ei vaadi erillistä tietokantamoottorin asennusta. Lisäksi tutustutaan aineiston lukemiseen Excel-tiedostoista. Vaikka esimerkeissä käytetään SQL-kieltä tietokantakyselyiden tekemiseen, ei SQL:n perusteita käsitellä kovin 89

98 PERUSTEET tarkasti, vaan ne on tarvittaessa omaksuttava jostakin toisesta oppikirjasta. RSQLite Ensimmäiseksi on ladattavat laajennuspaketti RSQLite muistiin: >library(rsqlite) Uusi SQLite-tietokanta voidaan perustaa Määritetään ensin tietokanta-ajuriksi SQLite: avaamalla siihen yhteys. >drv <- dbdriver("sqlite") Määritellään sitten tietokannan nimi: >tfile<-"antibiotics" Ja avataan lopuksi yhteys tietokantaan: >con <- dbconnect(drv, dbname = tfile) Näin luotuun tietokantaan voidaan perustaa uusi taulu esimerkiksi kirjoittamalla tauluksi jokin R:n muistissa oleva aineisto. Luetaan ensin Burtinin antibioottiaineisto objektiin dat, ja kirjoitetaan se sen jälkeen tietokantaan tauluksi burtin komennolla dbwritetable(): >dat<-read.table("burtin.txt", sep="\t", header=t, skip=2) >dbwritetable(con, "burtin", dat) Komento dbwritetable() saa kolme argumentti. Ensimmäinen on avoimen yhteyden nimi, toinen kertoo luotavan taulun nimen ja viimeinen kertoo tauluksi kirjoitettavan objektin nimen. Yleisesti ottaen komentoa voidaan käyttää kirjoittamaan tauluksi vain taulukkomuotoisia objekteja. Tietokantayhteys voidaan tämän jälkeen sulkea komennolla >dbdisconnect(con) Jos tietokannasta halutaan myöhemmin lukea jotakin, on hyödyllistä voida tarkastella sen ominaisuuksia. Esimerkiksi kaikki tietokannan antibiotics taulut voidaan listata seuraavasti. Ensin avataan tavanomaisesti yhteys tietokantaan: 90

99 R KIELEN PERUSTEET > drv <- dbdriver("sqlite") > con <- dbconnect(drv, dbname = tfile) Ja tämän jälkeen luetellaan kaikki sen sisältämät taulut: > dblisttables(con) [1] "burtin" Tämän jälkeen voidaan selvittää taulun burtin rakenne vilkaisemalla sen ensimmäisiä rivejä. Tämä vaatii yksinkertaisen haun tekemistä. Ensin tehdään haku, jossa valitaan kaikki taulun burtin sarakkeet ja rivit ja talletetaan haku objektiin res: >res<-dbsendquery(con, "SELECT * FROM burtin") Komento dbsendquery() saa tässä kaksi argumenttia. Ensimmäinen on avoimen yhteyden nimi ja lainausmerkeissä oleva jälkimmäinen argumentti sisältää tietokannasta tehtävän SQL-kielellä kirjoitettavan haun. Tämän jälkeen voidaan hakea taulun viisin ensimmäistä (ylintä) riviä komennolla: >fetch(res, n=5) row_names Penicillin Streptomycin Neomycin Gram 1 Aerobacter aerogenes negative 2 Brucella abortus negative 3 Brucella anthracis positive 4 Diplococcus pneumoniae positive 5 Escherichia coli negative Komennon fetch() argumentti n kertoo haettavien rivien lukumäärän. Taulu burtin koostuu siis viidestä sarakkeesta. Koko taulu voidaan lukea R:ään komennoilla: >res<-dbsendquery(con, "SELECT * FROM burtin") >dat2<-fetch(res) Komento dbsendquery() pitää antaa joka kerran erikseen, sillä komento fetch() sulkee haun, mikä tarkoittaa sitä, ettei objekti res enää sisälläkään tehtyä hakua ellei komento dbsendquery() toisteta. Toinen, käytännössä vastaava, tapa hakea burtin-taulusta aineistoa on käyttäen komentoa dbgetquery(): >dbgetquery(con, "SELECT * FROM burtin") Yllä tehdyissä kahdessa SQL-kyselyssä on haettu koko burtin-taulun sisältö. SQL-haku koostuu R-kielen tapaan komennoista ja niiden argumenteista. Kyselyssä SELECT * FROM burtin komennon select 91

100 PERUSTEET jälkeen kerrotaan mitkä sarakkeet taulusta haetaan. Tässä sarakkeita on merkitty tähti-merkillä (*), mikä tarkoittaa sitä, että haetaan kaikki taulusta löytyvät sarakkeet. Komennon FROM jälkeen kerrotaan sen taulun nimi, josta sarakkeet haetaan. Edellä on siis toisin sanoen haettu kaikki sarakkeet taulusta burtin. Hakua voidaan tarkentaa lisäämällä hakuun SQL-komento WHERE. Se vastaa käsitteellisesti R:n alaindeksiä, ja rajoittaa haun kattamaan vain tietyt rivit. Esimerkiksi kaikki rivit, joilla sarakkeessa Gram on arvo negative, saadaan haettua komennolla: >dbgetquery(con, "SELECT * FROM burtin WHERE Gram = 'negative '") row_names Penicillin Streptomycin Neomycin Gram 1 Aerobacter aerogenes 2 Brucella abortus 3 Escherichia coli 4 Klebsiella pneumoniae 5 Mycobacterium tuberculosis 6 Proteus vulgaris 7 Pseudomonas aeruginosa 8 Salmonella (Eberthella) typhosa 9 Salmonella schottmuelleri negative negative negative negative negative negative negative negative negative Koska itse SQL-kysely on kaksinkertaisten lainausmerkkien sisällä, tulee sarakkeen nimi antaa yksinkertaisten lainausmerkkien sisällä, sillä muutoin R menee sekaisin siitä, mikä kuuluu SQL-kieliseen hakuun ja mikä R-komentoon. R:n komentoa aggregate() vastaavia ryhmäkohtaisia yhteenvetotietoja voidaan laskea esimerkiksi SQL:n komennolla GROUP BY. Seuraava kysely laskee Gram-negatiivisten ja Gram-positiivisten ryhmille erikseen kunkin muuttujan arvon: >dbgetquery(con, "SELECT * FROM burtin GROUP BY Gram") row_names Penicillin Streptomycin Neomycin Gram 1 Salmonella schottmuelleri 1e negative 2 Streptococcus viridans 5e positive RODBC Laajennuspaketin RODBC avulla voidaan Windows-järjestelmissä lukea aineistoa suoraan esimerkiksi Excel-tiedostoista. Seuraavassa ladataan Burtinin antibioottiaineisto tiedostosta burtin.xls, mikä on Excel muodossa oleva tiedosto. Aluksi ladataan laajennuspaketti RODBC: >library(rodbc) 92

101 R KIELEN PERUSTEET Tämän jälkeen tiedoston lukemiseen odbcconnectexcel() ja sqlfetch(): käytetään >dat<-sqlfetch(odbcconnectexcel("burtin.xls"), "burtin", na.strings = "NA", as.is = T) komentoja sqtable = Komennon odbcconnectexcel() argumentti kertoo sen tiedoston nimen, josta aineisto luetaan. Tässä tiedosto on siis burtin.xls. Tiedostossa on yksi ainoa välilehti, jonka nimi on burtin, ja tämä annetaan komennon sqlfetch() argumentiksi sqtable. Argumentit na.strings ja as.is määrittelevät, että puuttuvien arvojen koodina on merkkijono NA, ja että aineisto luetaan siinä muodossa kuin se Excel-tiedostossa on eli merkkijonot merkkijonoina ja numerot numeroina. Tuloksena on datakehikko-muotoinen objekti nimeltä dat. Uudempien Excel-tiedostomuotojen, kuten Excel 2007, lukeminen ei suoraan onnistu edellä kuvatulla tavalla. Niiden lukemiseksi on ensin avattava yhteys tiedostoon. Tämä onnistuu helpoimmin interaktiivisesti. Seuraava komento avaa alla kuvatun valintaikkunan: >ch<-odbcconnect("") Valintaikkunan välilehdeltä Machine Data Source valitaan Data Source 93

102 PERUSTEET Name-kentästä vaihtoehto Excel files. Tämän jälkeen OK-napin painaminen avaa tiedostojen selailuun tarkoitetun valintaikkunan: Valintaikkunan kautta valitaan luettava tiedosto, joka tässä tapauksessa on Excel 2007-muodossa oleva Burtinin antibioottiaineiston sisältävä tiedosto burtin.xlsx. Vaihtoehtoisesti saman asian voi tehdä komentoriviltä komennolla odbcdriverconnect(): >ch<-odbcdriverconnect("driver=microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb); DBQ=C:/Users/Jarno Tuimala/Desktop/R-data/burtin.xlsx; ReadOnly=False") Komennossa määritellään lainausmerkeissä käytettävä Microsoftin valmistama ajuri, jonka pitää olla juuri yllä mainitulla tavalla kirjoitettu, luettavan tiedoston sijainti ja tiedoton nimi, sekä millä tavalla yhteys avataan: argumentti ReadOnly saa tässä arvon FALSE, joten tiedostoon on myös mahdollista kirjoittaa. Tiedoston sisältöä voidaan tämän jälkeen tarkastella komennolla: >sqltables(ch) TABLE_CAT TABLE_SCHEM 1 C:\\Users\\Jarno Tuimala\\Desktop\\R-data\\burtin.xlsx <NA> TABLE_NAME TABLE_TYPE REMARKS burtin$ SYSTEM TABLE <NA> Komennon tulosteesta voidaan päätellä, että tiedostossa olevan välilehden nimi on burtin. Tämä tieto nimittäin löytyy sarakkeesta TABLE_NAME, mutta aineiston lukemista varten siinä mainitun nimen perästä on poistettava dollari ($) -merkki. Tämän jälkeen koko aineisto voidaan lukea 94

103 R KIELEN PERUSTEET datakehikoksi, vaikkapa nimelle dat komennolla: >dat<-sqlfetch(ch, "burtin") Kun yhteys Excel-tiedostoon on luotu, voidaan aineistosta hakea vain osajoukko rajoittamalla luettavaa aineistoa SQL-kyselyllä. Tällöin käytetään komennon sqlfetch() sijaan komentoa sqlquery(). Kun komennolla sqlfetch() luettiin kokonainen välilehti, käytettiin aineiston lukemisessa välilehden nimeä ilman $-merkkiä. Komennon sqlquery() tapauksessa on välilehden nimi annettava $-merkin kanssa hakasuluissa eli esimerkiksi edellisen esimerkin tapauksessa muodossa [burtin$]. Koko burtin-aineisto voidaan hakea siis komennolla: >sqlquery(channel = ch, query = "SELECT * FROM [burtin$]") tai haku voidaan rajoittaa vaikkapa vain niihin riveihin, joilla sarakkeessa Gram on arvo negative: >sqlquery(channel = ch, query = "SELECT * FROM [burtin$] WHERE Gram='negative'") Olemassaolevaan tiedostoon voidaan lisätä uusi välilehti ja kirjoittaa sille jossakin datakehikossa oleva aineisto komennolla sqlsave(). Avataan ensin yhteys tavanomaisesti tiedostoon burtin2.xlsx: >chan<-odbcdriverconnect("driver=microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb); DBQ=C:/Users/Jarno Tuimala/Desktop/R-data/burtin2.xlsx; ReadOnly=False") Tämän jälkeen uusi aineisto lisätään uudelle välilehdelle seuraavalla komennolla: >sqlsave(chan, USArrests, "tests") Komennossa on kome argumenttia. Ensimmäinen kertoo sen yhteyden nimen, johon halutaan kirjoittaa. Toinen argumentti kertoo kirjoitettavan aineiston nimen, ja viimeinen argumentti uuden, luotavan välilehden nimen. Tässä USAarrests on eräs R:n mukana tuleva esimerkkiaineisto. Nyt tiedostossa burtin2.xlsx on kaksi välilehteä: burtin ja tests. Kun kaikki halutut toimenpiteet on tehty, voidaan tietty tietokantayhteys sulkea komennolla odbcclose(). Esimerkiksi yhteys tiedostoon burtin2.xlsx suljettaisiin komennolla: >odbcclose(chan) 95

104 PERUSTEET Ainoa komennolle annettava argumentti on siis suljettavan yhteyden, ei tiedoston, nimi. Kaikki avoinna olevat yhteydet voidaan sulkea yhdellä kertaa komennolla odbccloseall(). Myös R:n sulkeminen katkaisee kaikki tietokantayhteydet, mutta on parempi sulkea ne jo ennen ohjelmasta poistumista ongelmien välttämiseksi. Windows ei myöskään suostu avaamaan Excel-ohjelmassa sellaisia tiedostoja, joihin on luotu yhteys R:stä, jos yhteys on vielä auki. Jos siis tarkoituksena on kirjoittaa aineisto Excel-tiedostoon ja myöhemmin muokata sitä R:n vielä ollessa auki, on yhteys joka tapauksessa suljettava erikseen komennolla odbcclose(). Ehtolauseet Ehtolauseella tarkoitetaan komentojen yhdistelmää, jonka tarkoituksena on päättää, että jos tietty ehto täyttyy, miten sen jälkeen menetellään. Esimerkiksi voidaan vertailuoperaattorilla testata, onko jokin luku yhtä suuri kuin kymmenen, ja jos se on, niin tehdään sille jokin laskutoimitus. R tuntee kaksi ehtolausetta, if ja if...else. Kumpikin haluaa yhden tai useampia vertailuoperaatioita, mahdollisesti loogisilla operaatioilla yhdistettynä. Jos vertailu on tosi eli se saa arvon TRUE, if-lause suorittaa annetut komennot. Lause if...else puolestaan mahdollistaa kaksi eri toimintoa: yhden jos vertailu saa arvon TRUE ja toisen, jos se saa arvon FALSE. Ehtolauseiden käyttöä selventänee parhaiten muutama esimerkki. Talletetaan ensin muuttujan luku arvoksi 10: >luku<-c(10) Jos luku on yhtäsuuri kuin kymmenen, korotetaan se toiseen potenssiin, minkä tuloksen ruudulle pitäisi tulostua luku data. Tämä onnistuu komennolla if() seuraavasti: >if(luku==10) { +luku^2 +} [1] 100 If-lauseelle annetaan siis argumentiksi jokin vertailu, minkä jälkeen aaltosulkujen välissä luetellaan ne toiminnot, jotka toteutetaan, jos vertailu on tosi. Jos luvun ollessa jotakin muuta kuin kymmenen, siitä haluttaisiinkin ottaa neliöjuuri, voitaisiin käyttää joko erillistä if-lausetta: 96

105 R KIELEN PERUSTEET >if(luku==10) { +luku^2 +} >if(luku!=10) { +sqrt(luku) +} Vaihtoehtoisesti sama asia voitaisiin toteuttaan if...else-lausetta käyttäen seuraavasti: >if(luku==10) { +luku^2 +} else { +sqrt(luku) +} Edellisissä esimerkeissä on tärkeää kiinnittää huomiota siihen, miten ne on jaoteltu eri riveille. Ehtolauseet voidaan R:ssä kirjoittaa monella eri tavalla, mutta ne on hyvin helppo rikkoa, jos kaarisulut on aseteltu väärin. Niinpä suosittelen yllä esitetyn kaltaista ohjelmointitapaa, jossa vertailuoperaation jälkeen tulee ensimmäinen kaarisulku, tämän jälkeen suoritettavat komennot, ja lopuksi ehtolauseen päättävä kaarisulku omalla rivillään. Silmukkarakenteet Silmukkarakenteiden avulla tiettyä toimenpidettä voidaan toistaa haluttu määrä kertoja. Tyypillinen esimerkki, jossa silmukkarakennetta voidaan käyttää, on vaikkapa numeroiden 1-10 yhteenlasku. Yhteenlaskussa silmukkarakenne toimii siten, että se ottaa ensin ensimmäisen numeron ja laskeen sen yhteen toisen numeron kanssa. Näin muodostunut summa pidetään muistissa, ja luetaan kolmas luku. Kolmas luku lisätään jo aiemmin muodostettuun summaan, ja tällä uudella summalla korvataan aiemmin muistissa pidetty summa. Näin jatketaan kunnes kaikki luvut on käyty läpi. Silmukoita esiintyy myös reaalimaailmassa. Eräs esimerkki on vaikkapa 10 kilometrin juoksu olympialaisissa. Siinä kierretään 400 metrin rataa ympäri kunnes 10 matka tulee täyteen. Lisäksi kullakin kierroksella hypätään vesiesteen yli. Summan laskemiseen käytetty silmukka voidaan muodostaa esimerkiksi komennon for() avulla. Silmukan toteuttamista varten in ensin valittava minkä nimiseen objektiin silmukan kierros eli kuinka monta kertaa silmukka on pyörähtänyt ympäri talletetaan. Olkoon tällainen laskuri 97

106 PERUSTEET seuraavassa seuraavasti: objektissa i. Tämän jälkeen muodostetaan silmukka >for(i in 1:10) { +} Yllä muodostettu yksinkertainen silmukka koostuu kymmenestä kierroksesta, sillä i saa aluksi arvon 1, ja silmukan suorittaminen päättyy kun i saa arvon 10. Merkintä i in 1:10 ylläolevassa silmukassa tarkoittaa sitä, että i saa kaikki arvot yhdestä kymmeneen. Sanan in jälkeen siis luetellaan i:n saamat arvot. Ne voivat olla yksittäisiä lukuja, esimerkiksi: >for(i in c(1, 5, 10)) { +} Nyt i saa vain kolme eri arvoa, 1, 5 ja 10, ja sitten silmukan suorittaminen loppuu. Kumpikaan yllä muodostetuista silmukoista ei tee varsinaisesti mitään siinä mielessä, että ruudulle ei tulostu mitään. Jos kuitenkin silmukan suorittamisen jälkeen tarkistetaan, mikä arvo on talletettu muuttujaan i, havaitaan, että se on kummassakin tapauksessa kymmenen: > i [1] 10 Jo jonkinverran mielenkiintoisemman silmukasta tekee, jos kunkin kierroksen jälkeen i:n arvo tulostetaan ruudulle. Seuraava silmukka toimii näin. >for(i in 1:10) { +print(i) +} [1] 1 [1] 2 [1] 3 [1] 4 [1] 5 [1] 6 [1] 7 [1] 8 [1] 9 [1] 10 Silmukan sisällä kaarisulkujen välissä voidaan antaa komentoja, joita silmukan kullakin kierroksella suoritetaan. Yllä olevassa esimerkissä kunkin kierroksen jälkeen tulostetaan ruudulle jo läpikäytyjen kierrosten 98

107 R KIELEN PERUSTEET määrä komennolla print(). Silmukoiden avulla voidaan toteutta varsin monenlaisia hyödyllisiä toimintoja. Eräänä esimerkkinä oli lukujen yhteenlasku. Silmukan avulla se voitaisiin toteuttaa vaikkapa seuraavasti. Jos käytetään muuttujaan i tallentamaan silmukan kierrosten määrää, ja muuttujaa summa tallentamaan lukujen summaa, voidaan luvut 1-10 laskea yhteen alla esitettävän silmukan avulla. Aluksi lukujen summaksi talletetaan nolla muuttujaan summa. Tämän jälkeen muodostetaan silmukka, ja kullakin silmukan kierroksella muuttujan summa arvoon lisätään sen hetkisen kierroksen järjestysluku eli jo läpikäytyjen kierrosten lukumäärä: >summa<-c(0) +for(i in 1:10) { +summa<-summa+i +} >print(summa) Yhteenlaskutoimituksen toteuttaminen silmukkaa käyttäen on kuitenkin turhaa, sillä R:stä löytyy suoraan komento sum(), jolla saman asian voi laskea. Koska R on tulkittava kieli, ovat silmukat toisinaan hitaita, ja varsinkin monimutkaisemmissa operaatioissa silmukoiden käyttöä kannattaa välttää, jos se vain on suinkin mahdollista. Silmukoiden sijaan kannattaa käyttää vektoroituja operaatioita, siis sellaisia, jotka on ohjelmoitu toimimaan erityisesti vektoreilla. Tällainen komento sum() juuri onkin. Edellä esitellyn for-lauseen lisäksi R:ssä on muitakin silmukkarakenteita, kuten while-lause. Yhteenlaskuesimerkki voidaan toteuttaa komentoa while() käyttäen seuraavasti: >summa<-c(0) >i<-0 >while(i<10) { +i<-i+1 +summa<-summa+i >} Erona for-lauseen käyttöön on, että käyttäjän on muistettava koodata mukaan kierrosten seuranta. Yllä olevassa esimerkissä kullakin kierroksella i:n arvoon lisätään yksi, joten se toimii samaan tapaan kuin aiempi forlausetta käyttävä esimerkki. Silmukan aloittaa komento while(), jolle annetaan argumentiksi jokin vertailu. Tässä silmukka pysähtyy kun i saavuttaa arvon kymmenen. Silmukoista voidaan tarvittaessa poistua komennolla break(). Tällöin silmukan suorittaminen keskeytyy, ja R palaa takaisin komentoriville. 99

108 PERUSTEET Silmukasta poistuminen voi tulla kyseeseen esimerkiksi, kun halutaan ohjelmoida vikasietoinen silmukka, joka virheen havaitessaan lopettaa silmukan kauniisti. Komentoa break() voidaan myös käyttää, jos silmukka muodostetaan repeat-lauseella: >summa<-c(0) >i<-0 >repeat { +i<-i+1 +summa<-summa+i +if(i==10) { +break() +} >} Edeltävässä esimerkissä silmukka toteutettiin komennolla repeat, joka toistaa aaltosulkujen välissä annettuja komentoja, kunnes silmukka keskeytetään. Silmukka voidaan tietysti keskeyttää tavanomaisella tavalla painamalla kesken suorituksen Esc- tai Escape-näppäintä, mutta jos silmukka halutaan päättää tietyssä kohdassa voidaan käyttää komentoa break() sopivan ehtolauseen kanssa. Tässä suoritus keskeytetään, jos i saa arvon 1. Uusien komentojen ohjelmoiminen Uusien komentojen luomisella voidaan R.n ominaisuuksia helposti laajentaa. Esimerkiksi silmukkarakenteiden yhdeydessä toteutettu yhteenlaskutoimitus voitaisiin paketoida uudeksi komennoksi. Uusi komento luodaan komennolla function(). Komentoa seuraavat aaltosulut samaan tapaan kuin edellä on esitetty ehtolauseiden ja silmukkarakenteiden yhteydessä. Aaltosulkujen välissä luetellaan ne komennot, jotka luotavan komennon tulee suorittaa. Komennolle function() annetaan argumenteiksi luotavan komennon argumentit, joille voidaan määrätä myös jokin alkuarvo. Esimerkiksi luvuista toisen potenssin laskeva komento toteutettaisiin seuraavasti. Ensin päätetään, että kutsutaan lukua, josta potenssi halutaan laskea, nimellä x, ja että potenssikomennon nimeksi tulee p2. Tämän jälkeen komento luotaisiin komennolla: >p2<-function(x) { +x^2 +} 100

109 R KIELEN PERUSTEET Nyt komentoa p2() voidaan käyttää minkä tahansa muun komennon tapaan. Sillä voidaan laskea vaikkapa luvun 2 toinen potenssi: > p2(2) [1] 4 Komennon koodi voidaan tulostaa ruudulle kirjoittamalla sen nimi komentoriville ilman kaarisulkuja: > p2 function(x) { x^2 } Komennon argumentit voidaan tarkistaa komennolla args(): > args(p2) function (x) NULL Tulostuksesta voidaan päätellä, että komento p2() haluaa vain yhden argumentin, luvun nimeltä x, josta potenssi lasketaan. Argumenteille voidaan antaa myös oletusarvoja. Luodaanpa komento, joka laskee annetusta luvusta toisen potenssin, mutta jos lukua ei ole annettu, käytetään laskennassa lukua 2. Tällöin luku annetaan komennon function() argumentin x arvoksi: p2<-function(x=2) { x^2 } Nyt komento laskee potenssin käyttäen lukua kaksi, jos argumenttia ei ole annettu, muutoin se käyttää annettua lukua: > p2() [1] 4 > p2(4) [1] 16 Uudelle komennolle voidaan antaa erikoisargumentti..., jonka R tulkitsee graafisiksi parametreiksi, jotka välitetään suoraan komennolla par(). Komennolla par() voidaan muokata erilaisia graafisia parametreja, jotka vaikuttavat piirrettävän kuvan ominaisuuksiaan, kuten marginaalien leveyteen tai tekstin kokoon. Niiden käytöstä ei tässä yhteydessä anneta esimerkkiä, mutta asia kannattaa huomioida, sillä piirtokomentoja 101

110 PERUSTEET luotaessa siitä on suuresti hyötyä. Virheiden metsästys ja virheistä toipuminen Jokaiseen vähemmänkin pitempään komentoon tai komentosarjaan (ohjelmaan) tulee, ainakin ensivaiheessa, luultavasti erilaisia virheitä. Niiden paikallaistaminen ei kuitenkaan aina ole yksinkertaista, sillä virhe ei välttämättä esiinny siinä kohdassa, mihin komennon tai komentosarjan suorittaminen päättyy. Virheiden etsimiseksi on usein tarpeen käyttää erilaisia aputoimintoimintoja, joista tässä esiteltävät toiminnot on tarkoitettu virheiden etsimiseen jo olemassaolevista komennoista. Niiden avulla voidaan myös seurata jonkin komennon toimintaa vaihe vaiheelta. Uutta komentoa luotaessa on usein viisasta sijoittaa sopiviin kohtiin runsaasti komentoja print() tai cat(), joilla objektien sisältöjä tai silmukan kierrosten lukumääriä voidaan tulostaa ruudulle. Näiden avulla päästään usein virheiden etsinnässä jo varsin pitkälle. Vaikka turhien komentojen lisääminen koodiin tällä tavalla voi tuntua turhalta, on niistä suuri apu, kun virhetilanteita sattuu. Ylimääräiset komennot voidaan kuitenkin myöhemmin poistaa, mistä on pienempi vaiva kuin lähteä etsimään virhettä täysin pimennosta. Otetaan esimerkiksi silmukkarakenteiden yhteydessä luomamme uusi ohjelma lukujen summan laskemiseksi: >summa<-c(0) +for(i in 1:10) { +summa<-summa+i +} Komento on toki varsin yksinkertainen, mutta sopiikin siksi hyvin esimerkiksi. Jotta komennon toimintaa voitaisiin seurata vaihe vaiheelta, voidaan siihen sijoittaa komentoja, jotka tulostavat sekä silmukan kierrosnumeron että summan arvon jokaisella kierroksella: >summa<-c(0) +for(i in 1:10) { +summa<-summa+i +print(i) +print(summa) +} Ohjelma tulostaa ajettaessa luettelon sekä kierrosnumeroista, että summan arvoista, mutta se on hieman vaikealukuinen, koska tulostusta ei ole muotoiltu sopivasti: 102

111 R KIELEN PERUSTEET [1] [1] [1] [1] [1] [1]... [1] [1] [1] [1] [1] [1] Tulostaminen voidaan komentoa paste(): tehdä kauniimminkin, >summa<-c(0) +for(i in 1:10) { +summa<-summa+i +print(paste("kierros ", i, ", +} esimerkiksi käyttäen Summa ", summa, sep="")) Nyt tulostus on jo helpommin luettavissa: [1] [1] [1] [1] [1] [1] [1] [1] [1] [1] "Kierros "Kierros "Kierros "Kierros "Kierros "Kierros "Kierros "Kierros "Kierros "Kierros 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, Summa 1" Summa 3" Summa 6" Summa 10" Summa 15" Summa 21" Summa 28" Summa 36" Summa 45" Summa 55" Erilaisten tulostuskomentojen lisääminen komentojen joukkoon on kuitenkin vain yksinkertaisin tapa lähestyä virheiden etsintää. Monimutkaisempien työkalujen avulla on mahdollista tutkia komennon tai ohjelman toimintaa tarkemminkin. Luodaan seuraavia esimerkkejä varten ensin komento summa(), jossa käytetään edellä esitettyä silmukkarakennetta. Komentoa summa() varten komentosarjaan tehdään ensin pieniä muutoksia. Ensinnäkin silmukan täytyy jatkuu niin pitkään kuin läpikäymättömiä lukuja on, joten forsilmukkaa muutetaan siten, että siihen tulee kierroksia yhtä monta kuin komennolle annettuja lukuja on. Tämä muutos on tehty riville: 103

112 PERUSTEET >for(i in 1:length(x)) Toinen muutos on, että silmukan jälkeen on lisätty komento return(), joka palauttaa muuttujan summa viimeisimmän arvon. Ilman kyseistä komentoa summa kyllä lasketaan, mutta se ei tulostu ruudulle eikä sitä voida tallentaa muuhunkaan muuttujaan. Kokonaisuudessaan tehty ohjelma näyttää nyt seuraavalta: >summa<-function(x) { + summa<-c(0) + for(i in 1:length(x)) { + summa<-summa+i + print(paste("kierros ", i, ", + } + return(summa) +} Summa ", summa, sep="")) Virheiden etsinnän tärkeä vaihe on ohjelman tai komennon testaaminen myös sellaisilla arvoilla, joita sille voidaan antaa, mutta joiden käyttöä ei ole toteutusvaiheessa välttämättä tultu erikseen ajateltua. Komennon summa() toteutusvaiheessa on ajateltu, että sillä lasketaan yhteen vain peräkkäisiä numeroita, mutta toimiiko se, jos numero eivät olekaan peräkkäisiä. Peräkkäisillä numeroilla saadaan oikea tulos: >summa(1:10) [1] "Kierros [1] "Kierros [1] "Kierros [1] "Kierros [1] "Kierros [1] "Kierros [1] "Kierros [1] "Kierros [1] "Kierros [1] "Kierros [1] 55 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, Summa 1" Summa 3" Summa 6" Summa 10" Summa 15" Summa 21" Summa 28" Summa 36" Summa 45" Summa 55" Mutta jos numerot eivät ole peräkkäisiä, on tulos väärä: > summa(c(1, [1] "Kierros [1] "Kierros [1] "Kierros [1] 6 3, 5)) 1, Summa 1" 2, Summa 3" 3, Summa 6" Mistä tämä johtuu? Yllä olevasta tulosteesta on helppo nähdä, että vaikka komennolle yhteenlaskettavaksi annetut luvut ovat 1, 3 ja 5, on komento 104

113 R KIELEN PERUSTEET laskenut yhteen luvut 1, 2 ja 3. Komentoa pitää siis muttaa, jos sillä halutaan laskea yhteen myös lukuja, jotka eivät ole peräkkäisiä. Muutos on tässä tapauksessa helppo. Komennon rivillä summa<-summa+i summaan lisätään aina silmukan kierrosnumero, vaikka oikeastaan summaan pitäisi lisätä annetuista luvuista seuraava. Virhe voidaan korjata muuttamalla rivi muotoon: summa<-summa+x[i] Tämän jälkeen edellä tehdylle testille saadaan oikea tulos: > summa(c(1,3,5)) [1] "Kierros 1, Summa 1" [1] "Kierros 2, Summa 4" [1] "Kierros 3, Summa 9" [1] 9 Laajennuspaketti codetools sisältää useita hyödyllisiä komentoja, joilla Rkoodin rakennetta ja siinä mahdollisesti pesiviä virheitä voidaan tutkia. Komennolla checkusage() voidaan etsiä erilaisia koodivirheitä. Tehdään ensin esimerkkiä varten uusi komento summa2(), joka ottaa kaksi argumenttia, mutta joista vain toista käytetään: >summa2<-function(x, y) { + summa<-c(0) + for(i in 1:length(x)) { + summa<-summa+x[i] + print(paste("kierros ", i, ", + } + return(summa) +} Summa ", summa, sep="")) Komento checkusage() ottaa nyt kaksi argumenttia, joista ensimmäinen määrittelee tutkittavan komennon nimen, ja jälkimmäinen, että kaikki havaitut virheet halutaan raportoida: > checkusage(summa2, all=true) <anonymous>: parameter y may not be used R havaitseekin, että komennon summa2() argumenttia y ei käytetä mihinkään. Tämä ei sinällään ole komennon toiminnan estävä virhe, mutta turhat argumentit kannattaa yleensä eliminoida sotkemasta asioita. 105

114 PERUSTEET Komennolla findglobals() voidaan tietysti komennosta etsiä siinä käytetyt muut komennot: > findglobals(summa) [1] ":" "[" "{" [7] "for" "length" "paste" "+" "print" "<-" "c" "return" Komennolle findglobals() annetaan siis yksi argumentti, joka on tutkittavan komennon nimi. Tuloksena se luettelee kaikki komennossa käytetyt muut komennot, joita näyttäisi tässä tapauksessa olevan 11. Jos edellä olevilla keinoilla ei mahdollista virhettä ole löytynyt, voidaan ohjelman tai komennon toimintaa seurata vaihe vaiheelta. Aluksi määritellään komennolla debug(), että halutaan aloittaa seuranta. Argumentiksi komennolle debug() annetaan seurattavan komennon nimi. Seurataan seuraavassa komennon summa() toimintaa: >debug(summa) Tämän jälkeen komentoa kutsuttaessa päästää browser-tilaan, jossa komentoa voidaan suorittaa rivi kerrallaan: >summa(1:3) > summa(1:3) debugging in: summa(1:3) debug: { summa <- c(0) for (i in 1:length(x)) { summa <- summa + x[i] print(paste("kierros ", i, ", } return(summa) } Browse[2]> Summa ", summa, sep = "")) Browser-tilassa, johon päästään myös antamalla komentoriviltä komento browse(), tavanomainen kehote > muuttuu esimerkiksi muotoon Browse[2]>. Hakasuluissa mainittu numero voi vaihdella. Seuraavaan komentoon voidaan siirtyä yksinkertaisesti painamalla rivinvaihtoa (Enter). Koko komennon summa() seuranta on esitetty alla. Browse[2]> debug: summa <- c(0) Browse[2]> debug: for (i in 1:length(x)) { summa <- summa + x[i] print(paste("kierros ", i, ", } Summa ", summa, sep = "")) 106

115 R KIELEN PERUSTEET Browse[2]> debug: i Browse[2]> debug: summa <- summa + x[i] Browse[2]> debug: print(paste("kierros ", i, ", Browse[2]> [1] "Kierros 1, Summa 1" debug: i Browse[2]> debug: summa <- summa + x[i] Browse[2]> debug: print(paste("kierros ", i, ", Browse[2]> [1] "Kierros 2, Summa 3" debug: i Browse[2]> debug: summa <- summa + x[i] Browse[2]> debug: print(paste("kierros ", i, ", Browse[2]> [1] "Kierros 3, Summa 6" debug: return(summa) Browse[2]> exiting from: summa(1:3) [1] 6 Summa ", summa, sep = "")) Summa ", summa, sep = "")) Summa ", summa, sep = "")) Ohjelman toiminta näyttää sikäli moitteettomalta, että kussakin vaiheessa sen tulostamat arvot tuntuvat järkeviltä. Kun komennon seuranta on saatu päätökseen, voidaan komennon seuranta lopettaa komennolla undebug(): >undebug(summa) Jos ohjelma kaatuu johonkin omituiseen virheilmoitukseen, voidaan syypää mahdollisesti selvittää komennolla traceback(). Se tulostaa virheeseen johtaneiden komentojen sarjan. Esimerkiksi jos edellä luodulle komennolle summa() syötetään luvun sijasta kirjain, on tuloksema virheilmoitus: > summa(c(1, 2, "a")) Error in summa + x[i] operator : non-numeric argument to binary Tällöin komennolla traceback() päästään kiinni virheen aiheuttaneeseen komentoon: > traceback() 1: summa(c(1, 2, "a")) Komento voidaan myös rakentaa sellaiseksi, että se tarvittaessa osaa toipua virheistä tai ainakin ilmoittaa käyttäjälle, että virhe on havaittu. Esimerkiksi komentoa summa() voidaan kehittää siten, että se ei 107

116 PERUSTEET alunperinkään hyväksy kirjaimia, ainoastaan numeroita. Jos syötteessä havaitaan kirjaimia, keskeytetään komennon suoritus virheilmoitukseen. Tämä voidaan toteuttaa yhdistämällä ehtolause komentoon stop(), jolla voidaan yhtäaikaisesti keskeyttää komennon suoritus ja tulostaa virheilmoitus. Esimerkiksi voidaan testata ovatko kaikki vektorin arvot numeerisia: >is.numeric(c(1, 2, "a")) [1] FALSE Tässä tapauksessa tulos on FALSE eli arvot eivät ole numeroita, vaan joukossa on ainakin yksi kirjain tai muuta muotoa vektorin arvo. Virheilmoitus voidaan tulostaa komennolla stop() seuraavasti: >stop("summa voidaan laskea vain luvuista!") Error: Summa voidaan laskea vain luvuista! Ehtolause ja virheilmoitus voidaan yhdistää vaikkapa seuraavasti: >if(!is.numeric(c(1, 2, "a"))) { +stop("summa voidaan laskea vain luvuista!") +} Komentoon summa() sovellettuna tämä näyttäisi seuraavalta: >summa<-function(x) { + if(!is.numeric(x)) { + stop("summa voidaan laskea vain numeroista!") + } + summa<-c(0) + for(i in 1:length(x)) { + summa<-summa+x[i] + print(paste("kierros ", i, ", Summa ", summa, sep="")) + } + return(summa) +} Jos komennolle summa() annetaan tämän jälkeen muitakin kuin lukuja yhteenlaskettavaksi, näyttää tulos seuraavalta: > summa2(c(1,2,"a")) Error in summa2(c(1, 2, "a")) : Summa voidaan laskea vain numeroista! Jos jonkin komennon toimivuudesta ei olla varmoja, voidaan tähän varautua ennalta. Esimerkiksi jos yritetään ladata tiedostoa burtin.txt 108

117 R KIELEN PERUSTEET Internetistä osoitteesta muttei tiedetä, onko kone yhdistetty Internetiin, voidaan latauskomennossa ottaa tämä huomioon. Tavanomainen latauskomento olisi: >download.file("http://koti.mbnet.fi/tuimala/oppaat/r/data/bu rtin.txt", "burtin.txt") Mahdolliseen virhetilanteeseen varauduttaessa latauskomento voidaan sijoittaa komennon try() sisälle seuraavasti: >lataus<try(download.file("http://koti.mbnet.fi/tuimala/oppaat/r/data /burtin.txt", "burtin.txt")) Jos tietokone on yhdistetty Internetiin ja tiedoston lataaminen onnistuu, on objektin lataus luokka kokonaislukuvektori, joka saa arvon nolla: >class(lataus) [1] "integer" > lataus [1] 0 Jos taas tietokonetta ei ole yhdistetty Internetiin, tai tiedoston lataaminen epäonnistuu jostakin muusta syystä, on objektin lataus luokka try-error, ja se sisältää komennon antaman virheilmoituksen: > class(lataus) [1] "try-error" > lataus [1] "Error in download.file(\"http://koti.mbnet.fi/tuimala/oppaat/r/data/bu rtin.txt\", : \n cannot open URL 'http://koti.mbnet.fi/tuimala/oppaat/r/data/burtin.txt'\n" attr(,"class") [1] "try-error" Nyt latauksen onnistuminen voitaisiin testata komennossa yhdistämällä komento try() sopivaan ehtolauseeseen esimerkiksi seuraavasti: >lataus<try(download.file("http://koti.mbnet.fi/tuimala/oppaat/r/data /burtin.txt", "burtin.txt")) >if(class(lataus)=="try-error") { +stop("lataus epäonnistui! Tarkista verkkoyhteys.") +} 109

118 PERUSTEET Yllä esitetyssä tapauksessa annetaan virheilmoitus, jos tiedostoa ei saatu ladattua, ja ohjelman tai komennon suorittaminen keskeytetään siihen. Jos taas tiedoston lataaminen onnistui, ohjelman sallitaan jatkua normaalisti, mitä tiedoston latauksen jälkeen sitten ikinä onkaan tulossa. Tiedostojen Internetistä lataamiseen liittyvän virhetilanteen käsittely ei tietenkään ole komennon try() ainut käyttötarkoitus, vaan sitä voidaan soveltaa yleisesti vastaavankaltaisissa tilanteissa, joissa halutaan voida vaikuttaa ohjelman toimintaa mahdollisimma virhetilanteissa. Lisäpakettien luominen Edellä on käsitelty ohjelmointia R-ympäristössä, uusien komentojen luomista ja mahdollisten ohjelmointivirheiden karsintaa. Suurin osa R:n toiminnallisuudesta on erilaisissa laajennuspaketeissa, joita edistyneempi tai ainakin harrastuneempi käyttäjä voi itsekin luoda. Jos ohjelmointiprojekti on tuottanut suhteellisen vähän koodia, voi laajennuspaketin luominen kuitenkin olla turhan järeä ratkaisu. Laajennuspaketin sijaan komennot voidaan tallentaa tekstitiedostoon, josta ne voidaan tarvittaessa lukea R:n muistiin komennolla source(). Esimerkiksi virheiden etsintään keskittyvässä kappaleessa kehitetty komento summa() on kirjan data-kansiossa tiedostossa nimeltä summa.r. Jos tiedosto sijaitsee työhakemistossa, se voidaan siis lukea R:ään komennolla: >source("summa.r") Tämän jälkeen komentoa summa() voidaan käyttää R:ssä kuin mitä tahansa muutakin komentoa. Lisäpakettien luomista ei tässä käsitellä enää tarkemmin, sillä kokonainen R:n mukana tuleva käsikirja, Writing R Extensions, käsittelee asiaa perinpohjaisesti. 110

119 R KIELEN PERUSTEET Grafiikka Tämä luku esittelee lähinnä R:n tarjoamia työkaluja tilastollisen grafiikan tuottamiseen. Aluksi käydään läpi erilaisia yhdelle, kahdelle ja useammalle muuttujalle soveltuvia kuvantamistapoja, kuten histogrammi, hajontakuvio ja mosaiikkikuvio. Tämän jälkeen keskitytään erityisesti kuvioiden muokkaamiseen haluttuun muotoon. Keskeistä ovat graafiset parametrit ja erilaiset tavat asetella kuviot samalle sivulle. Lopuksi esitellään muutamia edistyneempiä sovelluksia Grafiikkajärjestelmät R:sä on kaksi päällekkäistä järjestelmää, joilla voidaan tuottaa grafiikkaa. Tavanomainen base-grafiikkajärjestelmä esitellään tässä luvussa tarkemmin. Vaihtoehtoinen grid-järjestelmä, ja sen päälle rakennetut laajennuspaketit lattice ja ggplot2 esitellään huomattavasti lyhyemmin. Perusgrafiikan tuottamiseen tarvitaan vain R:n asennus, mutta gridtilastografiikan tuottaminen vaatii mainittujen laajennuspakettien asentamisen. Grafiikka voidaan tuottaa joko ruudulle, josta se voidaan myöhemmin tallentaa johonkin tiedostoon juuri sen näköisenä kuin kuvio ruudulla esiintyy, tai kuvio voidaan tuottaa suoraan johonkin tiedostoon. R osaa tallentaa kuvioita varsin monissa eri tiedostomuodoissa, kuten PDF, postscript, Windows Metafile, bitmap, TIFF, JPG ja PNG. Joillakin laajennuspaketeilla tätä valikoimaa voidaan vielä laajentaa. Kun kuvio tallennetaan suoraan tiedostoon, ei lopputulos välttämättä aina muistuta samaa kuviota, joka ruudulla näytetään, vaikka kummankin luomiseen olisikin käytetty samaa komentoa. Esimerkiksi tieteellisen aikakauslehden julkaisuun tarkoitettujen kuvien tuottaminen voi vaatia melko paljon työtä, jotta niistä saadaan juuri halutunkaltaisia. 111

120 GRAFIIKKA Peruskomento plot() ja tiedostojen tallentaminen Komento plot() tuottaa kuvion tietokoneen ruudulle. Tarkkaan ottaen sen toiminta riippuu kuvattavan objektin muodosta (vektori, faktori, päivämäärä, taulukko), mutta lukuarvoja sisältävälle vektorille tuloksen on hajontakuvio. Komento plot(1) tuottaa alla olevan hajontakuvion uuteen avautuvaan grafiikkaikkunaan. Grafiikkaikkunan ylälaidassa on valikkopalkki, jonka valikosta File on mahdollista tallentaa kuvio tiedostoon halutussa muodossa. Esimerkiksi valinnalla File->Save as->pdf... kuvio voidaan tallentaa PDF-tiedostoon. Kuvio voidaan tuottaa myös suoraan PDF-muotoiseen tiedostoon. Tällöin ensin soveltuvalla komennolla avataan tiedosto, johon kuvio halutaan tallentaa. Tämän jälkeen annetaan kuvion tuottamiseen tarkoitetut komennot, ja lopuksi tiedosto suljetaan. Tiedoston sulkeminen on hyvin tärkeää muistaa, sillä muutoin kaikki jatkossa tuotettavat kuviot tallentuvat edelleen samaiseen tiedostoon, eikä tiedostoa ole mahdollista tutkia muissa ohjelmissa, koska Windows ei suostu avaamaan tiedostoja, joihin on olemassa oleva avoin kirjoitusyhteys. 112

121 R KIELEN PERUSTEET Esimerkiksi yllä tuotettu erittäin yksinkertainen hajontakuvio voidaan tallentaa PDF-tiedostoon komennolla pdf(), joka avaa tiedostoon kirjoitusyhteyden. Komento haluaa argumentiksi sen tiedoston nimen, johon kuvio tallennetaan (tässä hajontakuvio.pdf). Tässä nimessä on oltava mukana myös tarkennin (.pdf), jotta Windows osaa avata sen oikeassa ohjelmassa. Lopuksi tiedosto voidaan sulkea komennolla dev.off(). Kuvion tuottaminen tapahtuu siis esimerkiksi seuraavasti: >pdf("hajontakuvio.pdf") >plot(1) >dev.off() windows 2 Komento dev.off() tulostaa ruudulle suljetun yhteyden numeron. Ne saavat avaamisjärjestyksessä juoksevan numeron. Muita kuvioiden tallentamiseen soveltuvia komentoja ovat muun muassa postscript(), windows(), png(), jpeg(), bmp(), ja tiff(). Riippuen komennosta, niille voidaan antaa monenlaisia argumentteja. Yleisin lienee kuvan koon määrittäminen. Edellisen PDF-esimerkin tapauksessa kuvan fyysinen koko määriteltäisiin tuumina vaikkapa A4kokoiseksi käyttäen argumenttia paper: >pdf("hajontakuvio.pdf", paper="a4") >plot(1) >dev.off() tai käyttäen tietoa A4-paperin mitoista millimetreinä (297 mm * 210 mm) sekä tuuman pituudesta (25,4 mm): >pdf("hajontakuvio.pdf", width=210/25.4, height=297/25.4) >plot(1) >dev.off() Pistekarttakuviolle, jollaisia ovat esimerkiksi bitmap, TIFF ja JPG, ei kokoa voida määritellä suoraan tuumina, vaan niiden koko määritellään pikseleiden tai pisteiden määränä. Kuvan lopullinen koko määräytyy sitten tulostuksessa käytettävän laitteen mukaan, tai jos kuva on yhdistetty esimerkiksi Word-dokumenttiin tai PowerPoint-esitykseen, niissä käytetyn skaalauksen mukaan. Useimmat tulostimet tulostavat nykyisin kuvia vähintään tarkkuudella 300 dpi (dots per inch), mikä tarkoittaa siis sitä, että jos pistekarttakuvio on 300 pistettä leveä ja korkea, on sen lopullinen koko tulostettuna yhden tuuman vaaka- ja pystysuoraan. Kokonaisen A4sivun täyttämiseksi tarkkuudella 300 dpi kuvan koon tulisi siis olla noin 113

122 GRAFIIKKA 2500 * 3500 pistettä. Seuraavassa siirrytään esittelemään erilaisia kuvioita, joita voidaan käyttää muuttujien kuvaamiseen. Aloitamme tilanteesta, jossa kuvattavana on vain yksi muuttuja. Kaikissa esimerkeissä käytetään rairuoho-aineistoa, joka on ladattu objektiin dat komennolla: >dat<-read.table("rairuoho.txt", header=t, sep="\t") Yhden jatkuvan muuttujan kuvaaminen Yhden jatkuvan muuttujan kuvaamiseen soveltuvat esimerkiksi histogrammi, tiheysfunktio (density), stem-and-leaf -kuvio, laatikkokuvio (boxplot) ja pistekuvio (stripchart). Muodostetaan kuvin mainituista kuvioista kasvatuksen seitsemäntenä päivänä mitatulle rairuohon pituudelle. Kuten edellisessä luvussa selitettiin, tämä voidaan irrottaa datakehikosta dat omaksi vektorikseen käyttäen komentoa dat$day7. Histogrammin kukin pylväs kuvaa pinta-alallaan kyseiseen pylvääseen sijoitettujen arvojen lukumäärää. Histogrammi voidaan piirtää komennolla hist(), joka ottaa argumentikseen muuttujan (vektorin) nimen: >hist(dat$day7) 114

123 R KIELEN PERUSTEET Histogrammista on helppo nähdä, että rairuohon pituuksin jakauma on jokseenkin symmetrinen ja yksihuippuinen, huipun ollessa 90 ja sadan millimetrin välissä. Sama asia voidaan kuvantaa myös käyttäen niin sanottua tiheysfunktion kernel-estimaattia, jota voi ajatella ikäänkuin siloitetuksi histogrammiksi. Ensin lasketaan kernel-estimaatti komennolla density(), ja tämän jälkeen piirretään siitä käyrä komennolla plot(): >dens<-density(dat$day7) >plot(dens) Stem-and-leaf kuvio on myös käyttökelpoinen esitystapa, mutta lähinnä pienille aineistoille. Siinä kutakin havaintoarvoa kuvataan yhdellä lukuarvolla, ja tuloksena on tavallaan vaakasuuntaan käännetty histogrammi. Kuvio muodostetaan komennolla stem(), joka ottaa argumentiksi muuttujan nimen: >stem(dat$day7) 115

124 GRAFIIKKA The decimal point is 1 digit(s) to the right of the Stem-and-leaf -kuviossa luvun kantaa ja desimaaleja erottaa pystypalkkimerkki ( ). Kunkin luvun kannan jälkeen on lueteltu kaikki siihen liittyvät havainnot käyttäen yhtä desimaalia kunkin esittämiseen. Siten kukin havainto esiintyy kuviossa vain kerran. Laatikkokuvion avulla esitetään usein muuttujan jakauman muoto käyttäen ei-parametrisia suureita, kuten mediaania sekä ylä- ja alakvartiilia. Laatikkokuvio muodostetaan komennolla boxplot(), joka ottaa argumentiksi muuttujan nimen: boxplot(dat$day7) Laatikon muodostavat alakvartiili (alin laatikon sivu), jonka alle jää 25% aineiston arvoista, mediaani (laatikon keskellä oleva vaakasuora viiva), sekä yläkvartiili (laatikon ylin sivu), jonka yläpuolella on 25% aineistosta. 116

125 R KIELEN PERUSTEET Laatikosta lähtevät viikset kuvaavat tässä aineiston pienintä ja suurinta arvoa, mutta ne voivat ulottua myös 1.5-kertaa laatikon korkeuden verron ylä- ja alakvartiilien ylä- ja alapuolelle, jos aineiston jakauma on hieman erilainen. Kuviossa toisinaan esiintyvät viiksien ulkopuolelle jäävät pisteet kuvaavat poikkeavia tai muista eniten poikkeavia havaintoja. Pistekuvio on yksiulotteinen hajontakuvio, jossa kaikki havainnot on kuvattu yhdessä tasossa, tavanomaisimmin vaakatasossa. Pistekuvio muodostetaan komennolla stripchart(), joka ottaa argumentiksi kuvannettavan muuttujan nimen: >stripchart(dat$day7) Pistekuviossa kutakin aineiston havaintoa kuvataan yhdelle pisteellä. Yhden luokitteluasteikollisen muuttujan kuvaaminen Yhden luokitteluasteikollisen muuttujan kuvaamiseen voidaan käyttää pylväsdiagrammia (barchart) tai pistekuviota (dotchart). Seuraavissa esimerkeissä käytetään raituoho aineiston muuttujaa germinate, joka ei varsinaisesti ole luokitteluasteikollinen muuttuja, vaan kuvaa itäneitten siementen lukumäärää kussakin käsittelyssä. 117

126 GRAFIIKKA Sekä pylväsdiagrammin, että pistekuvion muodostamiseksi on ensin laskettava kussakin luokassa olevien havaintojen lukumäärä. Tämä lienee helpointa tehdä komennolla table(). Talletetaan tulos objektiin germ: >germ<-table(dat$germinate) >germ Tämän jälkeen pylväsdiagrammi voidaan piirtää komennolla barplot(), joka ottaa argumentiksi luokkien lukumäärätiedon, siis edellä lasketun muuttujan germ: >barplot(germ) Pylväsdigrammissa pylvään korkeudet kuvaavat kuhunkin luokkaan kuuluvien havaintojen lukumääriä. Vaaka-akselilla on luokkien nimet. Pistekuviota käytetään usein pylväsdiagrammin sijaan, koska sen tapa esittää aineisto on usein pylväsdiagrammia havainnollisempi. Pistekuvio muodostetaan komennolla dotchart(), joka ottaa argumentiksi luokkien lukumäärät, siis jälleen edellä lasketun objektin germ: >dotchart(germ) 118

127 R KIELEN PERUSTEET Pistekuviossa kutakin luokkaa edustaa yksi piste, jonka sijainti vaakaakselilla kertoo luokan havaintojen lukumäärän. Luokat on sijoitettu pystyakselille. Kahden jatkuvan muuttujan kuvaaminen Kaikkein tavallisin tapa kuvata kahden jatkuvan muuttujan välistä yhteyttä on hajontakuvio. Siinä kumpikin muuttujan sijoitetaan omalle akselilleen, toinen vaaka- ja toinen pystyakselille. Kutakin havaintoa kuvataan sitten yhdellä pisteellä, joka sijoitetaan kuviion sille kohdin, jossa se muuttujien saamien arvojen perusteella sijaitsisi. Hajontakuvio muodostetaan komennolla plot(), ja sille annetaan kaksi argumenttia, x ja y, jotka määräävät vaaka (x)- ja pysty (y) -akseleille sijoitettavien objektien nimet. Esimerkiksi rairuohon pituus seitsemäntenä ja kahdeksantena päivänä voidaan havainnollistaa hajontakuviona komennolla: >plot(x=dat$day7, y=dat$day8) 119

128 GRAFIIKKA Yhden jatkuvan ja yhden luokitteluasteikollisen muuttujan kuvaaminen Jos toinen muuttujista on jatkuva, ja toinen luokitteluasteikollinen, voidaan niiden välistä yhteyttä kuvata esimerkiksi hajontakuviolla tai piirtämällä laatikkokuvio, kullekin luokitteluasteikon luokalle erikseen. Laatikkokuvioiden tuottaminen kullekin luokalle onnistuu jo edellä esitellyllä komennolla boxplot(). Nyt komennolle on kuitenkin tarpeen antaa yhden muuttujan sijaan kaava, jotta kuva piirtyy oikein. Kaava koostuu kolmesta osasto. Kaavan oikean ja vasemman puolen erottaa kissanhäntämerkki (~). Sen vasemmalle puolelle jää kuvattava jatkuva muuttuja ja sen oikealle puolelle luokitteluasteikollinen muuttuja. Esimerkiksi kullekin rairuohon kasvatusalustalle (bed) voidaan piirtää seitsemäntenä päivänä mitattujen pituuksien laatikkokuvio komennolla: >boxplot(dat$day7~dat$bed) Samaan tulokseen päästään itseasiassa myös komennolla plot(), sillä jos sen toinen argumentti on jatkuva muuttuja, ja toinen luokitteluasteikollinen (faktori tai tekstivektori), piirretään laatikkokuvio: 120

129 R KIELEN PERUSTEET > plot(x=dat$bed, y=dat$day7) Kummallakin tavoin piirrettynä tuloksena on kuvio, jossa on yksi laatikko kutakin alustatyyppiä kohden: Toinen vaihtoehto olisi piirtää vaikkapa samoista muuttujista hajontakuvio. Nyt tämä ei onnistu suoraan komennolla plot(), kuten edellä näimme, sillä toinen muuttujista on luokitteluasteikollinen. Ennen kuvan piirtämistä on muuttuja bed siis muutettava numeeriseksi. Muutos on helppo toteuttaa komennolla as.numeric(), joka koodaa tekstivektorin automaattisesti uudelleen juoksevilla numeroilla siten, että aakkosjärjestyksessä ensimmäisen luokan nimi saa arvon 1, ja näin jatketaan, kunnes kaikki luokat on käyty läpi: >as.numeric(dat$bed) [1] [29] Arvojen koodaus voidaan tarkistaa komentoa table() käyttäen: > table(dat$bed, as.numeric(dat$bed)) mould mould paper

130 GRAFIIKKA paper Kun kaikki on kunnossa, voidaan piirtää itse hajontakuvio seuraavasti: plot(x=as.numeric(dat$bed), y=dat$day7) Kukin luokitteluasteikon luokka on nyt kuvattu vaaka-akselilla numeroilla 1-4, ja on helppoo nähdä, että kuvioon muodostuu neljä pystysuuntaista palkkia. Ne koostuvat kussakin luokassa tehtyjen pituushavaintojen arvoista. Kahden luokitteluasteikollinen muuttujan kuvaaminen Kahden luokitteluasteikollisen muuttujan kuvaamisen soveltuu usein hyvin jonkinlainen taulukko. Taulukon lisäksi kuvaamiseen voidaan käyttää esimerkiksi mosaiikkikuviota, jossa taulukon soluja ja niihin sijoitettuja havaintojen lukumääriä kuvataan nelikulmioiden kokojen avulla. Yksinkertainen taulukko rairuohon kasvatusalustojen ja ksäittelyjen yhdistelmien lukumääristä voidaan tehdä komennolla table():, jolle annetaan argumentteina taulukoitavien muuttujien tai objektien nimet: > table(dat$bed, dat$treatment) 122

131 R KIELEN PERUSTEET mould1 mould2 paper4 paper8 nutrient water Sama tauluko voidaan esittää mosaiikkikuviona. Komento mosaicplot() piirtää kuvion, kunhan aineisto syötetään sille edellä muodostetun taulukon muodossa: >mosaicplot(table(dat$bed, dat$treatment)) Mosaiikkikuvio ei nyt ole kovinkaan mielenkiintoinen, sillä taulukon kaikissa soluissa esiintyi yhtä monta havaintoa. Kunkin suorakulmion leveys kuitenkin kuvastaa kyseisellä alustalla tehtyjen havaintojen lukumäärää tai oikeammin oikeastaan suhteellista osuutta kaikista sillä rivillä olevista havainnoista. Samaan tapaan kunkin suorakulmion korkeus kuvastaa kunkin käsittelyn havaintojen suhteellista osuutta kaikista havainnoista. Toinen tapa esittää sama aineisto on käyttää pylväsdiagrammin laajennusta, joka tunnetaan nimellä spineplot. Siinä kussakin pinotussa pylväsdiagrammissa, joita on yksi alustaa kohden, esitetään sekä vesi- että ravinnekäsittelyjen suhteellinen lukumäärä. Komento, jolla kuvio piirretään, on spineplot(), ja se toimii samaa tapaan kuin mosaicplot(): 123

132 GRAFIIKKA > spineplot(table(dat$bed, dat$treatment)) Vähintään kolmen jatkuvan muuttujan kuvaaminen Jos jatkuvia muuttujia on vähintään kolme, voidaan niiden välisiä suhteita kuvata hajontakuvioilla siten, että kustakin muuttujaparista piirretään oma hajontakuvio. Tällaista kuviota kutsutaan usein parittaishajontakuvioksi (scatter plot matrix tai pairplot). Muita vaihtoehtoja ovat erilaiset muun muassa viivakuviot ja rinnakkaiskoordinaattikuvio (parallel coordinates). Parittaishajontakuvio muodostetaan komennolla pairs(). Komennolle on annettava vähintään kaksi saraketta sisältävä taulukko, joko matriisi tai datakehikko. Rairuohoaineistossa sarakkeet 1-6 sisältävät rairuohon pituudet päivinä 3-8. Nämä sarakkeet voidaan erottaa datakehikosta erikseen käyttäen alaindeksiä: dat[,1:6]. Tämän jälkeen kuvio piirretään komennolla: >pairs(dat[,1:6]) 124

133 R KIELEN PERUSTEET Kuviossa on nyt yksi hajontakuvio kutakin muuttujien yhdistelmää kohden. Kunkin muuttujan nimi on merkitty tämän hajontakuviomatriisin lävistäjälle. Nimien leikkauskohdassa sijaitsee niiden välinen hajontakuvio. Esimerkiksi ensimmäisen rivin ensimmäinen kuva on siis muuttujien day3 ja day4 välinen hajontakuvio, jossa day3 on pystyakselilla ja day4 vaakaakselilla. Sama kuva on myös ensimmäisessä sarakkeessa ensimmäisenä, mutta siinä day3 on vaaka-akselilla ja day4 pystyakselilla. Toinen vaihtoehto on rinnakkaiskoordinaattikuvio. Siinä kutakin havaintoa kuvataan yhdellä käyrällä, joka kulkee eri muuttujien, tässä siis päivien läpi. Helpoiten tällaisen kuvan piirtää käyttäen komentoa matplot(). Oletusarvoisesti se piirtää yhden käyrän kutakin saraketta kohden, joten ennen kuvan piirtämistä on aineisto transponoitava. Transponoinnissa taulukon riveistä tulee sarakkeita ja sarakkeista rivejä. Transponointi tapahtuu komennolla t(). Talletetaan transponoitu aineisto muuttujaan tdays >tdays<-t(dat[,1:6]) Nyt rinnakkaiskoordinaattikuvio voidaan piirtää komennolla: >matplot(tdays, type="l") Komennon matplot() ensimmäinen 125 argumentti on kuvannettavan

134 GRAFIIKKA aineiston sisältävän objektin nimi. Jälkimmäinen argumentti type puolestaan määrittelee kuvion tyypin. Oletusarvoisesti piirretään hajontakuvio, jossa havaintoja merkitään juoksevilla numeroilla. Rinnakkaiskoordinaattikuviossa kuitenkin käytetään viivoja tai käyriä (lines), joten kuviotyypiksi valitaan "l". Tuloksena syntyy alla esitetty kuvio: Muita vaihtoehtoja useiden jatkuvien muuttujien yhtäaikaiseen tarkasteluun ovat yhteiskuvio (coplot) ja erilaiset pintoja esittävät kuviot, kuten korkeuskäyrät (contour) ja kolmiulotteinen hajontakuvio tai pinta. Yhteiskuvio voidaan hyvin muodostaa käyttäen yhtäaikaa sekä jatkuvia että luokitteluasteikollisia muuttujia, kunhan vastemuuttuja on jatkuva. Muodostetaan yhteiskuvio kolmen jatkuvan muuttujan, päivinä 3, 5 ja 7 mitattujen rairuohon pituuksien välille. Komento coplot() piirtää yhteiskuvion: >coplot(day3~day5 day7, data=dat) Komennon ensimmäinen argumentti on kaava, jossa on kolme osaa. Tässä day3 ja day5 ovat ne muuttujat, joiden yhteysjakauma halutaan esittää, ja day7 määrää, minkä muuttujan suhteen yhteysjakauma pilkotaan alajoukoiksi. Kullekin alajoukolle piirretään oma kuva. Argumentilla data kerrotaan minkä nimisestä objektista sarakkeita day3, day5 ja day7 126

135 R KIELEN PERUSTEET etsitään. Jos argumentti data halutaan jättää pois, pitää komento kirjoittaa osoittamaan juuri näihin sarakkeisiin: >coplot(dat$day3~dat$day5 dat$day7) Tuloksena on alla esitetty kuva: Ylimpänä kuvassa on kuudesta harmaasta palkista koostuva kuvio. Se kertoo muuttujan day7 arvojen jakauman eri alajoukoissa, ja niitä vastaavissa kuvissa. Kolmea vasemmanpuoleisinta palkkia vastaavat alarivin hajontakuvioita, ja kolme oikeanpuoleisinta ylärivin hajontakuvioita. Kuviosta on helppo nähdä, että kun rairuohon pituus päivänä 7 on varsin lyhyt, on pituus ollut lyhyt myös päivinä 3 ja 5. Ryhmien määrittelyyn voidaan käyttää myös luokitteluasteikollisia muuttujia, kuten käsittelyä: > coplot(dat$day7~dat$day3 dat$treatment) Tällöin päivinä 3 ja 7 tehtyjen pituusmittausten välinen hajontakuvio esitetään erikseen ravinnekäsittelylle (nutrient) ja vesikäsittelylle (water): 127

136 GRAFIIKKA Rairuoho kasvatus tehtiin jääpalamuoteissa, joiden korkeus oli kahdeksan palaa, ja leveys kuusi palaa. Kukin käsittely-alusta-yhdistelmä kasvatettiin yhdessä jääpalamuotin palassa. Rairuohon pituudet kussakin palassa voidaan esittää koeasetelman muodossa esimerkiksi korkeuskäyriä käyttäen. Ennen kuin korkeuskäyrät voidaan laskea ja piirtää, pitää aineisto ensin muokata koeasetelman muotoon. Edellä käytettyä muotoa kutsutaan aineiston pitkäksi (long) muodoksi, sillä kutakin muuttujaa edustaa vain yksi sarake. Korkeuskäyrien piirtämistä varten aineisto pitää muuntaa leveään muotoon, jossa seitsemännen päivän pituusdet on jaettu useammaksi muuttujaksi. Aineiston muunnos leveään muotoon tehdään seuraavasti. Poimitaan ensin objektiin d vain ne muuttujat, joita muunnoksessa tarvitaan. Nämä ovat rairuohon pituus seitsemäntenä päivänä (day7) sekä kunkin viljelmän sijainti jääpalamuotissa (row ja column). Uusi aineisto muodostetaan komennolla: >d<-dat[,c(5, 12, 13)] Tämän jälkeen aineisto muunnetaan leveään muotoon objektiin wide komennolla reshape(): 128

137 R KIELEN PERUSTEET >wide<-reshape(data=d, v.names="day7", timevar="column", direction="wide") idvar="row", Argumentti data määrittelee muokattavan aineiston sisältävän objektin nimen, ja argumentti direction, mihin suuntaan aineistoa ollaan muuntamassa, tässä siis leveään (wide) muotoon. Argumentti v.names määrittelee, mikä on vastemuuttuja (tässä day7). Sen arvot siis pilkotaan yhdestä sarakkeesta useampaan. Argumentti idvar määrittelee sen muuttujan nimen, jonka perusteella aineisto jaetaan riveille, ja argumentti timevar määrittelee sen muuttujan, jonka perusteella muuttuja day7 jaetaan eri sarakkeisiin. Alkuperäinen aineisto on muotoa: day7 row column Muunnoksen jälkeen aineiston on jokseenkin eri näköinen, sillä muuttujaa day7 vastaa nyt yhteensä kuusi eri saraketta: row day7.1 day7.2 day7.3 day7.4 day7.5 day Muunnettua aineistoa voidaan vielä kaunistella hieman, sillä saraketta row 129

138 GRAFIIKKA ei siinä mihinkään tarvita. Poistetaan siis se, ja talletetaan näin saatu aineisto nimellä d: >wide<-wide[,-1] > wide day7.1 day7.2 day7.3 day7.4 day7.5 day Kun aineisto on muokattu sopivaan muotoon, voidaan korkeuskäyräkuvio piirtää komennolla contour(). >contour(x=1:8, y=1:6, z=as.matrix(wide)) Komennolle contour() on tarpeen antaa kolme argumenttia, joista x ja y kertovat koordinaatit, joihin pisteisiin korkesukäyrä piirretään. Nämä ovat siis tässä yhteydessä koeasetelman rivien (x) ja sarakkeiden (y) lukumäärä. Kolmas argumentti z on matriisi, jossa kussakin pisteessä (x, y) tehtyjen havaintojen (rairuohon pituus) arvot on mainittu. Argumentille z annettavan taulukon on oltava matriisi, datakehikko ei sille kelpaa. Niinpä 130

139 R KIELEN PERUSTEET komennossa onkin muutettu datakehikko wide matriisiksi komennolla as.matrix(). Komennon contour() sijaan voidaan käyttää komentoa filled.contour(), jolloin tuloksena on väritetty korkeuskäyrästö: >filled.contour(x=1:8, y=1:6, z=as.matrix(wide)) Yksittäiset numeeriset arvot voidaan esittää myös kuvaamalla niiden suuruutta väreillä. Tällainen kuvio voidaan tuottaa komennolla image(): >image(x=1:8, y=1:6, z=as.matrix(wide)) Mitä suurempi havaintoarvo on, sitä kirkkaampi väri, valkoisen ollessa kirkkain ja tumman punaisen himmein väri. Tällä tavalla muodostetusta kuvasta kannattaa huomata, ettei se ole enää tismalleen samassa muodossa kuin alkuperäinen aineisto, vaan rivit ja sarakkeet ovat vaihtaneet paikkaa. Aineiston kuvaaminen samassa muodossa kuin alkuperäinen aineisto vaatii hieman ylimääräistä vaivaa. Ensinnäkin aineistosta pitää ottaa transpoosi, ja sen jälkeen sarakkeet tulee järjestellä laskevaan järjestykseen, mikä onnistuu alaindeksiä käyttäen. Seuraava komento tekee tarvittavat järjestelyt, ja piirtää kuvan: > image(x=1:6, y=1:8, z=t(as.matrix(wide))[,8:1]) 131

140 GRAFIIKKA Korkeuskäyrien sijaan sama aineisto voidaan esittää myös kolmiulotteina hajontakuviona tai pintana. Näiden piirtämiseen löytyvät työkalut laajennuspaketista lattice, joka on siis ladattava ennen komentojen antamista: >library(lattice) Kolmiulotteinen hajontakuvio voidaan piirtää komennolla cloud(). Se saa kaksi argumenttia, joista ensimmäinen on kaava, jossa kissanhäntämerkin vasemmalle puolelle jää vastemuuttuja, jonka arvot esitetään kuvassa pystyakselilla (z-akseli). Kissanhäntämerkin oikealle puolelle jäävät kertomerkillä yhdistettynä ne muuttujat, jotka määräävät vaaka-akseleilla (x ja y). Lisäksi voidaan antaa argumentti data, jolla kerrotaan mistä objektista kaavassa mainittuja muuttujia etsitään. Hajontakuvio muodostuu siis komennolla: > cloud(day7~row*column, data=dat) Tuloksena syntyvä kuva on esitetty alla. 132

141 R KIELEN PERUSTEET Pinta voidaan piirtää komennolla wireframe(). Sen argumentti drape=true värittää kuvan vastemuuttujan day7 arvojen mukaan: >wireframe(day7~row*column, data=dat, drape=t) 133

142 GRAFIIKKA Toinen tapa piirtää pinta on käyttäen perusgrafiikkakomentoa persp(). Se haluaa aineiston samassa muodossa kuin esimerkiksi edellä esitelty komento contour(), joten jos aineisto on joka tapauksessa muutettu sille sopivaan muotoon, on komennon persp() käyttö helppoa. Seuraava komento piirtää pinnan, joka on esitetty miltei suoraan "sivulta": >persp(x=1:8, y=1:6, z=as.matrix(wide)) Toisinaan voikin olla hyödyllistä kääntää kuvaa hieman tulkinnan helpottamiseksi. Argumentti phi kääntää kuviota kuin sitä pyöritettäisiin eteenpäin tai taaksepäin. Argumentti theta puolestaan kääntää kuviota vaakasuunnassa. Molemmat haluavat tietyn arvon asteissa (0-360). Tässä tapauksessa seuraava komento piirtää kenties helpommin tulkittavan kuva, joka on esitetty alla: > persp(x=1:8, y=1:6, z=as.matrix(wide), theta=0, phi=60) Vähintään kolmen luokitteluasteikollisen muuttujan kuvaaminen Usean kategorisen muuttujan kuvaamiseen on ensisijaisena vaihtoehtona useinmiten mosaiikkikuvio. Edellä muodostettiin mosaiikkikuvio kahden muuttujan aineistosta. Samaan tapaan mosaiikkikuvio muodostetaan useammillekin muuttujille, mutta taulukkoa laskettaessa käytetään tietenkin kaikkia kolmea muuttujaa. 134

143 R KIELEN PERUSTEET Esimerkiksi rairuohon kasvatusalustan, käsittelyn ja sijainnin (jääpalamuotin ala- tai yläosassa) välille voidaan ensin muodostaa taulukko, josta piirretään mosaiikkikuvio: >mosaicplot(table(dat$bed, dat$treatment, dat$spatial1)) Toinen varsin usein käyttökelpoinen kuvio on rinnakkaiskoordinaattikuvio, joka piirretään samaan tapaan kuin aiemmin on esitetty. Graafisten asetusten muuttaminen Edellä esitetyt kuviot ovat useimmat varsin karun näköisiä. Niillä on usein otsikko, joka luettelee komennon, jolla kuva on piirretty, ja akselien otsikkoina toimivat usein muuttujien nimet. Kuvissa voi olla myös liikaa tai liian vähän marginaalia, tai teksti voi olla liian pientä luettavaksi. Useimmat, joskaan eivät aivan kaikki, asetukset toimivat kaikkien komentojen kanssa, mutta seuraavassa lähestytään asiaa hajontakuvion muokkaamisen kautta. Graafisia asetuksia voidaan muuttaa komennolla par(). Monien komentojen yhteyteen voidaan myös liittää komennon par() argumentteja siten, että ne vaikuttavat vain sillä hetkellä piirrettävänä olevan kuvan tuottamiseen. 135

144 GRAFIIKKA Uusi tyhjä kuva voidaan avata antamalla komento par(). Jos samalla on muutettu joitakin graafisia asetuksia, muutokset pätevät näin avattuun kuvaan kunnes se ikkuna, jossa kuva on auki, suljetaan. Jos siis ensin piirretään samaan ikkunaan yksi kuva, ja sen päälle toinen korvaten aiemman kuvan, molempiin pätevät samat graafiset asetukset. Jos sen sijaan asetuksia muutetaan kuvan piirtämiskomennossa, ne vaikuttavat vain sen kuvan piirtämisen ajan. Piirretäänpä ensin oletusarvoilla rairuohoaineiston päivien 3 ja 7 pituusmittausten tuloksista hajontakuvio: > plot(x=dat$day3, y=dat$day7) Syntyneessä kuvassa ei ole lainkaan otsikkoa, joten lisätäänpä se ensimmäisenä. Tämä tapahtuu käyttämällä argumenttia main kuvan piirtokomennossa. Otsikko annetaan tekstivektorina. Kuvalle kannattaa antaa jokin kuvaava nimi, vaikkapa "Rairuohon itämisajan pituus ei vaikuta lopulliseen pituuteen". Uusi, otsikollinen kuva piirretään komennolla: >plot(x=dat$day3, y=dat$day7, main="rairuohon pituus ei vaikuta lopulliseen pituuteen") Tuloksena olevassa kuvassa on nyt otsikko: 136 itämisajan

145 R KIELEN PERUSTEET Akselien otsikot ovat kuvan piirtämisessä käytettyjen muuttujien nimet. Muutetaan ne seuraavaksi kuvaavammiksi. Tämä tapahtuu lisäämällä piirtokomentoon argumentit xlab, joka määrittelee vaaka-akselin otsikon, ja ylab, joka määrittelee pystyakselin otsikon. Seuraava komento antaa siis vaaka-akselille otsikoksi "Pituus 3. päivänä", ja pystyakselille otsikoksi "Pituus 7. päivänä". >plot(x=dat$day3, y=dat$day7, main="rairuohon itämisajan pituus ei vaikuta lopulliseen pituuteen", xlab="pituus 3. päivänä", ylab="pituus 7. päivänä") Pystyakselin lukuarvot ovat pystysuorassa, mikä vaikeuttaa kuvan lukemista, mutta ne voidaan kääntää vaakasuoraan lisäämällä komentoon argumentti las=1. Se määrittelee akselien arvojen kirjoitussuunnaan, ja arvo 1 tarkoittaa vaakasuoraa. Nyt siis komento on kokonaisuudessaan: >plot(x=dat$day3, y=dat$day7, main="rairuohon itämisajan pituus ei vaikuta lopulliseen pituuteen", xlab="pituus 3. päivänä", ylab="pituus 7. päivänä", las=1) Ja sillä muodostuva kuva on esitetty alla. 137

146 GRAFIIKKA Kuvassa käytettyä tekstikokoa voidaan muokata useilla erilaisilla cexalkuisilla argumenteilla. Kukin argumentti saa oletusarvoisesti arvon 1. Sitä pienemmät arvot pienentävät tekstikokoa, ja suuremmat suurentavat tekstikokoa. Pääotsikon kokoa voidaan muuttaa argumentilla cex.main. Akselien otsikoiden kokoa muutetaan argumentilla cex.lab, ja argumentilla cex.axis vaikutetaan akselin lukuarvojen kokoon. Seuraavassa suurennetaan kaikkia 25%, jolloin kaikki tekstikokoasetukset saavat arvon 0.25: >plot(x=dat$day3, y=dat$day7, main="rairuohon itämisajan pituus ei vaikuta lopulliseen pituuteen", xlab="pituus 3. päivänä", ylab="pituus 7. päivänä", las=1, cex.main=1.25, cex.lab=1.25, cex.axis=1.25) Tuloksena syntyvä kuva on esitetty alla. 138

147 R KIELEN PERUSTEET Kunkin havainnon esittämiseen käytetyn symbolin kokoon voidaan vaikuttaa argumentilla cex. Tehdään niistäkin seuraavassa 1.25-kertaa oletusarvon kokoisia: >plot(x=dat$day3, y=dat$day7, main="rairuohon itämisajan pituus ei vaikuta lopulliseen pituuteen", xlab="pituus 3. päivänä", ylab="pituus 7. päivänä", las=1, cex.main=1.25, cex.lab=1.25, cex.axis=1.25, cex=1.25) Symbolia voidaan muuttaa argumentilla pch. Argumentille voidaan antaa tekstivektorina jokin merkki tai mikä on yleisempää, sille voidaan antaa jotakin ennalta määrättyä merkkiä vastaava numeroarvo. Merkit ja niitä vastaavat numeroarvot ovat: Oletusarvoisesti symbolina käytetään ympyrää, siis merkkiä numero 1. Jos symboliksi haluttaisiin vaihtaa vaikkapa suljettu ympyrä eli numero 19, tapahtuisi tämä lisäämällä piirtokomentoon argumentti pch=19: 139

148 GRAFIIKKA >plot(x=dat$day3, y=dat$day7, main="rairuohon itämisajan pituus ei vaikuta lopulliseen pituuteen", xlab="pituus 3. päivänä", ylab="pituus 7. päivänä", las=1, cex.main=1.25, cex.lab=1.25, cex.axis=1.25, cex=1.25, pch=19) Symbolien piirtämiseen käytettävää väriä voidaan muuttaa argumentilla col. Argumentille voidaan antaa arvoksi jokin värin nimi tai jokin ennalta määritettyjä värejä vastaava numeroarvo. Kaikki valmiiksi määritellyt värit, joita on 657 kappaletta, voi tarkistaa komennolla colors(), joka listaa hyväksyttävät värien nimet ruudulle. Muutetaan symbolien piirtäväri vaikkapa siniseksi: >plot(x=dat$day3, y=dat$day7, main="rairuohon itämisajan pituus ei vaikuta lopulliseen pituuteen", xlab="pituus 3. päivänä", ylab="pituus 7. päivänä", las=1, cex.main=1.25, cex.lab=1.25, cex.axis=1.25, cex=1.25, pch=19, col="blue") Nyt kuva näyttää seuraavalta: Symbolia ja sen väriä voidaan vaihtaa myös piste kerrallaan, sillä argumentit pch ja col hyväksyvät myös vektorin, jossa on useampia arvoja. Usein on kätevää, jos esimerkiksi jonkin luokitteluasteikollisen muuttujan luokat voidaan esittää eri symboleilla kuviossa. Esitetään nyt muodostamassamme hajontakuviossa vaikkapa 140

149 R KIELEN PERUSTEET rairuohoviljelmän käsittelyt eri värejä käyttäen. Ensin luodaan vektori, jossa kutakin pistettä vastaa yksi väri. Tämä voidaan luoda komennolla ifelse(), jolla korvataan alkuperäisen muuttujan treatment arvot värien nimillä. Valitaan sininen väri vastaamaan vesikäsittelyä ja punainen vastaamaan ravinnekäsittelyä. Talletetaan värit uuteen vektoriin nimeltä cols: >cols<-ifelse(dat$treatment=="water", "blue", "red") Piirretään tämän jälkeen hajontakuvio uudelleen siten, että nyt vektori cols annetaan argumentille col: >plot(x=dat$day3, y=dat$day7, main="rairuohon itämisajan pituus ei vaikuta lopulliseen pituuteen", xlab="pituus 3. päivänä", ylab="pituus 7. päivänä", las=1, cex.main=1.25, cex.lab=1.25, cex.axis=1.25, cex=1.25, pch=19, col=cols) Kuvan akselit määräytyvät automaattisesti, joskin tähänkin asiaan voidaan haluttaessa vaikuttaa. Toisinaan akselit vaativat muokkausta sen suhteen, mistä lukuarvosta niiden halutaan alkavan ja mihin niiden halutaan loppuvan. Hajontakuvion yhteydessä nämä voidaan määrittää argumenteilla xlim ja ylim. Kumpikin argumentti haluaa kahden mittaisen vektorin, jossa ensimmäinen arvo kertoo akselin alkupisteen ja 141

150 GRAFIIKKA jälkimmäinen arvo sen loppupisteen. Muutetaan pystyakseli alkamaan arvosta 40 ja loppumaan arvoon 140: >plot(x=dat$day3, y=dat$day7, main="rairuohon itämisajan pituus ei vaikuta lopulliseen pituuteen", xlab="pituus 3. päivänä", ylab="pituus 7. päivänä", las=1, cex.main=1.25, cex.lab=1.25, cex.axis=1.25, cex=1.25, pch=19, col=cols, ylim=c(40, 140)) Nyt kuva muuttuu hieman: Kuvan reunoissa näyttäisi olevan hieman ylimääräistä tilaa, joka voidaan poistaa muuttamalla marginaalien kokoja. Tähän käytetään argumenttia mar, joka ottaa neljä lukuarvoa. Ne määrittävät marginaalist järjestyksessä ala, vasen, ylä ja oikea. Oletusasetuksena on mar=c(5, 5, 5, 5)+0.1. Poistetaan hieman marginaalia alhaalta, ylhäältä ja oikealta: >par(mar=c(4,4,2,0)) >plot(x=dat$day3, y=dat$day7, main="rairuohon itämisajan pituus ei vaikuta lopulliseen pituuteen", xlab="pituus 3. päivänä", ylab="pituus 7. päivänä", las=1, cex.main=1.25, cex.lab=1.25, cex.axis=1.25, cex=1.25, pch=19, col=cols, ylim=c(40, 140)) 142

151 R KIELEN PERUSTEET Nyt muodostuva kuva on hieman edellistä suurempi, koska marginaaleihin jäänyt tyhjä tila on otettu käyttöön: Marginaalien muuttaminen on eräs niistä grafiikka-asetuksista, joka on pakko antaa käyttäen komentoa par() ennen itse kuvan piirtämistä. Jos argumentti mar sijoitetaan kuvan piirtokomentoon, sillä ei ole vaikutusta kuvan marginaaleihin. Edellä on esitelty kenties kaikkein useimmin käytetyt grafiikkaasetukset, mutta niitä on koko joukko lisää. Komennon par() ohjesivuun kannattaa tutustua tarkasti, sillä se luettelee kaikki asetukset, joita voidaan muuttaa. Tästä esityksestä poisjääneitä asetuksia ovat esimerkiksi kuvan fontin muuttaminen (font) ja kuvaa rajaavan laatikon muoto (bty). Elementtien lisääminen jo luotuun kuvaan Kaikki edellä mainitut komennot ovat korkean tason (high level) grafiikan tuottamiseen tarkoitettuja komentoja. Ne piirtävät kuvan, mutta sen muokkaaminen ei enää ole mahdollista, ellei sitä piirretä uudelleen. Alhaisen tason (low level) komennoilla jo piirrettyyn kuvaan voidaan kuitenkin lisätä esimerkiksi pisteitä, viivoja, nuolia, tekstiä tai selite. Jo luotuun kuvaan voidaan lisätä pisteitä komennolla points(). Sille 143

152 GRAFIIKKA annetaan kaksi muuttujaa, jotka määräävät lisättävien pisteiden sijainnin. Lisäksi pisteille voidaan luonnollisesti määritellä esimerkiksi väri tai symboli. Esimerkiksi edellä muodostettuun hajontakuvioon voidaan lisätä vaikkapa yksi musta piste vaaka-akselilla kohtaan 10 ja pystyakselilla kohtaan 120: >par(mar=c(4,4,2,0)) >plot(x=dat$day3, y=dat$day7, main="rairuohon itämisajan pituus ei vaikuta lopulliseen pituuteen", xlab="pituus 3. päivänä", ylab="pituus 7. päivänä", las=1, cex.main=1.25, cex.lab=1.25, cex.axis=1.25, cex=1.25, pch=19, col=cols, ylim=c(40, 140)) >points(x=10, y=120, pch=19) Komento points() osaa lisätä yhtäaikaa useampikin pisteitä, jos sille annetaan syötteksi kaksi vektoria. Esimerkiksi seuraava komento piirtäisi kunkin jo kuvassa oleva havainnon ympärille saman värisen ympyrän: >par(mar=c(4,4,2,0)) >plot(x=dat$day3, y=dat$day7, main="rairuohon itämisajan pituus ei vaikuta lopulliseen pituuteen", xlab="pituus 3. päivänä", ylab="pituus 7. päivänä", las=1, cex.main=1.25, cex.lab=1.25, cex.axis=1.25, cex=1.25, pch=19, col=cols, ylim=c(40, 140)) >points(x=dat$day3, y=dat$day7, pch=1, cex=2, col=cols) 144

153 R KIELEN PERUSTEET Koko kuvan halkaisevia viivoja on mahdollista lisätä komennolla abline(). Vaakasuora viiva lisätään antamalla sen argumentiksi h jokin numeroarvo. Vastaavasti pystysuora viiva listään antamalla argumentiksi v jokin numeroarvo. Lisätään esimerkiksi edellä muodostettuun hajontakuvoon pystyviiva kohtaan 5, ja vaakaviiva kohtaan 90: >par(mar=c(4,4,2,0)) >plot(x=dat$day3, y=dat$day7, main="rairuohon itämisajan pituus ei vaikuta lopulliseen pituuteen", xlab="pituus 3. päivänä", ylab="pituus 7. päivänä", las=1, cex.main=1.25, cex.lab=1.25, cex.axis=1.25, cex=1.25, pch=19, col=cols, ylim=c(40, 140)) >abline(h=90) >abline(v=5) Viivojen leveyttä voidaan muuttaa graafisella asetukselle lwd. Oletusarvona on 1, mikä tarkoittaa kapeaa viivaa. Viivan tyypin muuttaminen tapahtuu argumentilla lty, joka määrittelee, onko viiva yhtenäinen vai jonkinlainen katkoviiva. Oletusarvona on yhtenäinen viiva, mutta arvot 2-6 piirtävät erilaisia katkoviivoja. Jos edellä annettuja viivan piirtokomentoja muutetaan seuraavasti: >abline(h=90, lwd=2, lty=1) >abline(v=5, lwd=2, lty=2) 145

154 GRAFIIKKA saadaan tuloksena ala esitetty kuva. Erilaiset valmiiksi määritellyt viivatyypit on esitetty alla olevassa kuvassa: 146

155 R KIELEN PERUSTEET Erilaiset viivanpaksuudet väliltä 1-10 on esitetty esimerkinomaisesti alla olevassa kuvassa. Koko kuvan läpäisevan viivan sijaan voi toisinaan olla tarpeen piirtää lyhyempi viiva. Tämä tapahtuu komennolla lines(). Se haluaa kaksi argumenttia, x ja y, jotka määrittävät viivan alku- ja loppupisteiden sijainnin x- ja y-akseleilla. Edellä muodostettuun hajontakuvioon voidaan lisätä vaakaviiva, joka kulkee korkeudella 90, mutta alkaa vaaka-akselilla pisteestä 2 ja loppuu pisteeseen 8: >par(mar=c(4,4,2,0)) >plot(x=dat$day3, y=dat$day7, main="rairuohon itämisajan pituus ei vaikuta lopulliseen pituuteen", xlab="pituus 3. päivänä", ylab="pituus 7. päivänä", las=1, cex.main=1.25, cex.lab=1.25, cex.axis=1.25, cex=1.25, pch=19, col=cols, ylim=c(40, 140)) >lines(x=c(2,8), y=c(90, 90)) Näin muodstuva kuva on esitetty ala. 147

156 GRAFIIKKA Viivojen lisäksi kuvaan on mahdollista lisätä myös monikulmioita, polygoneja, komennolla polygon(). Piirretäänpä hajontakuvion oikeaan alareunaan suorakulmio, jonka vasen ylänurkka on kohdassa (x=6, y=80) ja oikea alanurkka kohdassa (x=10, y=60). Komennolle polygon() on tarpeen antaa kaksi argumenttia, x ja y, jotka määrittävät niiden pisteiden sijainnit, joissa monikulmion kulmat sijaitsevat. Vasemmasta ylanurkasta myötäpäivään lueteltuna nämä ovat siis (6,80), (10, 80), (10, 60), ja (6, 60). Argumentilla x määritellään kaikki x-akselin pisteet, ja argumentilla y puolestaan kaikki y-akselin pisteet. Argumentti x saisi tässä siis arvoksi vektorin c(6, 10, 10, 6) ja vastaavasti y vektorin c(80, 80, 60, 60). Koko kuvan piirtäminen taaphtuisi siis komennoilla: >par(mar=c(4,4,2,0)) >plot(x=dat$day3, y=dat$day7, main="rairuohon itämisajan pituus ei vaikuta lopulliseen pituuteen", xlab="pituus 3. päivänä", ylab="pituus 7. päivänä", las=1, cex.main=1.25, cex.lab=1.25, cex.axis=1.25, cex=1.25, pch=19, col=cols, ylim=c(40, 140)) Muodostuva kuva on esitetty alla. 148

157 R KIELEN PERUSTEET Komennolla arrows() kuvaan voidaan lisätä nuoli. Komento vaatii neljä argumentti, joista x0, ja y0 määrittävät nuolen alkupisteen ja x1 ja y1 nuolen loppupisteen. Jo piirretyn monikulmion sisään voitaisiin lisätä vasemmalta oikealle osoittava nuoli esimerkiksi komennolla: >arrows(x0=7, y0=70, x1=9, y1=70) Komentoa käytetään usein, kun pylväsdiagrammin pylväisiin halutaan lisätä luottamusvälit tai keskihajonnat. Koska tämä on niin yleinen kysymys, esitetään ratkaisu siihen tässä. Edellä piirrettiin tavanomainen pylväsdiagrammi siementen itämisajoista. Piirretään sama kuvio uudelleen, mutta nyt talletetaan komennon barplot() tulos objektiin r. Tästä on hyötyä, sillä nyt objektista r löytyvät kunkin pylväsdiagrammin pylvään keskikohdan sijainnit vaaka-akselillä, mitä käytämme hyväksi luottamusvälien piirtämisessä. >germ<-table(dat$germinate) >r<-barplot(germ) Ensimmäisen pylvään keskikohta näyttää sijaitsevan vaaka-akselilla kohdassa 0.7. Jos nyt oletetaan, että ensimmäisen pylvään luottamusväli on 0,5-1,5, piirretään nuoli pisteestä (0.7, 0.5) pisteeseen (0.7, 1.5). 149

158 GRAFIIKKA Argumentilla angle voidaan asettaa nuolen kärjen sivujen ja suuntaa osoittavan nuolen kannan välinen kulma. Jos nuolen halutaan loppuvan vaakasuoraan viivaan, on kulman oltava 90 astetta. Argumentilla lenght asetetaan nuolen kärjen sivujen pituus tuumina, tässä 0.1 toimii varsin hyvin. Jos lisäksi halutaan samanlainen vaakasuora viiva nuolen kumpaankin päähän, on piirrettävä päällekäin kaksi nuolta. Argumentilla code voidaan asettaa, kumpaan päähän nuolta kärki piirretään. Kun annetaan nuolen piirtokomento kaksi kertaa, ja kummassakin piirretään kärki eri päähän nuolta, saadaan lopulta haluttu tulos: >arrows(x0=0.7, x1=0.7, y0=0.5, y1=1.5, angle=90, length=0.1, code=1) >arrows(x0=0.7, x1=0.7, y0=0.5, y1=1.5, angle=90, length=0.1, code=2) Nyt kuvassa on nuoli vain ensimmäisessä pylväässä. Jotta jokaiseen pylvääseen saataisiin luottamusväli, pitää nuolen piirtokomennot toistaa kullekin pylväälle. Palataan takaisin hajontakuvioesimerkkiin. Jo piirrettyyn kuvaan on usein tarpeen lisätä tekstiä. Esimerkiksi SPSS-tyylisen hajontakuvion tuottamiseksi kukin piste voidaan merkitä sen sijainta vastaavalla tekstillä. Tämä tapahtuu komennolla text(). Se vaatii kolme argumenttia, kaksi vektoria, x ja y, jotka määrittävät tekstien sijaintikohdat, sekä itse tekstit, jotka määritellään argumentilla labels. Lisätäänpä kunkin havainnon 150

159 R KIELEN PERUSTEET yhteyteen sen havainnon sijainti. Muodostetaan ensin tekstivektori, joka sisältää sijoitettavat tekstit: >par(mar=c(4,4,2,0)) >plot(x=dat$day3, y=dat$day7, main="rairuohon itämisajan pituus ei vaikuta lopulliseen pituuteen", xlab="pituus 3. päivänä", ylab="pituus 7. päivänä", las=1, cex.main=1.25, cex.lab=1.25, cex.axis=1.25, cex=1.25, pch=19, col=cols, ylim=c(40, 140)) >txt<-paste("(", dat$day3, ",", dat$day7, ")", sep="") >text(x=dat$day3, y=dat$day7, labels=txt) Pisteiden merkitsemiseen käytetyt tekstit menevät kuitenkin pahasti päällekkäin itse havaintoja esittävien pisteiden kanssa. Tähän voidaan vaikuttaa argumentilla pos, jolla voidaan määrätä mille puolelle annettuja koordinaatteja teksti lisätään. Piirretään tekstit pisteiden oikealle puolelle argumentilla pos=4, ja pienennetään samalla tekstin kokoa hieman: >par(mar=c(4,4,2,0)) >plot(x=dat$day3, y=dat$day7, main="rairuohon itämisajan pituus ei vaikuta lopulliseen pituuteen", xlab="pituus 3. päivänä", ylab="pituus 7. päivänä", las=1, cex.main=1.25, cex.lab=1.25, cex.axis=1.25, cex=1.25, pch=19, col=cols, ylim=c(40, 140)) >txt<-paste("(", dat$day3, ",", dat$day7, ")", sep="") 151

160 GRAFIIKKA >text(x=dat$day3, y=dat$day7, labels=txt, pos=4, cex=0.75) Tämä parantaa kuvan luettavuutta huomattaavasti: Komennolla text() tekstin lisääminen kuvan marginaaleihin ei kuitenkaan onnistu. Tähän pitää käyttää komentoa mtext(). Se vaatii kaksi argumenttia: text, joka määrittää tekstin, joka marginaaliin lisätään, ja side, joka määrittää marginaalin, johon teksti lisätään. Piirretään ensi hajontakuvio siten, että oikeassa marginaalissa on tilaa tekstille, ja lisätään marginaaliin sitten teksti "Tekstiä marginaalissa": >par(mar=c(4,4,2,2)) >plot(x=dat$day3, y=dat$day7, main="rairuohon itämisajan pituus ei vaikuta lopulliseen pituuteen", xlab="pituus 3. päivänä", ylab="pituus 7. päivänä", las=1, cex.main=1.25, cex.lab=1.25, cex.axis=1.25, cex=1.25, pch=19, col=cols, ylim=c(40, 140)) >mtext(text="tekstiä marginaalissa", side=4) Näin muodostettu kuva on esitetty alla. 152

161 R KIELEN PERUSTEET Kuvaan on mahdollista lisätä myös selite. Selite muodostetaan komennolla legend(). Sille annettavat argumentit riippuvat kuvion tyypistä. Seuraavassa on esitetty selitteen lisääminen hajontakuvioon. Tärkeimmät argumentit ovat x, jolla määritetään selitteen sijaint, legend, joka on selitteen teksti, pch, joka määrää selitteesseä käyttävät merkit, ja col, joka määrittelee selitteen merkkien värit. Hajontakuviossamme näyttäisi olevan tyhjää tilaa oikeassa alareunassa, ja selite voidaan sijoittaa sinne käyttämällä argumenttia x="bottomright". Kaikki kuviossa esiintyvät symbolit ovat tyyppiä, joka koodi on 19, mikä voidaan määritellä käyttämällä argumenttia pch=19. Selitteen ensimmäiseksi tekstiksi sijoitetaan "ravinnekäsittely", ja toiseksi "vesikäsitely". Näitä vastaavien merkkien värit ovat punainen ja sininen, joten käytämme argumenttia col=c("red", "blue"). Kokonaisuudessaan kuvio voidaan siis tuottaa komennolla: >par(mar=c(4,4,2,0)) >plot(x=dat$day3, y=dat$day7, main="rairuohon itämisajan pituus ei vaikuta lopulliseen pituuteen", xlab="pituus 3. päivänä", ylab="pituus 7. päivänä", las=1, cex.main=1.25, cex.lab=1.25, cex.axis=1.25, cex=1.25, pch=19, col=cols, ylim=c(40, 140)) >legend(x="bottomright", legend=c("ravinnekäsittely", "Vesikäsittely"), pch=19, col=c("red", "blue")) 153

162 GRAFIIKKA Valmis kuva selitteineen on esitetty alla. Selite, jota ympäröi laatikko erottuu minusta liiaksi kuvasta, joten suosin itse lisäargumenttia bty="n", joka määrittelee, ettei selitteen ympärille piirretä lainkaan laatikkoa. Toinen selitettä usein kaunistava vaihtoehto on piirtää selite vaakasuoraan oletusarvoisen pystysuuntaisen sijaan. Tämä tapahtuu käyttämällä argumenttia horiz=true. Kun selite vielä keskitetään kuvan alareunaan käyttämällä argumenttia x="bottom" komennossa legend(): >par(mar=c(4,4,2,0)) >plot(x=dat$day3, y=dat$day7, main="rairuohon itämisajan pituus ei vaikuta lopulliseen pituuteen", xlab="pituus 3. päivänä", ylab="pituus 7. päivänä", las=1, cex.main=1.25, cex.lab=1.25, cex.axis=1.25, cex=1.25, pch=19, col=cols, ylim=c(40, 140)) >legend(x="bottom", legend=c("ravinnekäsittely", "Vesikäsittely"), pch=19, col=c("red", "blue"), horiz=t, bty="n") Yllä esitettyä koodia vastaava kuva on alla. 154

163 R KIELEN PERUSTEET Värien määrittäminen ja väriliu'ut R käyttää värien määrittelyyn etupäässä RGB-järjestelmää, mutta muitakin värijärjestelmiä, HCL ja HSV on mahdollista käyttää. RGB-järjestelmä perustuu ajatukseen, että väri muodostuu kolmen komponentin, punaisen (R), vihreän (G) ja sinisen (B) yhdistelmänä. Kullekin komponentille voidaan erikseen määrittää kirkkaus. Seuraavassa tutustutaan tarkemmin vain tämän RGB-järjestelmän soveltamiseen. Jotkin värit on R:ssä määritelty valmiiksi käyttöön. Esimerkiksi kuvien yhteydessä väreinä voidaan käyttää joko värien numerokoodeja tai niden nimiä. Käytettävissä olevat värikoodit voidaan tarkistaa komennolla palette(), joka oletusarvoisesti antaa seuraavan listan: >palette() [1] "black" "red" [6] "magenta" "yellow" "green3" "gray" "blue" "cyan" Vastaavalla tavalla kaikki nimellä määritellyt 657 väriä on mahdollista listata komennolla colors(). RGB-järjestelmässä kunkin värin kirkkaus voidaan asettaa joksikin 256 vaihtoehdosta. Tyypillisesti värin kirkkaus esitetään lukuarvona väliltä 0-155

164 GRAFIIKKA 256 tai kahdesta heksadesimaaliluvusta koostuvana yhdistelmänä. Yksinkertaisin tapa määritellä uusi väri, jota valmiista listoista ei löydy, on komentoa rgb() käyttäen. Se vaatii neljä argumenttia, joista kolme ensimmäistä määrittelevät punaisen, vihreän ja sinisen värin kirkkauden, ja neljäs argumentti maxcolorvalue määrittelee, mikä on määrittelyssä käytetty maksimikirkkauden arvo. Jotta määrittely olisi yhteensopiva muiden ohjelmistojen kanssa, kannattaa sille antaa aina arvo 255. Esimerkiksi kaikkein kirkkain punainen väri määritellään komennolla: >rgb(255, 0, 0, maxcolorvalue=255) [1] "#FF0000" Komennon antama risuaidalla (#) alkava numerojono on yllä mainittu RGBvärin heksadesimaalimuotoinen koodi. Heksadesimaalijärjestelmä tarkoittaa kuusitoistakantaista lukujärjestelmää, jossa numeroita 0-10 merkitään vastaavilla numeroilla, mutta numeroiden merkintään käytetän kirjaimia A-F. Kunkin värin kirkkaus voidaan siis esittää käyttäen kahta heksadesimaalilukua: esimerkiksi ylläolevassa värissä heksadesimaalimuotoinen luku FF vastaa kymmenjärjestetlmän lukua 256. Jos osaa kirjoittaa värin heksadesimaalimuodossa tekstivektoriksi, voi siis käyttää yhtä hyvin sitä komennon rgb() sijaan. Toisin sanoen, täyskirkas punainen väri voitaisiin koodata myös komennolla: >c("#ff0000") Värit voivat myös olla joko kokonaan tai osittain läpinäkyviä. Värin läpinäkyvyys ilmoitetaan RGB-järjestelmän tapaan numerolla, joka saa arvon väliltä Komennossa rgb() voidaan läpinäkyvyyden määrittämiseen käyttää argumenttia alpha: >rgb(255, 0, 0, maxcolorvalue=255, alpha=128) [1] "#FF000080" Kuten edeltävän komennon tulosteesta näkyy, koodataan läpinäkyvyys heksadesimaalimuodossa värin seitsemännen ja kahdeksannen merkin avulla (tässä 80). Läpinäkyvyyden käytöstä on hyötyä esimerkiksi silloin, kun piirrettävässä hajontakuviossa on suuri määrä pisteitä päällekkäin. Jos kaikkien piirtämiseen käytetään samaa väriä, ei pisteiden lukumäärä tule kovin hyvin esiin, koska pisteet peittävät toisensa, ja kuvasta voi tulla tasainen, mustaksi värjäytynyt pinta. Valmiiksi määriteltyjen värien RGB-järjestelmän mukainen koodaus voidaan selvittää komennolla col2rgb(). Komento tarvitsee vain yhden argumentin, värin nimen. Esimerkiksi oranssi (orange) antaa seuraavan tuloksen: 156

165 R KIELEN PERUSTEET >col2rgb("orange") [,1] red 255 green 165 blue 0 Joidenkin kuvien tuottamisessa erilaiset väriliu'ut ovat käteviä. Aiemmin muodostettiin rairuohojen pituuksista viljelmissä väritetty korkeuskäyräkuvio seuraavilla komennoilla: >d<-dat[,c(5, 12, 13)] >wide<-reshape(data=d, v.names="day7", idvar="row", timevar="column", direction="wide") >wide<-wide[,-1] >filled.contour(x=1:8, y=1:6, z=as.matrix(wide)) Kuva näytti seuraavalta: Väriliuku magentasta violettiin voidaan korvata vaikkapa harmaan sävyillä, kunhan piirtokomennolle annetaan värikoodeista koostuva vektori. Harmaan sävyjä voidaan helposti luoda komennolla grey(). Esimerkiksi neljästoista väriä valkoisesta mustaa sisältävä vektori voidaan tallentaa objektiin cols seuraavasti: >cols<-grey(1:14/14) 157

166 GRAFIIKKA Tämän jälkeen komennolla: värejä voidaan käyttää korkeuskäyrien piirtämiseen >filled.contour(x=1:8, y=1:6, z=as.matrix(wide), col=cols) Syntyvässä kuviosso lyhyitä rairuhokasvatuksia on kuvattu tummalla värillä, ja pitkiä vaalealla värillä: Muita valmiiden väriliukujen tekemiseen käytettävissä olevia komentoja ovat rainbow(), joka tuottaa sateenkaaren värejä, heat.colors(), joka tuottaa punaisen ja oranssin sävyjä, cm.colors(), jolla edellä esitetyn korkeuskäyräkuvion oletusarvoiset värit on tuotettu, ja terrain.colors(), sekä topo.colors(), jotka tuottavat karttoihin sopivia väriliukuja. Kukin näistä toimii samalla tavalla: ne kaikki haluavat argumentiksi tuotettavien värien määrä. Esimerkiksi: >topo.colors(6) [1] "#4C00FFFF" "#00E5FFFF" "#00FF4DFF" "#E6FF00FF" [5] "#FFFF00FF" "#FFE0B2FF" tuottaa kuusi karttoihin sopivaa värisävyä Väriliuku on myös mahdollista tuottaa minkä tahansa kahden värin välillä käyttäen komentoa colorramppalette(). Sen argumentiksi annetaan halutut kaksi väriä sisältävä vektori. Tuloksena on funktio, joka kutsuttaessa palauttaa pyydetyn määrän värjeä. Niinpä, jos halutaan 158

167 R KIELEN PERUSTEET saadan suoraan värit sisältävä vektori, on komennon loppuun vielä sijoitettava kaarisulkuihin värien lukumäärä. Esimerkiksi seuraava komento tuottaa kuusi väriä punaisen ja vihreän väliltä: >colorramppalette(c("red", "green"))(6) Kuvan kokoaminen yksittäisistä elementeistä Edellä on piirretty hajontakuvio käyttäen komentoa plot(), minkä jälkeen siihen on lisätty esimerkiksi selite komennoilla legend(). Komento plot() tekee suuren osan asioista automaattisesti, eikä esimerkiksi akselien piirtotapaan ole kovin paljon mahdollisuuksia vaikuttaa. Kuva on kuitenkin mahdollistaa koota pala palalta siten, että kussakin vaiheessa kuvaa lisättävästä osasto tulee juuri sen näköinen kuin halutaan. Tällä tavalla kuvan kokoaminen on kuitenkin huomattavasti vaivalloisempaa kuin valmiita piirtokomentoja käyttäen. Seuraavassa esimerkissä kootaan edellä piirretty hajontakuvio osissa. Avataan aluksi marginaalien osalta sopivan kokoinen piirtoalue käyttäen komentoa par(): >par(mar=c(4,4,2,0)) Tämän jälkeen voidaan edetä useaa reittiä. Yksinkertaisinta lienee piirtää itse kuva aivan kuten edellä, mutta jättää akselit piirtämättä antamalla argumentti axes=false: >cols<-ifelse(dat$treatment=="water", "blue", "red") >plot(x=dat$day3, y=dat$day7, main="rairuohon itämisajan pituus ei vaikuta lopulliseen pituuteen", xlab="pituus 3. päivänä", ylab="pituus 7. päivänä", las=1, cex.main=1.25, cex.lab=1.25, cex.axis=1.25, cex=1.25, pch=19, col=cols, ylim=c(40, 140), axes=false) Tämän jälkeen kuvan ympärille voidaan piirtää laatikko komennolla box(): >box() Tarvittaessa laatikon viivanpaksuutta, väriä tai viivatyyppiä voidaan muuttaa argumenteilla. Esimerkiksi komento >box(lty=2, lwd=3, col="red") piirtäisi kuvaan katkoviivalla kolmen pisteen levyisen punaisen laatikon. 159

168 GRAFIIKKA Laatikon lisäämisen jälkeen voidaan piirtää akselit komennolla axis(). Argumentiksi komennolle on annettava vähintään sen sivun numero, jolle akseli piirretään. Tämä tapahtuu argumentilla side. Kuten aina, sivu määritellään numerolla, jossa 1=alasivu, 2=vasen sivu, 3=yläsivu, 4=oikea sivu. Siten komento >axis(side=1) piirtää kuvan vaaka-akselin, ja komento >axis(side=2) piirtää kuvan pystyakselin vasempaa laitaan. Näin piirretty hajontakuvio näyttää samalta kuin aiemmin komennolla plot() suoraan muodostettu kuva: Kuva on kuitenkin mahdollista piirtää vieläkin pienemmissä osissa, mistä seuraavassa esimerkki. Aloitetaan kuvan piirtäminen aivan kuten edellä, avaamalla sopivan kokoinen piirtoalue: >par(mar=c(4,4,2,0)) Tämän jälkeen luodaan kuva kuten yllä, mutta ei piirretä sitä lainkaan. 160

169 R KIELEN PERUSTEET Tämä tapahtuu argumentilla type="n". Jos itse kuvaa ei piirretä, R asettaa kuitenkin akselien alku- ja loppupisteet automaattisesti kohdalleen, jollei niitä muuteta argumenteilla xlim ja ylim, kuten aiemmin olemme itse asiassa menetelleet. Poistetaan myös akselit ja niiden otsikot argumenteilla axes=false ja xlab="" ja ylab="". >plot(x=dat$day3, y=dat$day7, type="n", axes=false, xlab="", ylab="", ylim=c(40,140)) Tässä vaiheessa tuloksena on täysin tyhjä kuva, johon voidaan lisätä osia halutulla tavalla. Piirretään ensin piirtoalueen ympärille laatikko: >box() Piirretään sen jälkeen itse havainnot: >points(x=dat$day3, y=dat$day7, col=cols, pch=19, cex=1.25) Lisätään sitten kuvalle otsikko komennolla title(): >title("rairuohon itämisajan pituus ei vaikuta lopulliseen pituuteen") Lisätään seuraavaksi akselit. Muutetaan akseleita siten, että merkinnät ovat harvemmassa. Vaaka-akselille muodostetaan vain kolme merkkiä, 0, 5 ja 10. Tämä tapahtuu komennolla axis() käyttäen argumenttia at. Samalla merkinnöille on kuitenkin annettava nimet käyttämällä argumenttia labels: >axis(side=1, at=c(0,5,10), labels=c(0,5,10)) Jos oletusarvoiset akselin merkintöihin liityvät viivat ovat liian pitkät, niiden pituutta voidaan muuttaa argumentilla tcl. Se negatiiviset arvot saavat merkit piirtymään kuvasta ulospäin, positiiviset arvot kuvan sisään. Lisäksi voidaan muuttaa akselin merkintöjen piirtokohtaa graafisella parametrilla mgp. Sille annetaan vektori, jonko toinen numero määrää, kuinka monta riviä akselista ulospäin merkinnät piirretään. Myös akselin merkintöjen kokoa voidaan muuttaa graafisella parametrilla cex.axis. Piirretään siis lopullinen akseli siten, että sen merkkiviivat osoittavat sisäänpäin, merkinnät ovat lähellä akselia (rivillä 0), ja merkintöjen tekstikoko on hieman tavallista suurempi: >axis(side=1, at=c(0,5,10), labels=c(0,5,10), 161 mgp=c(3,0,0),

170 GRAFIIKKA tcl=0.1, cex.axis=1.25) Toistetaan sama pystyakselille, mutta merkiten vain pituudet 40, 65, 90, 115 ja 140. Käännetään lisäksi merkinnät vaakasuoraan graafisella parametrilla las=1: >axis(side=2, at=c(40, 65, 90, 115, 140), labels=c(40, 65, 90, 115, 140), mgp=c(3,0,0), tcl=0.1, cex.axis=1.25, las=1) Lisätään lopuksi akselien otsikot komennolla mtext(). Oletusarvoisesti se lisää tekstin riville nolla akselista ulospäin, mutta kyseisellä rivillä on akselin merkintöjä. Lisätään otsikot riville 2 käyttämällä argumenttia line=2. Piirretään otsikot lisäksi hieman tavallista suuremmalla teksitllä käyttäen graafista parametria cex=1.25: >mtext(side=1, text="pituus 3. päivänä", line=2, cex=1.25) >mtext(side=2, text="pituus 7. päivänä", line=2, cex=1.25) Lisätään lopuksi komennolla: kuvan >legend(x="top", "Vesikäsittely"), bty="n") yläreunaan pch=19, selite aivan kuten aiemminkin legend=c("ravinnekäsittely", col=c("red", "blue"), horiz=t, Kokonaisuudessaan yllä luotu kuvan luomiseen tarvittavat komentojoukko on siis: >par(mar=c(4,4,2,0)) >plot(x=dat$day3, y=dat$day7, type="n", axes=false, xlab="", ylab="", ylim=c(40,140)) >box() >points(x=dat$day3, y=dat$day7, col=cols, pch=19, cex=1.25) >title("rairuohon itämisajan pituus ei vaikuta lopulliseen pituuteen") >axis(side=1, at=c(0,5,10), labels=c(0,5,10), mgp=c(3,0,0), tcl=0.1, cex.axis=1.25) >axis(side=2, at=c(40, 65, 90, 115, 140), labels=c(40, 65, 90, 115, 140), mgp=c(3,0,0), tcl=0.1, cex.axis=1.25, las=1) >mtext(side=1, text="pituus 3. päivänä", line=2, cex=1.25) >mtext(side=2, text="pituus 7. päivänä", line=2, cex=1.25) >legend(x="top", legend=c("ravinnekäsittely", "Vesikäsittely"), pch=19, col=c("red", "blue"), horiz=t, bty="n") Näin piirretty kuva on esitetty alla. 162

171 R KIELEN PERUSTEET Kuten näimme, on kuvan kokoamisessa pala palalta mahdollisuus vaikuttaa sen ulkonäköön valmista piirtokomentoa enemmän. Kuvan kokoaminen pala palalta on kuitenkin työlästä, ja yleensä siihen kannattaa ryhtyä vain, jos valmiilla piirtokomennolla ei, edes sen ominaisuuksia ja graafisia parametreja muokkaamalla, saada tuotettua tyydyttävää lopputulosta. Usean kuvan piirtäminen samalle sivulle Kaikissa edellä käsitellyissä esimerkeissä on kuhunkin kuvaan tai kullekin sivulle piirretty vain yksi ainoa kuva. Kuvia on kuitenkin mahdollistaa sijoittaa samaan kuvaan useampiakin. Tämän toteuttamiseen on kolme vaihtoehtoa: Graafisen parametrin mfow avulla voidaan määritellä sivulle tulevien kuvien lukumäärä riveinä ja sarakkeina. Komento split.screen() jakaa ruudun parametrin mfrow tapaan tiettyyn määrään rivejä ja sarakkeita, mutta kukin niistä voidaan jakaa edelleen pienemmiksi kuviksi. Sen avulla voidaankin tuottaa varsin monimutkaisia kuvaasetelmia. Eniten vaihtoehtoja tarjoaa kuitenkin komento layout(), jolla ruutu voidaan jakaa määrätyn kokoisiksi palasiksi, mikä erottaa sen muista jo mainituista vaihtoehdoista, joissa syntyvät alueet ovat aina kaikki keskenään samankokoisia. Seuraavassa esitellään esimerkein kunkin 163

172 GRAFIIKKA vaihtoehdon käyttöä. Graafisen parametrin mfrow käyttö on helppoa. Sille annetaan vektori, joka sisältää kaksi lukua, rivien ja sarakkeiden lukumäärän. Samalle sivulle tulevien kuvien lukumäärä on luonnollisesti rivien ja sarakkeiden lukumäärän tulo. Parametria on käytettävä komennossa par() ennen varsinaisten kuvien piirtämistä, muuten sillä ei ole vaikutusta. Luodaan sivu, jolla neljä kuvaa, ja merkitään ne kuvan numeroilla: >par(mfrow=c(2,2)) >plot(1, 1, main="kuva >plot(1, 1, main="kuva >plot(1, 1, main="kuva >plot(1, 1, main="kuva 1", 2", 3", 4", cex.main=3) cex.main=3) cex.main=3) cex.main=3) Jos tämän jälkeen annettaisiin jälleen uusi piirtokomento, tämä uusi kuva piirtyisi kuvan 1 paikalle ja korvaisi sen. Parametrin käytössä on erityisen näppärää, ettei piirrettävän kuvan paikan valinnasta tarvitse erikseen huolehtia, vaan kuvat piirretään tyhjille paikoille järjestyksessä ylävasemmalta alaoikealle. Sama kuva voidaan toteuttaa myös komennolla split.screen(). Sillekin annetaan argumenttina kahden mittainen vektori, joka määrää kuvarivien ja -sarakkeiden lukumäärän. Erona parametrin mfrow käyttöön on, että ennen kuin tiettyyn kuvaan voidaan piirtää, on se ensin valittava komennolla screen(). Komennolle screen annetaan sen kuvan numero, 164

173 R KIELEN PERUSTEET johon halutaan piirtää. Kuvien numerointi toimii samaan tapaan kuin parametrin mfrow tapauksessa, normaalin suomalaisen lukusuunnan mukaisesti. Luodaan sama kuva kuin edellä parametrillä mfrow käyttäen split.screen() ja screen() komentoja: >split.screen(c(2,2)) >screen(1) >plot(1, 1, main="kuva >screen(2) >plot(1, 1, main="kuva >screen(3) >plot(1, 1, main="kuva >screen(4) >plot(1, 1, main="kuva 1", cex.main=3) 2", cex.main=3) 3", cex.main=3) 4", cex.main=3) Piirtämisen jälkeen kuvat kannattaa sulkea, minkä jälkeen niihin ei enää voi tehdä muutoksia eikä niiden päälle voi myöskään vahingossa piirtää. Kuvan sulkeminen tapahtuu komennolla close.screen(), jolle annetaan argumentiksi kuvan tai kuvien numerot. Esimerkiksi komento >close.screen(1:4) sulkisi kaikki neljä edellä avattua kuvaa. Komennolla split.screen() on mahdollista luoda melko monimutkaisiakin kuvia, sillä jo kertaalleen pilkottu sivu tai kuva voidaan pilkkoa edelleen pienemmiksi osiksi. Pilkotaan ensin koko sivu neljäksi yhtäsuureksi kuvaksi: >split.screen(c(2,2)) [1] >screen(1) Nyt luodut kuvat saavat juoksevat numerot väliltä 1-4. Ja tämän jälkeen ensimmäinen kuva voidaan edelleen pilkkoa neljäksi pienemmäksi kuvaksi: >split.screen(c(2,2)) [1] Nämä uudet kuvat saavat juoksevat numerot väliltä 5-8. Nyt kuhunkin kuvaan voidaan tehdä oma kuva, esimerkiksi: screen(5) par(mar=c(0,0,5,0)) plot(1, 1, main="kuva 1.1", cex.main=2, axes=f, type="n") screen(6) par(mar=c(0,0,5,0)) 165

174 GRAFIIKKA plot(1, 1, main="kuva screen(7) par(mar=c(0,0,5,0)) plot(1, 1, main="kuva screen(8) par(mar=c(0,0,5,0)) plot(1, 1, main="kuva screen(2) plot(1, 1, main="kuva screen(3) plot(1, 1, main="kuva screen(4) plot(1, 1, main="kuva 1.2", cex.main=2, axes=f, type="n") 1.3", cex.main=2, axes=f, type="n") 1.4", cex.main=2, axes=f, type="n") 2", cex.main=3) 3", cex.main=3) 4", cex.main=3) Näin piirretty kuva näyttää seuraavalta: Vaikka komennolla split.screen() on mahdollista tehdä jo varsin monimutkaisia kuvakoosteita, ei sillä kuitenkaan ole mahdollista esimerkiksi tehdä yhtä kahden palstan levyistä ja kahta yhden palstan levyistä kuvaa. Tällaisiin tarkoituksiin onkin käytettävä komentoa layout(). Yksinkertaisimmillaan sille on tarpeen antaa matriisi, joka määrittelee eri kuvien sijainnin ruudulla. Matriisin rivien ja sarakkeiden määrä määrää kuinka moneen kuvariviin ja -sarakkeeseen sivu jaetaan. Kukin kuva on numeroitava juoksevalla numerolla siten, että ensimmäinen kuva saa numeron 1. Jos halutaan esimerkiksi useamman sarakkeen 166

175 R KIELEN PERUSTEET levyinen kuva, on kaikkiin niihin sarakkeisiin, joihin kuvan halutaan ulottuvan, sijoitettava sama numero kyseiselle riville. Luodaan seuraavassa esimerkinomaisesti sivu, jolla on yksi kahden sarakkeen levyinen kuva, ja sen alla kaksi sarakkeen levyistä kuvaa. Ensiksi luodaan siis sivun määrittelevä matriisi: >mat<-matrix(ncol=2, nrow=2, data=c(1,1,2,3), byrow=true) >mat [,1] [,2] [1,] 1 1 [2,] 2 3 Tämän jälkeen luodaan itse sivun asettelu antamalla matriisi argumentiksi komennolle layout(). Talletetaan asettelu objektiin l: > l<-layout(mat) Asettelun onnistuminen voidaan tarkistaa komennolla layout.show(): >layout.show(l) Asettelu näyttäisi olevan halutun mukainen. Kuvaksi 1 kutsutaan ylintä, koko sarakkeen levyistä kuvaa, ja kuvat 2 ja 3 sijaitsevat seuraavalla rivillä. Tämän jälkeen voidaan antaa kuvien piirtokomennot, ja kuvat lisätään 167

176 GRAFIIKKA sivulla kuvien komentosarja: saamien numeroiden järjestyksessä. Esimerkiksi >plot(1,1,main="kuva 1", cex.main=3) >plot(1,1,main="kuva 2", cex.main=3) >plot(1,1,main="kuva 3", cex.main=3) luo alla olevan kuvan. Asettelua voidaan vielä tarkentaa antamalla kuva-alueille eri leveydet ja korkeudet. Kullekin riville voidaan määrittää oma korkeutensa antamalla argumentille heights rivien korkeudet vektorina. Sarakkeiden leveydet voidaan määrittää antamalla argumentille widths kunkin sarakkeen leveys vektorissa. Luodaan sivu, jossa ensimmäinen rivi on 25% pystysuunnasta, ja alempi rivi 75% pystysuunnasta. Määritellään sarakkeiden leveyksiksi samaan tapaan 40% ja 60%. Piirretään sivulle lopuksi samat kuin edellisessä kuvassakin: >mat<-matrix(ncol=2, nrow=2, data=c(1,1,2,3), byrow=true) >l<-layout(mat, heights=c(0.25, 0.75), widths=c(0.40, 0.60)) >plot(1,1,main="kuva 1", cex.main=3) >plot(1,1,main="kuva 2", cex.main=3) >plot(1,1,main="kuva 3", cex.main=3) 168

177 R KIELEN PERUSTEET Muutamia erikoisempia kuvioita Seuraavassa esitellään tämän kirjan osion alkupään kuvien täydennykseksi muutamia sellaisia kuvioita, joita ei vielä ole esitelty. Nämä kuviot eivät välttämättä ole aina käyttökelpoisia tai niillä on rajattu käyttöalue, mutta niistä voi olla toisinaan hyötyä. Kuvioita ei esitelty jo aiemmin siksi, että niiden käyttäminen vaatii hieman syvällisempää osaamista ja käsitystä erilaisista graafisista parametreista, jotka on esitelty tämän osion aikana. Kartat R tarjoaa hyvät mahdolisuudet erilaisten karttojen piirtämiseen. Koko maailmankartta on saatavilla suhteellisen tarkkana esityksenä laajennuspaketissa mapdata. Karttoja voidaan piirtää komennolla map(). Koko maailmankartta voidaan piirtää yksinkertaisesti komennolla: >map("worldhires") Komennolle on annettu argumentiksi karttapaketin nimi. Samalla komennolla voidaan piirtää myös yksittäisen maan kartta, mutta tällöin komennolle annetaan lisätarkenteeksi piirrettävän valtion nimi. Esimerkiksi 169

178 GRAFIIKKA Suomen kartta voidaan piirtää komennolla: > map("worldhires", "Finland") Valitettavasti kartta perustuu vanhentuneisiin tietoihin valtioista, eikä siitä löydy esimerkiksi Viroa. Kuvaan voidaan lisätä myös koordinaatisto komennolla: 1980-luvun >map.axes() Tiedoista löytyvät kaupungit voidaan sijoittaa karttaa komennolla map.cities(), jolle on annettava argumentin country arvoksi jonkin maan nimi. >map.cities(country="finland") Suurimmat joet voidaan lisätä kartalle leveällä sinisellä viivalla käyttäen komentoa: >map("rivers", add=true, col="blue", lwd=2) Suomi näyttää näin muodostetussa kuvassa seuraavalta: Kartan avulla voidaan esimerkiksi selvittää, missä ovat maailman kaupungistuneimmat kolkat ja missä vähintään miljoonan asukkaan 170

179 R KIELEN PERUSTEET kaupungit sijaitsivat 1980-luvulla. Piirretään esin maailmankartta, ja lisätään siihen kaikki kaupungit. Käytetään piirtovärinä aavistuksen läpinäkyvää väriä, jotta päällekkäinkin menevät kaupungit näkyvät: >map("worldhires") >map.cities(col="# ", lwd=1) Lisätään lopuksi kaupungit: karttaa punaisella kaikki yli miljoonan asukkaan >map.cities(col="red", lwd=1, minpop= ) Tuloksena on alla oleva kartta. Kartta voidaan rajoittaa myös esittämään aluetta vain tiettyjen koordinaattien väliltä. Tämä tapahtuu lisäämällä komentoon map() argumentit xlim ja ylim. Maa-alueet voidaan värittää, kunhan mahdollisuus valitaan käyttämällä argumenttia fill=true. Tämän jälkeen maa-alueiden täyttöväri voidaan asettaa argumentilla col. Taustan väri on oletusarvoisesti valkoinen, mutta sitä voidaan muuttaa argumentilla bg. Kuvaan voidaan lisätä myös otsikko käyttämällä jo aiemmin tutuksi tullutta komentoa title(). Skaalan lisääminen tapahtuu komennolla map.scale(), joka haluaa kaksi argumenttia, joilla skaalan sijaintipaikka kuvassa määritellään. Piirretäänpä esimerkiksi Itämeren aluetta esittävä kuva käyttäen komentosarjaa: 171

180 GRAFIIKKA >map("worldhires", xlim=c(10.0,31), ylim=c(53,66), fill=true, col="lightgrey", bg="white", lwd=1) >title("baltic Sea") >map.axes() >map.scale(x=25.5, y=54, cex=0.5) Kuvaa voidaan täydentää vielä vaikkapa merkkaamalla siihen muutamien maiden pääkaupungit käyttäen komentoa map.cities(): >par(pch=19, lwd=2) >map.cities(capital=1, country="finland") >map.cities(capital=1, country="sweden") >map.cities(capital=1, country="estonia") Näin muodostettu kuva Itämeren alueesta on esitetty alla. 172

181 R KIELEN PERUSTEET R:n valmiit karttapaketit eivät sisällä tietoa esimerkiksi Suomen lääneistä tai kunnista, mutta tieto on mahdollista ladata ilmaiseksi Global Administrative Areas-hankkeen Internetsivuilta osoitteesta Näiden karttojen käyttö vaatii laajennuspaketin sp asennuksen. Aineisto voidaan ladata suoraan Internetistä R:ään, kunhan karttatiedostoon muodostetaan ensin yhteys komennolla url(): >library(sp) >con <- url("http://gadm.org/data/rda/fin_adm1.rdata") >load(con) >close(con) Tämän jälkeen kartta on R:ssä talletettuna objektiin nimeltä gadm. Suomen osalta saatavilla on neljä erilaista karttaa. Tiedosto FIN_adm1.RData, joka edellä on ladattu sisältää läänien rajat. Muut tiedoston sisältävät vanhojen läänien rajat (FIN_adm2.RData), maakuntien rajat (FIN_adm3.RData) ja kuntien rajat(fin_adm3.rdata). Kartan sisältö voidaan näyttää ruudulla komennolla: >spplot(gadm) 173

182 GRAFIIKKA Yksi yksittäinen kartta voidaan piirtää jostakin NAME-alkuisesti muuttujasta. Esimerkiksi nimikoidut läänit löytyvät muuttujasta NAME_1. Kartta voidaan piirtää antamalla tämän muuttujan nimi lisäargumentiksi komennolle spplot(): >spplot(gadm, "NAME_1") Kartan alueiden värittämiseen käytettyjä värejä voidaan muuttaa argumentilla col.regions. Alueet väritetään annetuilla väreilä siinä järjestyksessä kuin ne esiintyvät kartassa. Nimet saadaan selville vilkaisemalla muuttujaa NAME_1: 174

183 R KIELEN PERUSTEET > gadm$name_1 [1] Eastern Finland Lapland Oulu [3] Southern Finland Western Finland Levels: Eastern Finland Lapland Oulu Southern Finland Western Finland Esimerkiksi Etelä-Suomi voidaan värittää mustaksi, kun neljäs täyttöväri asetetaan mustaksi: >cols<-c("white", "white", "white", "black", "white") >spplot(gadm, "NAME_1", col.regions=cols) 175

184 GRAFIIKKA 176

185 R KIELEN PERUSTEET Tilastolliset toiminnot Tässä luvussa perehdytään R:n tilastollisiin työkaluihin. Luku alkaa kuvailevien suureiden ja klassisten tilastollisten testien esittelyllä, ja loppuu riippuvien otosten analysointiin soveltuvien työkalujen esittelyyn. Pääpaino on kuitenkin yleistetyssä lineaarisessa mallissa, mallin valinnassa ja validoinnissa. Useimmissa tämän luvun esimerkeissä käytetään rairuohoaineistoa, joka voidaan ladata komennolla: >dat<-read.table("rairuoho.txt", header=t, sep="\t") Aineiston kuvaileminen Aineistoa tai muuttujia kuvailevia suureita ovat yksinkertaiset tilastolliset suureet, kuten keskiarvo, keskihajonta, varianssi ja niitä vastaavat epäparametriset suureet, kuten mediaani ja kvartiiliväli. Kukin suure voidaan laskea omalla komennolla, ja näitä ovat esimerkiksi: Suure keskiarvo keskihajonta varianssi mediaani minimi maksimi vaihteluväli kvantiilit kvartiiliväli viiden numeron tiivistelmä Komento mean() sd() var() median() min() max() range() quantile() IQR() fivenum() Kutakin yllä mainituista komennoista voidaan käyttää yhden vektorin kuvailemiseen kerrallaan. Esimerkiksi rairuohoaineiston pituusmuuttujasta 177

186 TILASTOLLISET TOIMINNOT day7 voidaan laskea keskiarvo ja keskihajonta: >mean(dat$day7) [1] > sd(dat$day7) [1] Jos halutaan laskea kaikista datakehikon sarakkeista kerrallaan jokin kuvaileva suure, voidaan apuna käyttää joko jotakin apply-komentoa, kuten luvussa Perusteet on kuvattu. Toinen, kenties yksinkertaisempi ratkaisu on käyttää jotakin tarkoitukseen jo kehitettyä komentoa, kuten perus-r:n summary() tai laajennuspaketin psych komento describe(). Komento summary() antaa varsin suppean joukon kuvailevia suureita kustakin sarakkeeesta. Sillä on kuitenkin helppo tarkistaa esimerkiksi jatkuvien muuttujien vaihteluväli tai luokitteluasteikollisten muuttujien eri arvojen lukumäärä. Lisäksi komento mainitsee puuttuvien arvojen lukumäärän kullekin muuttujalle, jos aineistossa on puuttuvuutta. Komennon antama tulostus rairuoaineistosta on alla: > summary(dat) day3 day4 day5 day6 Min. : Min. : 4.00 Min. :17.00 Min. : st Qu.: st Qu.: st Qu.: st Qu.: Median : Median :19.00 Median :51.00 Median : Mean : Mean :19.08 Mean :49.10 Mean : rd Qu.: rd Qu.: rd Qu.: rd Qu.: Max. : Max. :32.00 Max. :78.00 Max. : day7 day8 germinate bed treatment Min. : Min. : 81.0 Min. : 6.00 mould1:12 nutrient:24 1st Qu.: st Qu.: st Qu.:15.00 mould2:12 water :24 Median : Median :108.5 Median :17.00 paper4:12 Mean : Mean :107.4 Mean :16.48 paper8:12 3rd Qu.: rd Qu.: rd Qu.:18.00 Max. : Max. :144.0 Max. :20.00 spatial1 spatial2 row column lower:24 left :16 Min. :1.00 Min. :1.0 upper:24 middle:16 1st Qu.:2.75 1st Qu.:2.0 right :16 Median :4.50 Median :3.5 Mean :4.50 Mean :3.5 3rd Qu.:6.25 3rd Qu.:5.0 Max. :8.00 Max. :6.0 Laajennuspaketin psych komento describe() tulostaa kutakin datakehikon saraketta kohden yhden rivin, jolla on lueteltu useita muuttujaa kuvaavia suureita. Tähdellä merkityt muuttujien (sarakkeiden) nimet ovat kategorisia, joten kuvailevat suureet eivät välttämättä sovellu niille. Tulostus rairuohoaineistosta on esitetty alla. > library(psych) > describe(dat) 178

187 R KIELEN PERUSTEET var range skew day3 day4 day5 day6 day7 day8 germinate bed* treatment* spatial1* spatial2* row column n kurtosis se day day day day day day germinate bed* treatment* spatial1* spatial2* row column mean sd median trimmed mad min max Muuttujien numeerinen kuvailu kannattaa yhdistää kuvien tarkasteluun. Esimerkiksi ylläolevia kuvailevia suureita tarkastelemalla on vaikeaa sanoa, onko muuttuja day7 normaalisti jakautunut vai ei. Stem-and-leaf -kuvion tarkastelu kuitenkin antaa olettaa, että jakauma on ainakin lähellä normaalista: > stem(dat$day7) The decimal point is 1 digit(s) to the right of the Erityisen tärkeää kuvien piirtäminen on kahden tai usemman muuttujan kuvailemisen apuna. Kahden muuttujan kuvailemiseen voidaan käyttää esimerkiksi korrelaatiota, jonka huonona puolena on, että se kuvastaa hyvin ainoastaan jokseenkin suoraviivaisia yhteyksiä muuttujien välillä. Korrelaation laskemisen voidaan käyttää komentoa cor(). Esimerkiksi 179

188 TILASTOLLISET TOIMINNOT muuttujien day3 ja day7 välille voidaan laskea korrelaatio komennolla: >cor(dat$day3, dat$day7) [1] Tuloksena saadaan nyt Pearsonin korrelaatiokerroin, mutta muitakin vaihtoehtoja on. Esimerkiksi Spearmanin korrelaatiokerroin saadaan laskettu käyttämällä argumenttia method="spearman": > cor(dat$day3, dat$day7, method="spearman") [1] Onko kummankaan korrelaation tarkastelemalla hajontakuviota: tulkitseminen järkevää? Se selviää >plot(dat$day3, dat$day7) Tuloksen tulkitseminen on aavistuksen vaikeaa, mutta näyttää enimmäkseen siltä, että muuttujien välinen yhteys on jokseenkin suoraviivaista. Niinpä korrelaatiokertoimen voi ajatella kuvastavan muuttujien välistä suhdetta hyväksyttävällä tavalla. Jos tutkittavia muuttujia on paljon, voidaan korrelaatiokertoimet laskea kaikille mahdollisille muuttujapareille syöttämällä komennolle cor() kokonainen datakehikko: 180

189 R KIELEN PERUSTEET >cor(dat[,1:7]) day3 day4 day5 day day day day day day germinate day8 germinate day day day day day day germinate day day Sarakkeiden ja rivien leikkauspisteissä ovat muuttujien väliset korrelaatiokertoimet. Esimerkiksi muuttujien day3 ja germinate välinen Pearsonin korrelaatiokerroin on Korrelaatio kannattaa yhdistä hajontakuvion tarkasteluun. Useiden muuttujien väliset hajontakuviot voidaan esittää matriisina komennolla pairs(): >pairs(dat[,1:7]) 181

190 TILASTOLLISET TOIMINNOT Suuren korrelaatiomatriisin tarkastelu voi olla vaikeaa, ja sitä voi helpottaa piirtämällä korrelaatioista kuvaajan. Laajennuspaketin ellipse komento plotcorr() tarjoaa tähän oivan mahdollisuuden. Sille annetaan syötteenä korrelaatiomatriisi, ja tuloksena on matriisin muotoon piirretty kuva, jossa korkeimmat korrelaatiot on esitetty litteimpinä aineistopilvinä, ja pienimmät korrelaatiot puolestaan miltei ympyröinä: >cors<-cor(dat[,1:7]) >plotcorr(cors mar=c(0,0,0,0)) Klassiset tilastolliset testit Klassisilla tilastollisilla testeillä tarkoitetaan tässä muun muassa mahden keskiarvon, varianssin tai suhteellisen osuuden vertailua kahdessa näytteessä. Muuttujan normaalisuuden testaaminen Useimmat yleisimmin käytetyt testit ovat varsin vakaita, robusteja, pienille poikkeamille niiden mahdollisesti tekemästä normaalisuusoletuksesta. Esimerkiksi t-testi kahden populaation keskiarvojen vertaamiseksi olettaa, 182

191 R KIELEN PERUSTEET että kummastakin populaatiosta tehdyt havainnot noudattavat normaalijakaumaa. Käytännössä useimmiten riittää, että muuttujan havainnoista piirretty histogrammin, stem-and-leaf -kuvio tai muu vastaavat osoittaa jakauman olevan yksihuippuinen ja jokseenkin symmetrinen. Esimerkiksi rairuohoaineiston muuttuja day7 näyttää tältä: >stem(dat$day7) The decimal point is 1 digit(s) to the right of the Normaalisuuden arviointiin voidaan käyttää myös normaalisuuskaaviota (normal probability plot). Tämä voidaan tuottaa komennoilla: >qqnorm(dat$day7) >qqline(dat$day7) Jos kuvioon merkityt pisteet sopivat hyvin kuviossa olevalle suoralle, 183

192 TILASTOLLISET TOIMINNOT voidaan muuttujan olettaa olevan normaalisti jakautunut. Kuviin perustuvien tarkastelujen lisäksi, voidaan normaalisuus testata jotakin sopivaa tilastollista testiä käyttäen. Tällainen on esimerkiksi ShapiroWilk:in testi, jonka voi tehdä komennolla shapiro.test(): > shapiro.test(dat$day7) Shapiro-Wilk normality test data: dat$day7 W = , p-value = Käytännössä kaikissa tilastollisissa testeissä nollahypoteesina on jonkinlainen testille sopiva ei-eroa -tyyppinen väittämä. Esimerkiksi Shapiro-Wilk:in testissä nollahypoteesina on, ettei muuttujan jakauma eroa normaalijakaumasta. Vaihtoehtoisena hypoteesina on, että muuttujan jakauma eroaa normaalijakaumasta. Koska tässä testin antama p-arvo on suuri, eikä lähelläkään tavanomaisesti käytettyjä merkitsevyysrajoja, jää nollahypoteesi (muuttujan jakauma on normaalinen) voimaan. Keskiarvotestit Keskiarvotesteillä, joita ovat esimerkiksi t-testi ja Wilcoxonin testi, voidaan testata esimerkiksi, ovatko kahden populaation keskiarvot erilaisia. Parametriset testit, kuten t-testi, perustuvat ajatukseen, että muuttujat ovat normaalisti jakautuneita. Epäparametriset testit eivät oleta muuttujilta normaalisuutta. Kahden populaation keskiarvojen vertaaminen t-testillä tapahtuu komennolla t.test(). Komennolle pitää antaa joko kaksi lukuarvoja sisältävää vektoria tai kaava, jossa on testattava muuttuja vasemmalla puolella ja oikealla puolella luokitteluasteikollinen muuttuja, joka jakaa havainnot kahteen eri ryhmään. Jos haluaisimme verrata vesi- ja ravinnekäsiteltyjen viljelmien pituuksia 7. päivänä, olisivat komentovaihtoehdot siis: >t.test(dat$day7[dat$treatment=="nutrient"], dat$day7[dat$treatment=="water"]) ja >t.test(dat$day7~dat$treatment) Molemmat vaihtoehdot antavat saman tuloksen: 184

193 R KIELEN PERUSTEET Welch Two Sample t-test data: dat$day7[dat$treatment == "nutrient"] and dat$day7[dat$treatment == "water"] t = , df = , p-value = alternative hypothesis: true difference in means is not equal to 0 95 percent confidence interval: sample estimates: mean of x mean of y Ylimmällä rivillä R kertoo tehneensä Welch:in t-testin, joka ei tee oletusta, että verrattavien populaatioiden varianssit olisivat samanlaiset. Tämän jälkeen R raportoi samalla rivillä testisuureen arvon (t = ), vapausasteiden määrän (df = ) ja näiden perusteella määräytyvän parvon (p-value = ). Tämän jälkeen R kertoo vaihtoehtoisen hypoteesin, joka on tässä tapauksessa, että populaatioiden keskiarvot ovat erisuuret. Populaatioiden keskiarvojen eron 95% luottamusväli on ja populaatioiden keskiarvot ovat ja Jos populaatioiden varianssit oletetaan yhtäsuuriksi, minkä paikkansapitävyys on mahdollista testata seuraavassa kappaleessa esiteltävien varianssitestien avulla, voidaan komentooon t.test() lisätä argumentti var.equal=true. Tällöin testinä käytetään klassista kahden populaation t-testiä, jonka tulos on esitetty alla. Sen tulkinta on samanlainen kuin yllä esitetyn Welch:in t-testin. > t.test(dat$day7~dat$treatment, var.equal=t) Two Sample t-test data: dat$day7 by dat$treatment t = , df = 46, p-value = alternative hypothesis: true difference in means is not equal to 0 95 percent confidence interval: sample estimates: mean in group nutrient mean in group water Tarvittaessa t-testin sijaan voidaan käyttää epäparametrista Wilcoxonin testiä komennolla wilcox.test(), joka toimii samaan tapaan kuin t-testi, joko kahdella vektorilla tai kaavalla: 185

194 TILASTOLLISET TOIMINNOT > wilcox.test(dat$day7~dat$treatment) >wilcox.test(dat$day7[dat$treatment=="nutrient"], dat$day7[dat$treatment=="water"]) Wilcoxon rank sum test with continuity correction data: dat$day7[dat$treatment == "nutrient"] and dat$day7[dat$treatment == "water"] W = 433.5, p-value = alternative hypothesis: true location shift is not equal to 0 Warning message: In wilcox.test.default(dat$day7[dat$treatment == "nutrient"], dat$day7[dat$treatment == : cannot compute exact p-value with ties R kertoo otsikossa käyttäneensä testissä jatkuvuuskorjausta (continuity correction). Tämän jälkeen R raportoi testisuureen arvon (W = 433.5), ja sitä vastaavan p-arvon (p-value = ). Vaihtoehtoinen hypoteesi on, ettei populaatioiden keskiarvojen ero ole yhtäsuuri kuin nolla. Lopuksi R varoittaa, ettei tarkkaa p-arvoa voitu laskea, koska datassa esiintyy sellaisia arvoja, jotka ovat molemmilla populaatioilla samat (ties). Jos mittaustulokset ovat parittaisia, siis esimerkiksi sellaisesta tilanteesta, jossa samoista henkilöistä on tehty mittauksia ennen ja jälkeen jonkin käsittelyn, voidaan tehtä parittainen t-testi tai parittainen Wilcoxonin testi käyttämällä argumenttia paired=t. Verrataan kuudennen ja seitsemännen päivän pituusmittauksia parittaisella t-testillä: > t.test(dat$day7, dat$day6, paired=t) Paired t-test data: dat$day7 and dat$day6 t = , df = 47, p-value < 2.2e-16 alternative hypothesis: true difference in means is not equal to 0 95 percent confidence interval: sample estimates: mean of the differences Testin tulosta luetaan samaan tapaan kuin edellä esitettyä kahden populaation testin tulosta. Samaan tulokseen päästään tekemällä päivien havaintojen erotuksille yhden populaation t-testi, jolloin erotusten keskiarvoa verrataan nollaan: 186

195 R KIELEN PERUSTEET > t.test(dat$day7-dat$day6) One Sample t-test data: dat$day7 - dat$day6 t = , df = 47, p-value < 2.2e-16 alternative hypothesis: true mean is not equal to 0 95 percent confidence interval: sample estimates: mean of x Jälleen tulosta luetaan samaan tapaan kuin aiemmin esitettyä kahden populaation t-testin tulosta. Varianssitestit Varianssitestejä käytetään kahden tai useamman näytteen (populaation) varianssien vertaamiseen. Varianssitestejä ovat esimerkiksi parametrinen F-testi ja sen epäparametrinen vastine Fligner-Killeen testi. Kahden populaation varianssien vertaaminen F-testillä tapahtuu komennolla var.test(). Se toimii samaan tapaan kuin t-testi, joka kahdella vektorilla tai kaavaa käyttäen. Kumpikin seuraavista komennoista >var.test(dat$day7[dat$treatment=="nutrient"], dat$day7[dat$treatment=="water"]) >var.test(dat$day7~dat$treatment) antaa siis saman tuloksen: F test to compare two variances data: dat$day7 by dat$treatment F = 1.883, num df = 23, denom df = 23, p-value = alternative hypothesis: true ratio of variances is not equal to 1 95 percent confidence interval: sample estimates: ratio of variances Ylimmällä rivillä R kertoo käytetyn testin nimen. Testisuureen arvo (F = 1.883), osoittajan (num df = 23) ja nimittäjän (denom df = 23) vapausasteen sekä näitä vastaava p-arvo (p-value = ) on lueteltu 187

196 TILASTOLLISET TOIMINNOT tämän jälkeen. Viimeisellä rivillä on populaatioiden varianssien arvioitu suhde eli osamäärä ( ), ja tämän osamäärän 95% luottamusväli on raportoitu sen yläpuolella ( ). Fligner-Killeen testi toimii hieman eri tavalla kuin F-testi: sille voidaan antaa joko havainnot sisältävä vektori ja havaintojen luokat sisältävä vektori tai kaava. Erona on siis, ettei Fligner-Killeen testi halua verrattavien populaatioiden havaintoja kahdessa eri vektorissa, vaan syötteenä pitää nimenomaan olla yksi havaintovektori ja yksi luokkavektori. Tässä tapauksessa alla mainituista komennoista kumpikin antaa saman tuloksen: >fligner.test(dat$day7, dat$treatment) >fligner.test(formula=dat$day7~dat$treatment) Fligner-Killeen test of homogeneity of variances data: dat$day7 by dat$treatment Fligner-Killeen:med chi-squared = , df = 1, p-value = Testin tuloksessa on ilmoitettu testisuureen arvo (chi-squared = ), vapausasteen (df = 1) ja näiden perusteella laskettu p-arvo (p-value = ). Rairuohoaineiston seitsemännen päivän mittaustuloksille sekä parametrinen testi että epäparametrinen testi antoivat saman tuloksen: populaatioiden variansseissa ei ole tilastollisesti merkitsevää eroa. Suhteellisen osuuden testit Suhteellisen osuuden testillä selvitetään, onko havaintojen suhteellinen osuus kahdessa eri populaatiossa yhtä suuri. Käytetään esimerkkinä Turun yliopiston opiskelijavalintoja vuodelta Silloin yliopistoon pyrki 3298 miestä, joista 761 pääsi sisään. Naispyrkijöitä oli 7114, joista 1466 pääsi sisään. Toisin sanoen, miehistä pääsi sisään noin 23%, mutta naisista vain noin 20%. Eron merkitsevyyden testaamiseen voidaan käyttää komentoa prop.test(). Sille annetaan kaksi vektoria, joista ensimmäinen kertoo onnistumisten määrän kummassakin ryhmässä. Jälkimmäinen vektori puolestaan kertoo kaikkien kokeiluiden (pyrkijöitten) määrän kummassakin ryhmässä. Testi tehtäisiin siis tässä tapauksessa seuraavasti: >prop.test(c(761, 1466), c(3298, 7114)) Testin tulos näyttää seuraavalta: 188

197 R KIELEN PERUSTEET 2-sample test for equality of proportions with continuity correction data: c(761, 1466) out of c(3298, 7114) X-squared = , df = 1, p-value = alternative hypothesis: two.sided 95 percent confidence interval: sample estimates: prop 1 prop Ylimmältä riviltä selviää, että testissä on sovelluttu epäjatkuvuuskorjausta. Testisuureen arvo (X-squared = ), vapausasteiden määrä (df = 1) ja näitä vastaava p-arvo (p-value = )löytyvät pari riviä alempaa. Ryhmien välisen eron 95% luottamusväli ( ) on raportoitu näiden alla, ja viimeisenä kummankin ryhmän onnistumisten osuus. Tulosten perusteella ryhmien välillä on tilastollisesti merkitsevä ero siten, että miehet näyttäisivät päässeen naisia helpommin Turun yliopistoon vuonna Yhteensopivuus- ja riippumattomuustestit Yhteensopivuustestillä tutkitaan, noudattaako jostakin populaatiosta poimittu otos oletettua jakaumaa. Esimerkki tällaisesta voisi olla nopan harhattomuuden tutkiminen: esiintyykö kaikki numeroita nopan heitoista kootussa aineistossa yhtä paljon. Riippumattomuustestillä tutkitaan, noudattavatko kahden populaation havainnot samaa jakaumaa. Testillä voidaan esimerkiksi selvittää samaa asiaa kuin edeltävän kappaleen suhteellisten osuuksien testillä: pääsivätkö miehet ja naiset yhtä helposti Turun yliopistoon vuonna Sekä yhteensopivuusettä riippumattomuustestit toteutetaan tyypillisesti Khiin neliötestillä. Seuraavassa tutkitaan yhteensopivuustestillä noppien harhattomuutta. Aineisto voidaan ladata komennolla: >nopat<-read.table("nopat.txt", header=true, sep="\t") Kukin aineiston sarake sisältää 120 havaintoa yhdestä nopasta. Ennen yhteensopivuustestin tekemistä havainnot pitää taulukoida. Tehdään taulukko valkoisen nopan havainnoista objektiin tbl: >tbl<-table(nopat$white) 189

198 TILASTOLLISET TOIMINNOT Tämän jälkeen yhteensopivuustesti tasajakauman kanssa voidaan suorittaa yksinkertaisesti komennolla: >chisq.test() Chi-squared test for given probabilities data: tbl X-squared = 7.7, df = 5, p-value = Tuloksessa on ilmoitettu testisuureen arvo (X-squared = 7.7), vapausasteiden määrä ( df = 5) sekä näitä vastaava p-arvo (p-value = ). Ajatusta, että nopan silmälukujen jakauma noudattaa oletettua tasajakaumaa, jossa kaikki arvot ovat yhtä todennäköisiä, ei voida hylätä. Jos on tarpeen verrata jakaumaa johonkin muuhun kuin tasajakaumaan, voidaan vertailujakauman todennäköisyysjakauma määrittää argumentilla p. Jos esimerkiksi haluttaisiin verrata, esiintyvätkö arvot 1-3 todennäköisyyksillä 0.3 kukin, ja arvot 4-6 todennäköisyydellä 0.1 / 3 = 0.03 kukin, testi voitaisiin tehdä seuraavasti: > chisq.test(tbl, p=c(0.3, 0.3, 0.3, 0.1/3, 0.1/3, 0.1/3)) Chi-squared test for given probabilities data: tbl X-squared = , df = 5, p-value < 2.2e-16 Warning message: In chisq.test(tbl, p = c(0.3, 0.3, 0.3, 0.1/3, 0.1/3, 0.1/3)) : Chi-squared approximation may be incorrect Tuloksen tulkintana olisi, että havainnot eivät näyttäisi noudattavan tällaista varsin epätasaista jakaumaa. Riippumattomuustestin suorittaminen on helpointa tehdä, jos ensin muodostetaan havainnoista taulukko. Noppa-aineistosta voidaan esimerkiksi tutkia, ovatko valkoisen nopan ja mustan nopan havaintojen jakauman samanlaiset. Tehdään ensin kaksi erillistä taulukkoa, jotka lopuksi yhdistetään yhdeksi taulukoksi, jolle testi tehdään: >tbl1<-table(nopat$white) >tbl2<-table(nopat$black) >tbl3<-cbind(tbl1, tbl2) >tbl3 190

199 R KIELEN PERUSTEET tbl1 tbl > chisq.test(tbl3) Pearson's Chi-squared test data: cbind(tbl1, tbl2) X-squared = , df = 5, p-value = Tulosten perusteella vaikuttaa siltä, että molempien noppien havainnot noudattavat samaa jakaumaa. Sama riippumattomuustesti voidaan tehdä myös Turun yliopiston vuoden 2007 opiskelivalintojen tuloksille. Muodostetaan ensin havainnoista matriisi: >utu<-matrix(nrow=2, ncol=2, data=c(761, 1466, 2537, 5648), byrow=true) >colnames(utu)<-c("mies", "nainen") >rownames(utu)<-c("pääsi", "hylättiin") > chisq.test(utu) Pearson's Chi-squared test with Yates' continuity correction data: utu X-squared = , df = 1, p-value = Tulos on testisuureen arvoa, vapausasteita ja p-arvoa myöten tismalleen sama kuin suhteellisten osuuksien testin antaman tulos. Tämä ei ole mitenkään yllättävää, sillä molemmat käyttävät Khiin neliötestiä! Tilastollinen mallinnus Kaikki edellä esitellyt klassiset testit voidaan suorittaa myös joustavammilla tilastollisilla malleilla, joista tässä kirjassa keskitytään erityisesti yleiseen ja yleistettyyn lineaariseen malliin. Yleinen lineaarinen malli tarkoittaa tilannetta, jossa vastemuuttuja on normaalisti jakautunut. Tavallisesti malli on ollut tapana jakaa edelleen kolmeen osaan, joista regressio kattaa tilanteen, jossa kaikki ennustavat muuttujat ovat jatkuvia, varianssianalyysi sopii tilanteeseen, jossa kaikki 191

200 TILASTOLLISET TOIMINNOT ennustavat muuttujat ovat luokitteluasteikollisia, ja covarianssianalyysi puolestaan soveltuu tilanteisiin, jossa ennustavien muuttujien joukossa on sekä jatkuvia että luokitteluasteikollisia muuttujia. Tässä kirjassa tästä historiallisesta jaottelusta on luovuttu, sillä ne ovat kaikki yleisen lineaarisen mallin erikoistapauksia, ja ne kaikki voidaan R:ssä suorittaa samalla komennolla lm(). Yleistetty lineaarinen malli on yleisen lineaarisen mallin laajennus, ja sitä voidaan käyttää tilanteissa, joissa vastemuuttuja ei ole normaalisti jakautunut. Jos vastemuuttuja koostuu lukumääristä, on kyseessä loglineaarinen malli eli Poisson- tai negatiivinen binomiaalinen regressio. Vastemuuttujan ollessa kaksiarvoinen, on kyseessä logistinen regressio. Tämän kaltaisia malleja voidaan R:ssä sovittaa komennolla glm(). Seuraavassa tutustutaan ensin yleisiin R:n regressiomalleihin liittyviin esitystapoihin, minkä jälkeen käydään läpi lineaaristen mallien toteutus, mallin valinta ja diagnosointi. Mallin esittäminen kaavana Regressiomalli voidaan esittää kaavana. Olemme jo aiemmin lyhyesti tutustuneet kaavoihin, jotka koostuvat vasemmasta puolesta, kissanhäntämerkistä ja oikeasta puolesta. Vasemmalla puolella on mallin vastemuuttuja, ja kissanhäntämerkin oikealla puolella määritetään malli ennustavien muuttujien avulla. Käytetään seuraavassa rairuohoaineiston muuttujia muutamissa esimerkeissä. Vastemuuttujana on aina day7 eli seitsemäntenä päivänä mitatut viljelmien pituudet. Selittävinä muuttujina ovat bed (viljelyalusta) ja treatment (käsittely). Yksinkertaisinta lineaarista mallia voidaan merkitä kaavalla: day7~1 Malleissa merkitä 1 tarkoittaa aina sitä, että mallissa on mukana y-akselin ja mallin leikkauspiste (intercept). Jos mallissa ei ole mukana kuin leikkauspiste, koostuu malli vain vastemuuttujan keskiarvosta. Jos mallissa on mukana ennustavia muuttujia, voidaan ykkönen jättää merkitsemättä. Esimerkiksi merkintä day7~bed tarkoittaisi mallia, jossa raituohon pituutta mallitettaisiin alustan avulla. Vaikka leikkauspistettä ei olekaan nyt ykkösellä erikseen valittu malliin mukaan, on se oletusarvoisesti aina mukana. Jos leikkauspistettä ei haluta mallissa arvioida, vaan regressiosuora tai -käyrä halutaan sovittaa 192

201 R KIELEN PERUSTEET kulkemaan origon kautta, voidaan mallin lisätä termi -1. Malli, jossa rairuohon pituutta ennustetaan alustalla, mutta leikkauspistettä ei haluta arvioida, merkittäisiin: day7~bed-1 Jos raituohon pituutta halutaan ennustaa sekä kasvatusalustalla että käsittelyllä, voidaan tällaista mallia merkitä esimerkiksi: day7~bed+treatment Tällaisessa mallissa sanotaan olevan mukana sekä alustan että käsittelyn päävaikutus. Jos muuttuja on merkitty malliin yksinään, on kyseessä muuttujan päävaikutus. Muuttujilla voi kuitenkin olla myös yhteisvaikutuksia keskenään. Yhteisvaikutus muuttujien välille voidaan merkitä sijoittamalla niiden nimien väliin kaksoispiste: day~bed:treatment Nyt malli ennustaa rairuohon pituutta vain alustan ja käsittelyn yhteisvaikutuksen avulla. Yhteisvaikutuksia ei kuitenkaan voi pitää mallissa yksinään, vaan jos mukana on muuttujien välinen yhteisvaikutus, on mukana oltava myös kyseisten muuttujien päävaikutukset. Tällöin malli näyttäisi kokonaisuudessaan seuraavalta: day7~bed+treatment+bed:treatment Nyt mukana ovat siis sekä alustan että käsittelyn päävaikutukset ja näiden yhteisvaikutus. Sama malli voidaan merkitä lyhyemmin käyttämällä kertomerkkiä päävaikutusten muuttujien nimien välillä: day7~bed*treatment Tällöin malliin otetaan mukaan kaikki muuttujien päävaikutukset ja yhteisvaikutukset. Yleinen lineaarinen malli Sovittaminen aineistoon Yleinen lineaarinen malli, olipa se sitten regressio, varianssi- tai kovarianssianalyysi, tapahtuu komennolla lm(). Edellä esiteltyjä mallin 193

202 TILASTOLLISET TOIMINNOT esittämistapoja käyttäen muodostetataan rairuohoaineistolle ensin yksinkertaisin mahdollinen malli (null model eli nollamalli), jossa on vain keskiarvo. Sovituksen tulos talletetaan objektiin fit0: >fit0<-lm(day7~1, data=dat) Mallin sovituksessa on useimmiten näppärintä käyttää muuttujien (sarakkeiden) nimiä, jos muuttujat ovat jossakin matriisissa tai datakehikossa. Tämä onnistuu kuitenkin vain, jos komennossa annetaan muuttujat sisältävän taulukun nimi argumentilla data. Jos argumenttia ei halua käyttää, voi mallin sovittaa myös viittaamalla taulukon sarakkeisiin suoraan: >fit0<-lm(dat$day7~1) Seuraavissa esimerkeissä käytetään yksinomaan argumenttiin data perustuvaa menetelmää. Objekti fit0 sisältää siis sovitetun mallin tiedot. Sen voi tulostaa ruudulle, jolloin R luettelee sovitettujen muuttujien parametrien estimaatiti, tässä siis vain muuttujan day7 keskiarvon mallin Intercept:nä: > fit0 Call: lm(formula = day7 ~ 1, data = dat) Coefficients: (Intercept) Koska malli estimoidaan suurimman uskottavuuden menetelmällä, on tulos sama kuin suoraan aineistosta laskettu keskiarvo: > mean(dat$day7) [1] Komennolla summary() on mahdollista tulostaa mallin tulos muodossa, joka sisältää enemmän informaatiota: > summary(fit0) Call: lm(formula = day7 ~ 1, data = dat) Residuals: Min 1Q Median 3Q 194 Max

203 R KIELEN PERUSTEET Coefficients: Estimate Std. Error t value Pr(> t ) (Intercept) <2e-16 *** --Signif. codes: 0 *** ** 0.01 * Residual standard error: on 47 degrees of freedom Tulosteen kohdassa Residuals on lueteltu joitakin jäännöstermien tunnuslukuja, kuten mediaani ja kvartiilit. Tämän jälkeen kohdassa Coefficients luetellaan kunkin mallissa arvioidun parametrin estimaatti keskihajontoineen, sekä niiden perusteella laskettu t-testisuure ja sitä vastaava p-arvo. Viimeisenä on kerrottu mallin jäännösvaihtelun ja vapausasteiden määrä. Komennolla anova() tulostetaan mallin varianssianalyysi (ANOVA) taulukko: > anova(fit0) Analysis of Variance Table Response: day7 Df Sum Sq Mean Sq F value Pr(>F) Residuals Tässä tapauksessa taulukko ei ole kovin mielenkiintoinen, koska malli koostuu vain keskiarvosta. Niinpä ANOVA-taulukossa onkin lueteltu vain neliösummat ja vapausasteet. Nollamallin lisäksi voidaan sovittaa täydellinen malli, joka sisältää kaikkien muuttujien päävaikutukset ja niiden yhteisvaikutukset. Jos rairuohon pituutta mallinnetaan kasvatusalustan ja käsittelyn avulla, olisi täydellinen malli siis: > fit1<-lm(day7~bed*treatment, data=dat) Tälle mallille on mahdollista tulostaa nollamallia mielenkiintoisempi yhteenveto: > summary(fit1) Call: lm(formula = day7 ~ bed * treatment, data = dat) Residuals: 195

204 TILASTOLLISET TOIMINNOT Min Q Median Q Max Coefficients: Estimate Std. Error t value Pr(> t ) (Intercept) < 2e-16 *** bedmould bedpaper *** bedpaper treatmentwater bedmould2:treatmentwater bedpaper4:treatmentwater bedpaper8:treatmentwater Signif. codes: 0 *** ** 0.01 * Residual standard error: on 40 degrees of freedom Multiple R-squared: 0.532, Adjusted R-squared: F-statistic: on 7 and 40 DF, p-value: 3.862e-05 Nyt parametrien estimaatit luettelevassa taulukossa on enemmän tulkittavaa. Kasvatusalustalla on neljä tasoa, joista ensimmäinen (mould1) on valittu vertailutasoksi, ja kaikkien muiden alustojen vaikutukset on esitetty suhteessa siihen. Siten, esimerkiksi tason mould2 vaikutus rairuohon pituuteen on luettavissa riviltä bedmould2, jolla parametrin estimaatti on Toisin sanoen, verrattuna alustaan mould1, antaa mould2 keskimäärin 6.33 millimetriä pidemmän rairuohokasvuston. Vastaavalla tavalla käsittelylle on valittu perustasoksi nutrient, ja vesikäsittelyn vaikutus suhteessa siihen on luettavissa riviltä treatmentwater. Vesi näyttäisi antavan keskimäärin millimetriä ravinnekäsittelyä lyhyemmän rairuohokasvuston. Alustan ja käsittelyn yhteisvaikutukset on raportoitu riveillä bedmould2:treatmentwater, bedpaper4:treatmentwater ja bedpaper8:treatmentwater. Yhteisvaikutukset on raportoitu samassa muodossa, jossa ne mallin kaavaan kirjoitettaisiin. Ensin tulee ensimmäisen muuttujan nimi, sitten kaksoispiste ja viimeisenä toisen muuttujan nimi. Parametrien estimaattien alla on kerrottu yhteenvetotietoja mallista. Ensimmäisenä on mallin jäännösvaihtelun määrä, joka näyttäisi olevan Jäännösvaihtelulla on 40 vapausastetta. Mallissa on kahdeksan parametria, joista kukin kuluttaa yhden vapausasteen, joten yhteensä saadaan 48 vapausastetta. Koska aineistossa on 48 havaintoa, tämä täsmää. Mallin selitysasten on mainittu kohdassa Multiple R-Squared, ja näyttää olevan Malli siis selittää noin 53% aineistossa havaitusta vaihtelusta. Mallin F-testisuure, sen vapausateet ja niitä vastaava p-arvo on mainittu alimmalla rivillä. Vaikka yhteisvaikutus ei ollutkaan mallissa merkitsevä, on mahdollisen yhteisvaikutuksen selvittäminen kuitenkin usein oleellista. Niinpä 196

205 R KIELEN PERUSTEET yhteisvaikutuksesta voi mallin tarkastelun lisäksi piirtää kuvio käyttäen komentoa interaction.plot(): >interaction.plot(dat$bed, dat$treatment, xlab="kasvatusalusta", ylab="rairuohon trace.label="käsittely", las=1, lwd=2) dat$day7, pituus", Tuloksena syntyvässä kuvassa alla on vaaka-akselilla esitetty kasvatusalusta ja pystyakselilla rairuohon pituus seitsemäntenä päivänä. Viivat kuvaavat eri käsittelyitä. Jos viivat ovat samanlaiset, eivätkö ainakaan risteä, ei yhteisvaikutusta ole tai se jää pieneksi. Kuvan perusteella yhteisvaikutusta ei näyttäisi esiintyvän, mikä vahvistaa mallin tulkintaa: Mallia vastaava ANOVA-taulukko saadaan jälleen tulostettua komennolla anova(): > anova(fit1) 197

206 TILASTOLLISET TOIMINNOT Analysis of Variance Table Response: day7 Df Sum Sq bed treatment bed:treatment Residuals Signif. codes: 0 *** Mean Sq F value Pr(>F) e-05 *** ** ** 0.01 * ANOVA-taulukossa on vain yksi rivi kutakin mallissa annettua termiä kohden: alustan ja käsittelyn päävaikutukset ja näiden yhteisvaikutus. Taulukossa annetut p-arvot on laskettu tyypin-i neliösummia käyttäen. Tyypin-I neliösummissa kunkin muuttujan merkitsevyys on laskettu ottaen kaikki sitä edeltävät muuttujat huomioon. Tyypin-II ja tyypin-iii neliösummien laskemiseen pitää käyttää laajennuspaketin car tarjoamaa komentoa Anova(). Neliösummien tyyppi voidaan määrittää argumentilla type: > Anova(fit1, type=2) Anova Table (Type II tests) Response: day7 Sum Sq Df bed treatment bed:treatment Residuals Signif. codes: 0 *** F value Pr(>F) e-05 *** ** ** 0.01 * > Anova(fit1, type=3) Anova Table (Type III tests) Response: day7 Sum Sq Df F value Pr(>F) (Intercept) < 2.2e-16 *** bed *** treatment bed:treatment Residuals Signif. codes: 0 *** ** 0.01 * Tyypin-II neliösummat on laskettu vakioimalla kaikkien muiden mallissa olevien muuttujien suhteen, ja tyypin-iii neliösummat siten, että on verrattu mallia, josta muuttuja puuttuu täydelliseen malliin. Riippuen neliösummien laskentatavasta tulosten tulkinta voi muuttua. Esimerkiksi ylläolevassa esimerkissä tyypin-i ja tyypin-iii neliösummat antavat hieman erilaiset tulokset ja johtanevat hieman erilaiseen mallin tulkintaan. 198

207 R KIELEN PERUSTEET Edellä esitettyjen nollamallin ja täydellisen mallin lisäksi, voi olla mielenkiintoista sovittaa aineistoon useita muitakin malleja, ja vertailla niitä keskenään. Sovitetaan seuraavassa kolme lisämallia, joista kaksi sisältävät ainoastaan kasvatusalustan tai käsittelyn päävaikutukset ja yksi molempien päävaikutukset muttei yhteisvaikutusta. Talletetaan nämä mallit objekteiksi nimillä fit2, fit3 ja fit4: >fit2<-lm(day7~bed, data=dat) >fit3<-lm(day7~treatment, data=dat) >fit4<-lm(day7~bed+treatment, data=dat) Kun aineistoon on sovitettu useita erilaisia malleja, voidaan niitä verrata keskenään, ja valita niistä parhaiten aineistoon sopiva. Tätä vaihetta kutsutaan mallin valinnaksi, ja se on esitelty seuraavassa kappaleessa. Mallin valinta Mallin valinnassa pyritään löytämään aineistoon parhaiten sopiva malli. Perinteinen menetelmä mallin valintaan on ollut jonkinlainen askeltava tapa, jossa mallista joko poistetaan tai siihen lisätään automaattisesti yksi muuttuja tai termi kerraallaan, kunnes lopulta saadaan muodostettua jotakin valintaan käytettävää kriteeriä soveltaen kaikkein sopivin malli. Tällaiseen askeltavaan menetelmään sisältyy kuitenkin ongelmia, joista tärkeimpänä lienee, että mallin parametrien estimaatit ja niden merkitsevyysarvot ovat epätarkkoja. Koska useimmiten on olemassa jonkinlainen käsitys mallin muodosta jo ennen tutkimuksen toteuttamista, on parempi käyttää tätä tietoa hyväksi mallin valinnassa. Niinpä askeltavia menetelmiä ei seuraavassa sen tarkemmin käsitellä. Edellä on muodostettu viisi erilaista mallia rairuohon seitsemäntenä päivänä mitatulle pituudelle. Kahden muuttujan perusteella ei enempää erilaisia malleja voitaisi muodostaakaan, jollei esimerkiksi muuttujien neliöitä tai muita muunnoksia oteta huomioon. Näiden mallien joukosta aineistoon parhaiten sopivan mallin valintaan voidaan käyttää esimerkiksi F-testiä tai Akaiken informaatikokriteeriä (AIC). F-testin tapauksessa vertailu on järkevää vain, jos mallit ovat hierarkkisia eli sisäkkäisiä ja niiden sovittamiseen on käytetty samaa aineistoa. Jos aineistossa on puuttuvia havaintoja, tätä voi olla vaikea saavuttaa. AIC:tä käytettäessä on tärkeää huomioida, että malleja voidaan vertailla, vaikkeivat ne olisikaan sisäkkäisiä, mutta vastemuuttujan täytyy olla eri malleissa tismalleen sama. F-testi tehdään komennolla anova(). Sille annetaan kaksi tai useampia mallin sovituksen sisältäviä objekteja. Ne kannattaa luetella 199

208 TILASTOLLISET TOIMINNOT yksinkertaisimmasta monimutkaisimpaan. Tuloksena on taulukko, jossa kutakin mallia on verrattu ensimmäiseen malliin, ja näin kullekin mallille on laskettu p-arvo: > anova(fit0, fit2, fit3, fit4, fit1) Analysis of Variance Table Model Model Model Model Model 1: 2: 3: 4: 5: day7 day7 day7 day7 day7 ~ ~ ~ ~ ~ 1 bed treatment bed + treatment bed * treatment Res.Df RSS Df Sum of Sq F Pr(>F) e-05 *** *** e-05 *** Signif. codes: 0 *** ** 0.01 * Yllä olevassa tulostuksessa kullekin mallille on annettu juokseva numero, jolla se esiintyy myös testitulokset luettelevassa taulukossa. Nollamalliin verrattuna useampi malli näyttäisi olevan yhtä hyvä, joten niitä voidaan vielä verrata keskenään: > anova(fit2, fit3) Analysis of Variance Table Model 1: day7 ~ bed Model 2: day7 ~ treatment Res.Df RSS Df Sum of Sq F Pr(>F) ** --Signif. codes: 0 *** ** 0.01 * > anova(fit2, fit4) Analysis of Variance Table Model 1: day7 ~ bed Model 2: day7 ~ bed + treatment Res.Df RSS Df Sum of Sq F Pr(>F) *** --Signif. codes: 0 *** ** 0.01 *

209 R KIELEN PERUSTEET > anova(fit3, fit4) Analysis of Variance Table Model 1: day7 ~ treatment Model 2: day7 ~ bed + treatment Res.Df RSS Df Sum of Sq F Pr(>F) e-05 *** --Signif. codes: 0 *** ** 0.01 * Mallit 2-4 vaikuttavat kaikki yhtä hyviltä, joten mallin valinnasta ei olisi kovin paljon hyötyä parhaan mallin valinnassa. Lähinnä se sulkee pois muutenkin erärealistisen nollamallin ja täydellisen mallin liian monimutkaisena. AIC:n perusteella mallin valinta tapahtuu samaan tapaan kuin edellä, mutta komento on AIC(): > AIC(fit0, fit2, fit3, fit4, fit1) df AIC fit fit fit fit fit Komento luettelee eri mallien AIC-arvot. Parhaaksi malliksi voidaan katsoa se, jolla on pienin AIC-arvo. Tässä tulisi siis valituksi objektiin fit4 talletettu malli, jossa selittäjinä olivat vain kasvatusalustan ja käsittelyn päävaikutukset. Jos AIC-arvot ovat kovin samanlaisia, ovat mallit samanarvoisia, ja niitä kaikkia kannattaa tarkastella tarkemmin. Usein samanarvoisten mallien rajana pidetään AIC-arvojen eroa, joka on kaksi tai pienempi. Kun mallin valinnalla on löydetty aineistoon parhaiten sopiva malli, pitää malli vielä validoida. Diagnostiikkaa käsitellään seuraavassa kappaleessa. Mallin diagnostiikka Mallin diagnosoinnin tarkoituksena on varmistaa, ettei malli riko menetelmän oletuksia. Yleinen lineaarinen malli olettaa, että muuttujan varianssi on sama kaikilla selittävillä muuttujilla ja niiden yhdistelmillä. Jos näin on, kutsutaan aineistoa homoskedastiseksi, muutoin heteroskedastiseksi. Lisäksi oletetaan, että vastemuuttuja on normaalisti jakautunut. Näiden oletusten paikkansapitävyyttä voidaan tutkia 201

210 TILASTOLLISET TOIMINNOT tarkastelemalla mallin virhetermejä. Oletusten tarkastamiseen tarkoitettu perusdiagnostiikka, joka on hyvin pitkälti graafisiin työkaluihin perustuvaa, voidaan tuottaa seuraavilla komennoilla. Käytetään diagnosointiin AIC-arvoihin perustuvassa mallin valinnassa valittua mallia, joka on talletettu objektiin fit4. >par(mfrow=c(2,2)) >plot(fit4) Kuvioissa on tarkasteltu vakioituja virhetermejä. Vasemmalla ylhäällä olevasta kuvasta voidaan tulkita, onko virhetermien keskiarvo nolla, ja pysyykö niiden varianssi kaikilla vastemuuttujan arvoilla samana. Punainen viiva on virhetermeihin sovitettu siloitekäyrä. Kuvion perusteella ei ole 202

211 R KIELEN PERUSTEET aihetta huoleen. Oikealla ylhäällä oleva kuva on tavanomainen normaalisuuskuvio, ja virhetermien jakauma näyttää varsin normaaliselta. Vasemmalla alhaalla on esitetty virhetermien itseisarvojen neliöjuuri, ja sen tulkinta on pitkälti sama kuin vasemmalla ylhäällä olevan kuvion. Oikealla alhaalla oleva kuva esittää havaintojen vipuvaikutuksia eli sitä, kuinka paljon jotkin muista havainnoista poikkeavat havainnot vetävät regressiosuoraa puoleensa. Tämänkään kuvion perusteella ei aihetta huoleen näyttäisi olevan, vaan aineisto sopii hyvin lineaarisen regression tekemiin oletuksiin. Toisinaan laatikkokuvioiden tarkastelu helpottaa virhetermien hetereskedastisuuden arviointia. Tällöin voidaan piirtää virhetermeistä yksi laatikko kutakin ennustavan muuttujan tasoa kohden. Komennolla resid() on mahdollista erottaa mallin sisältävästä objektista sen virhetermit. Tämän jälkeen laatikkokuvio voidaan pirtää esimerkiksi seuraavasti: > par(mfrow=c(1,2)) > boxplot(resid(fit4)~dat$bed) > boxplot(resid(fit4)~dat$treatment) Tuloksena syntyvässä kuvassa useimmat laatikot ovat hajonnaltaan jokseenkin samanlaisia: Mallin käyttö ennustamiseen 203

212 TILASTOLLISET TOIMINNOT Mallin perusteella voidaan myös ennustaa uusien, ennalta tuntemattomien näytteiden vastemuuttujan arvoja. Ennustaminen tapahtuu luomalla ensin alkuperäisen datan muotoinen taulukko, jossa sarakkeilla on samat nimet kuin siinä taulukossa, jossa olevaan dataan malli on sovitettu. Luodaan taulukko objektiksi dat2, jossa vastemuuttujan arvo on tuntematon, ja siten merkitty puuttuvaksi. Ennustetaan rairuohon pituus, kun kasvatusalusta on mould1 ja käsittely nutrient: >dat2<-data.frame(day7=na, treatment="nutrient") bed="mould1", Tämän jälkeen rairuohon pituuden ennustaminen tapahtuu komennolla predict(). Sille tulee antaa kaksi argumenttia: mallin sovituksen sisältävän objektin nimi sekä ennustettavan aineiston sisältävän taulukkoobjektin nimi: >predict(fit4, dat2) Jos siis kasvatusalusta on mould1 ja käsittely nutrient, on rairuohon pituus arviolta 105 millimetriä. Mallin komponenttien poimiminen Aineistoon sovitetun malli tulokset voidaan poimia sovituksen sisältävästä objektista erikseen sopivilla komennoilla. Aiemmin olemme jo tutustuneet esimerkiksi komentoon resid(), jolla virhetermit saatiin poimittua erilleen. Vastaavia komentoja on muihinkin tarkoituksiin. Parametrien estimaatit voidaan poimia komennolla: >coef(fit4) (Intercept) bedmould bedpaper bedpaper8 treatmentwater Parametrien estimaattien luottamusvälit lasketaan komennolla: >confint(fit4) 204

213 R KIELEN PERUSTEET 2.5 % 97.5 % (Intercept) bedmould bedpaper bedpaper treatmentwater Mallin sovitetut arvo poimitaan komennolla: >fitted(fit4) Mallin uskottavuus ja poikkeama saadaan selville komennoilla: >deviance(fit4) [1] >loglik(fit4) 'log Lik.' (df=6) Mallimatriisi, komennolla: jonka perusteella malli on sovitettu voidaan poimia >model.matrix(fit4) (Intercept) bedmould2 bedpaper4 bedpaper8 treatmentwater Yleistetty lineaarisen malli Yleistetyillä lineaarisilla malleilla voidaan analysoida sellaisia aineistoja, joissa vastemuuttujan jakauma ei ole normaalinen. Seuraavassa käsitellään lyhyesti lukumäärämuuttujille soveltuvaa Poisson-regressiota ja binaarisille vastemuuttujille soveltuvaa logistista regressiota. Molempien sovittamiseen käytetään komentoa glm(). Yleistettyjen lineaaristen mallien käsittelyyn, kuten mallin tulosten 205

214 TILASTOLLISET TOIMINNOT tarkasteluun ja mallin komponenttien poimintaan, soveltuvat useimmat edellä yleisen lineaarisen mallin yhteydessä esitellyt komennot. Yleistettyjen lineaaristen mallien valinta ja validointi on pitkälti samanlaista kuin yleisen lineaarisen mallinkin, joten niitä ei enää erikseen käsitellä tässä yhteydessä. Poisson-regressio Rairuohoaineiston muuttuja germinate mittaa itäneiden siementen lukumäärää kussakin viljelmässä. Koska tämä muuttuja saa vain kokonaislukuja, itäneitten siementen lukumääriä, ei sen mallintamiseen sovellu yleinen lineaarinen malli, vaan on käytettävä yleistettyä lineaarista mallia, joka tarjoaa mahdollisuuden olettaa vastemuuttujan noudattavan lukumäärille soveltuvaa Poisson-jakaumaa. Poisson-regressio sovitetaan aineistoon komennolla glm() käyttäen samalla argumenttia family=poisson. Esimerkiksi itäneiden siementen lukumäärää voitaisiin mallintaa kasvatusalustan ja käsittelyn avulla seuraavasti: >fit1<-glm(germinate~bed*treatment, family=poisson, data=dat) Sovitetun mallin tulokset tulostetaan ruudulle komennolla summary(), aivan kuten yleisen lineaarisen mallin yhteydessä jo toimittiin: >summary(fit1) Call: glm(formula = germinate ~ bed * treatment, family = poisson, data = dat) Deviance Residuals: Min 1Q Median Q Max Coefficients: Estimate Std. Error z value Pr(> z ) (Intercept) <2e-16 *** bedmould bedpaper bedpaper treatmentwater bedmould2:treatmentwater bedpaper4:treatmentwater bedpaper8:treatmentwater Signif. codes: 0 *** ** 0.01 *

215 R KIELEN PERUSTEET (Dispersion parameter for poisson family taken to be 1) Null deviance: Residual deviance: AIC: on 47 on 40 degrees of freedom degrees of freedom Number of Fisher Scoring iterations: 4 Tulosten tulkinta on pitkälti samanlainen kuin yleisen lineaarisen mallin tulkinta. Erona on, että mallille raportoidaan Null deviance, joka on nollamallin poikkeama sekä sovitetun mallin jäännöspoikkeama, Residual deviance. Lisäksi mallille raportoidaan automaattisesti sen AIC-arvo. Poisson-regressiossa on usein ongelma havaintojen yli- tai alihajonta. Karkean arvion tästä saa jakamalla mallin jäännöspoikkeaman sen vapausasteiden määrällä. Jos tulos on suurempi kuin yksi, on aineistossa ylipoikkeamaa, ja jos tulos on pienempi kuin yksi, on kyseessä alipoikkeama. Tässä arvo on /40 = , joten aineistossa tuntuisi olevan alipoikkeamaa. Ali- tai ylihajonta aiheuttaa p-arvojen ja luottamusvälien arviointiin virhettä, joka voidaan korjata käyttämällä mallia sovitettaessa parametrin family=poisson sijaan parametria family=quasipoisson: >fit1<-glm(germinate~bed*treatment, data=dat) >summary(fit1) Call: glm(formula = germinate quasipoisson, data = dat) ~ Deviance Residuals: Min 1Q Median Q bed family=quasipoisson, * treatment, family = Max Coefficients: Estimate Std. Error t value Pr(> t ) (Intercept) <2e-16 *** bedmould * bedpaper * bedpaper treatmentwater bedmould2:treatmentwater bedpaper4:treatmentwater bedpaper8:treatmentwater Signif. codes: 0 *** ** 0.01 * (Dispersion parameter for quasipoisson family taken to be ) 207

216 TILASTOLLISET TOIMINNOT Null deviance: Residual deviance: AIC: NA on 47 on 40 degrees of freedom degrees of freedom Number of Fisher Scoring iterations: 4 Nyt tulokset muuttuivat parametrien merkitsevyyksien osalta jonkin verran, mutta itse parametrien estimaatit pysyivät edelleen samanlaisina. Erityisesti jos aineistossa on ylihajontaa, voidaan Poisson-jakauman sijaan käyttää negatiivista binomiaalista jakaumaa. Se voidaan sovittaa laajennuspaketista MASS löytyvällä komennolla glm.nb(): >fit2<-glm.nb(germinate~bed*treatment, data=dat) >summary(fit2) Call: glm.nb(formula = germinate ~ bed * treatment, data = dat, init.theta = , link = log) Deviance Residuals: Min 1Q Median Q Max Coefficients: Estimate Std. Error z value Pr(> z ) (Intercept) <2e-16 *** bedmould bedpaper bedpaper treatmentwater bedmould2:treatmentwater bedpaper4:treatmentwater bedpaper8:treatmentwater Signif. codes: 0 *** ** 0.01 * (Dispersion parameter for Negative Binomial( ) family taken to be 1) Null deviance: Residual deviance: AIC: on 47 on 40 degrees of freedom degrees of freedom Number of Fisher Scoring iterations: 1 Lukumääriä sisältävien taulukoiden analysointi Poisson-regressiota voidaan soveltaa taulukoiden analysointiin. Aiemmin 208 myös lukumääriä käsiteltiin Turun sisältävien yliopiston

217 R KIELEN PERUSTEET opiskelijavalintoja vuodelta Sama aineisto voidaan analysoida käyttäen Poisson-regressiota ja mallien vertailua seuraavasti. Ideana on verrata mallia, jossa sukupuolen ja valintatuloksen välillä ei ole yhteisvaikutusta sellaiseen malliin, jossa yhteisvaikutus on mukana. Luodaan aluksi aineisto: >utu2<-data.frame(sukupuoli=c("mies", "mies", "nainen", "nainen"), tulos=c("pääsi","hylättiin","pääsi","hylättiin"), lukumäärä=c(761, 1466, 2537, 5648)) >utu2 sukupuoli tulos lukumäärä 1 mies pääsi mies hylättiin nainen pääsi nainen hylättiin 5648 Sovitetaan sen jälkeen mallit tähän aineistoon seuraavasti: >fit1<-glm(lukumäärä~tulos+sukupuoli, family=poisson) >fit2<-glm(lukumäärä~tulos*sukupuoli, family=poisson) data=utu2, data=utu2, Tämän jälkeen malleja verrataan käyttäen Khiin neliötestisuuretta vertaamiseen. Tämä vastaa uskottavuusosamäärätestiä kahden mallin välillä: > anova(fit1, fit2, test="chi") Analysis of Deviance Table Model 1: lukumäärä ~ tulos + sukupuoli Model 2: lukumäärä ~ tulos * sukupuoli Resid. Df Resid. Dev Df Deviance P(> Chi ) ** --Signif. codes: 0 *** ** 0.01 * Tuloksena on sama johtopäätös joka Khiin neliötestin yhteydessä jo tehtiin: sukupuolella näyttäisi olevan tilastollisesti merkitsevä yhteys mahdollisuuteen saada opiskelupaikka. Logistinen regressio Logistista regressiota käytetään paljon esimerkiksi epidemiologiassa, koska siellä monet vastemuuttujat ovat kaksiarvoisia. Logistinen regressio 209

218 TILASTOLLISET TOIMINNOT sovitetaan komennolla glm() käyttämällä argumenttia family=binomial. Rairuohoaineisto ei sisällä yhtään kaksiarvoista vastemuuttujaa, minkä vuoksi käytetään esimerkissä käytetäänkin avaruussukkuloiden Orenkaiden vaurioitumiseen liittyvää aineistoa. Aineistossa on kaksi muuttujaa, tempf, joka kertoo mitatun ulkolämpötilan Fahrenheit-asteina, ja damage, joka ilmoittaa, oliko jokin O-rengas vaurioitunut. Jos muuttuja damage saa arvon 1, on O-renkaan havaittu vaurioituneen. Ladataan ensin aineisto R:ään: >shuttle<-read.table("spaceshu.txt", header=t, skip=4) Tämän jälkeen komennolla: logistinen regressio voidaan sovittaa aineistoon >fit1<-glm(damage~tempf, data=shuttle, family=binomial) Mallin tulos näyttää seuraavalta: > summary(fit1) Call: glm(formula shuttle) = damage ~ Deviance Residuals: Min 1Q Median tempf, family 3Q = binomial, data = Max Coefficients: Estimate Std. Error z value Pr(> z ) (Intercept) tempf * --Signif. codes: 0 *** ** 0.01 * (Dispersion parameter for binomial family taken to be 1) Null deviance: Residual deviance: AIC: on 137 on 136 degrees of freedom degrees of freedom Number of Fisher Scoring iterations: 6 Tulosten tulkinta on esitetty jo edellä yleisen lineaarisen mallin ja Poissonregression yhteydessä. Erona esimerkiksi Poisson-regressioon on, että logistisen regression parametrien estimaatit on esitetty hieman eri skaalalla. Usein parametrin estimaattien on helpompi tulkita, jos sen ensin muuttaa suhdeluvuksi exponentioimalla sen: 210

219 R KIELEN PERUSTEET >exp( ) [1] Toisin sanoen, kun lämpötila kohoaa yhden asteen, pienenee O-renkaan rikkoutumistodennäköisyys noin 11%. Regression tuloksista on mahdollista piirtää kuva, jossa regressio esitetään käyränä. Tämä vaatii kuitenkin hieman vaivaa. Piirretään ensin tavanomainen hajontakuvio, jossa y-arvoihin on lisätty jokin pieni satunnaisluku komennolla jitter(), jotta havainnot erottuisivat kuvassa paremmin toisistaan. >plot(x=shuttle$tempf, y=jitter(shuttle$damage, amount=0.05), ylab="lämpötila", xlab="o-renkaan rikkoutuminen", pch=19, las=1, xlim=c(40, 100)) Ennustetaan tämän jälkeen mallin perusteella vaikkapa 100 lämpötilaarvon vastemuuttujan arvo: >x<-seq(40, 100, length=100) >y<-predict(fit1, data.frame(tempf=x), type="response") Lisätään tämä lopuksi käyräksi hajontakuvaan: >lines(x=x, y=y, lwd=2) 211

220 TILASTOLLISET TOIMINNOT Yleistetty additiivinen malli Edellä on käsitelty malleja, joissa aineistoon on sovitettu suora tai aivan tietynmallinen käyrä. Toisinaan aineistoon olisi kuitenkin tarpeen sovittaa joustavammin ylipäätään jonkinmuotoinen käyrä. Tällainen siloitekäyrä voidaan sovittaa aineistoon monella tapaa. Eräs usein käytetty menetelmä on lowess, jolla esimerkiksi hajontakuvioon voidaan piirtää siloitekäyrä. Ajatusta havainnollistaa ehkä parhaiten esimerkki. Piirretään rairuohoaineiston ensimmäisestä havainnosta kasvukäyrä päiviltä 3-8: >plot(x=3:8, y=as.numeric(dat[1,1:6]), pch=19, xlab="päivä", ylab="pituus", type="b", lwd=2, lty=2) Nyt piteet on yhdistetty hajontakuviossa katkoviivalla käyräksi, joka kuvaa rairuohon kasvua. Kuvaan voidaan lisätä siloitekäyrä, joka ensin lasketaan kuvaan piirretystä aineistosta komennolla lowess(): > lines(lowess(3:8, as.numeric(dat[1,1:6])), lwd=2) Muodostuvassa kuvassa siloitekäyrä on kuvattu yhtenäisellä viivalla: 212

221 R KIELEN PERUSTEET Yleistettyjen additiivisten mallien (GAM) ydinajatuksena on, että jotakin aineiston muuttujaa kuvataan tällaisella aineiston perusteella määräytyvällä käyrällä sen sijaan, että aineistoon sovitettavan käyrän muoto olisi ennalta pakotettu noudattamaan jotakin tiettyä muotoa. Rairuohoaineistosta on Grafiikka-luvussa piirretty kasvatusjärjestelyn muotoon rairuohon pituuksia kuvaava kuva: Kuvan perusteella voidaan ehkä epäillä, että rairuohon pituudet ovat oikeassa ylereunassa lyhyempiä kuin muualla, joten aineistossa voi olla jonkinlainen viljelmän sijaintiin liittyvä spatiaalinen vaikutus. Spatiaalinen vaikutus voitaisiin ottaa huomioon esimerkiksi yleisessä lineaarisessa mallissa lisäämällä malliin viljelmän sijaintitieto. Nämä ovat rairuohoaineistossa nimillä row ja column. Yksinkertainen lineaarinen malli, jossa paikan vaikutusta mallitettaisiin lineaarisesti rivin ja sarakkeen suhteen olisi: >lm(day7~bed+treatment+row*column, data=dat) Tässä mallissa sarakevaikutus tulee merkitseväksi. Toinen vaihtoehto olisi käsitellä sekä saraketta että riviä luokitteluasteikollisena muuttujana, jolloin malli näyttäisi seuraavalat: >lm(day7~bed+treatment+as.factor(row)*as.factor(column), data=dat) 213

222 TILASTOLLISET TOIMINNOT Tämän mallin ongelmana on, ettei sitä voida sovittaa aineistoon, koska havaintoja on liian vähän. Kuvan perusteella kuitenkin vaikuttaa siltä, että spatiaalinen vaikutus on epälineaarinen, ja niinpä mallintamiseen kannattaa ennemmin käyttää GAM-mallia. GAM-mallien sovittamiseen käytetään komentoa gam(), joka on laajennuspaketissa mgcv. Komennolle annetaan jo edellä esiteltyyn tapaan mallin kaava, mutta ne muuttujat, joihin halutaan sovittaa siloitekäyrä, tulee sijoittaa komennon s() sisään. Muodostetaan aluksi vertailukohdaksi sama malli, joka yleisellä lineaarisella mallilla valittiin parhaaksi: >library(mgcv) >fit1.lm<-lm(day7~bed+treatment, data=dat) >fit1.gam<-gam(day7~bed+treatment, data=dat) Jos malleja tarkastellaan komennolla summary(), huomataan että molemmat mallit antavat keskivirhettä myöten samat estimaatit mallin parametreille. GAM osaa siis sovittaa aineistoon myös suoria. Alla on esitetty GAM-mallin tulos: > summary(fit1.gam) Family: gaussian Link function: identity Formula: day7 ~ bed + treatment Parametric coefficients: (Intercept) bedmould2 bedpaper4 bedpaper8 treatmentwater --Signif. codes: Estimate Std. Error t value Pr(> t ) < 2e-16 *** e-05 *** *** 0 *** ** 0.01 * R-sq.(adj) = Deviance explained = 51.3% GCV score = Scale est. = n = 48 Yleisen lineaarisen mallin tulkintaan verrattuna ainoa ero on kahdella viimeisellä rivillä. Mallin selitysaste on mainittu kohdassa Deviance explained, ja se näyttää olevan 51.3%. Viimeisellä rivillä on mallin hyvyyttä mittavia muita parametreja (GVC score ja Scale est.) sekä mallissa käytettyjen havaintojen määrä. GAM-malleista ei ole automattisesti mahdollista piirtää samanlaista 214

223 R KIELEN PERUSTEET diagnostiikkaa sisältävää kuvaa kuin yleisistä ja yleistetyistä lineaarisista malleista, vaan kuvat on luotava yksitellen käsin. Esimerkiksi virhetermejä ja sovitettuja arvoja esittävä kuva voidaan luoda, kun mallista poimitaan ensin erikseen virhetermit ja sovitetut arvot komennoilla resid() ja fitted(), kuten yleisen lineaarisen mallin yhteydessä on tarkemmin selitetty: >plot(x=fitted(fit1.gam), y=resid(fit1.gam)) >lines(lowess(x=fitted(fit1.gam), y=resid(fit1.gam))) Kuvan tulkinta on oleellisesti samanlainen kuin yleisen lineaarisen mallin vastaavat kuvan. GAM-mallia voidaan tästä laajentaa lisäämällä siihen siloitustermejä, siis sellaisia muuttujia, joita mallitetaan siloitekäyrää käyttäen. Nämä termit sijoitetaan mallin kaavassa komennon s() sisään. Komennolle voidaan antaa yksi tai useampia muuttujia kerrallaan. Esimerkiksi edellä esitettyä rivin ja sarakkeen yhteisvaikutuksen sisältävää yleistä lineaarista mallia vastaava GAM-malli olisi: >fit2<-gam(day7~bed+treatment+s(row, column), data=dat) Nyt siloitekäyrä on siis sijoitettu yhtäaikaa sekä rivisarakemuuttujaan, mikä ottaa huomioon niiden yhteisvaikutuksen. 215 että

224 TILASTOLLISET TOIMINNOT Mallin tuloksissa ei ole siloitekäyrille parametrien estimaatteja tai merkitsevyyksiä: >summary(fit2) Family: gaussian Link function: identity Formula: day7 ~ bed + treatment + s(row, column) Parametric coefficients: (Intercept) bedmould2 bedpaper4 bedpaper8 treatmentwater --Signif. codes: Estimate Std. Error t value Pr(> t ) < 2e-16 *** *** ** 0 *** ** 0.01 * Approximate significance of smooth terms: edf Ref.df F p-value s(row,column) R-sq.(adj) = Deviance explained = 77.1% GCV score = Scale est. = n = 48 Jos kuitenkin verrataan mallia, jossa siloitekäyrä on sellaiseen malliin, jossa sitä ei ole, on siloitteen merkitsevyys mahdollista laskea. Mallien vertaaminen onnistuu esimerkiksi uskottavuusosamäärää käyttäen komennolla anova(): > anova(fit1.gam, fit2, test="chisq") Analysis of Deviance Table Model 1: day7 ~ bed + treatment Model 2: day7 ~ bed + treatment + s(row, column) Resid. Df Resid. Dev Df Deviance P(> Chi ) ** --Signif. codes: 0 *** ** 0.01 * Siloitekäyrän tilastollinen merkitsevyys voidaan tulkita tulosteen riviltä 2, jossa se p-arvoksi eli käyrä näyttäisi olevan merkitsevä. Mallin tulos on mahdollista esittää kuvana kahdella eri tavalla. Ensimmäinen tapa on käyttää komentoa plot(), jolloin tuloksena on korkeuskäyrästö mallin siloitekäyrällä arvioimista vaikutuksista: 216

225 R KIELEN PERUSTEET >plot(fit2) Toinen vaihtoehto on käyttää komentoa vis.gam(), jolloin tuloksena on saman kuvan kolmiulotteinen esitys: >vis.gam(fit2) 217

226 TILASTOLLISET TOIMINNOT Lineaarinen sekamalli - pitkittäisaineiston analysointi Edellä on käsitelty vain tilanteita, joissa havainnot ovat toisistaan riippumattomia. Rairuohoaineiston tapauksessa on analysoitu vain seitsemäntenä päivänä tehtyjä pituusmittauksia. Kutakin viljelmää on kuitenkin seurattu kuuden päivän ajan, päivänä 3-8. Jos kaikkien päivien havaintoja haluttaisiin käyttää analyysissä, eivät edellä esitellyt menetelmät sovellu esitettyyn tilanteeseen, vaan on käytettävä jotakin niin sanottua pitkittäisaineiston analysointiin soveltuvaa menetelmää. Eräs pitkittäisaineiston analysointiin soveltuva menetelmä on yleinen lineaarinen sekamalli. Tämä sopii rairuohoaineistolle, sillä rairuon pituudet ovat normaalistijakautuneita, mikä on eräs menetelmän oletuksista. Sekamallin keskeisenä piirteenä on, että jos havainnot ovat toisistaan riippuvaisia, kuten samoista viljelmistä eri päivänä tehdyt havainnot, voidaan tämä riippuvuussuhde huomioida sekamallissa. Muutetaan rairuohoaineisto ensin sellaiseen muotoon, jossa kukin aineiston dat2 sarakkeista vastaa yhtä muuttujaa. Aineistoon tulee muuttujiksi seurantapäivä, rairuohon pituus, kasvatusalusta, käsittely ja viljelmän sijainti: >dat2<-data.frame(paiva=rep(c(3:8), each=48), pituus=c(dat$day3, dat$day4, dat$day5, dat$day6, dat$day7, dat$day8), alusta=rep(dat$bed, 6), kasittely=rep(dat$treatment, 6), rivi=rep(dat$row, 6), sarake=rep(dat$column,6)) Viljelmien kasvu hahmottuu paremmin, jos eri alusta- ja käsittelyyhdistelmien kasvukäyrät piirretään erikseen. Ensin lasketaan kullekin päivälle eri yhdistelmien keskimääräiset pituudet komennolla aggregate(), ja sen jälkeen piirretään kuva komennolla interaction.plot(). Toimenpiteet ovat hieman monimutkaisen näköisiä, joten jos haluaa tietää tarkalleen, mitä esimerkissä tehdään, kannattaa ajaa alla olevat komennot itse R:ssä, ja tutustua komentojen ohjesivuihin huolellisesti. >d<-aggregate(dat2$pituus, list(dat2$paiva, dat2$alusta, dat2$kasittely), mean) >par(mar=c(5,5,2,2)) >interaction.plot(d$group.1, paste(d$group.2, d$group.3, sep=" "), d$x, las=1, xlab="päivä", ylab="pituus", trace.label="viljelmä", lty=c(1,1,2,2,3,3,4,4), lwd=2, col=c(2,2,2,2,4,4,4,4)) Tuloksena syntyvät kuva on esitetty alla. 218

227 R KIELEN PERUSTEET Perinteinen tapa analysoida tällaisia aineistoja on toistomittausten ANOVA (repeated measures ANOVA). Sen voi ajatella sovittavan aineistoon mallin, jossa kutakin alusta-käsittely-yhdistelmää kohden on sovitettu oma malli. Kaikkien näiden mallien kulmakertoimien oletetaan olevan samoja, mutta niiden leikkauspisteiden annetaan vaihdella vapaasti. Tällainen malli voidaan sovittaa aineistoon laajennuspaketin nlme komennolla lme(). Sille annetaan kaksi mallin määrittelevää argumenttia. Argumentti fixed määrittelee mallin muodon ja argumentti random mallin satunnaistermin muodon. Toistomittausten ANOVA:ssa satunnaistermissä esiintyy vain leikkauspiste, joka määräytyy mallitettavan satunnaismuuttujan mukaan, tässä siis päivän. Aineistoon sovitettava malli näyttäisi seuraavalta: >fit1<-lme(fixed=pituus~alusta+kasittely, method="ml", data=dat2) random=~1 paiva, Mallin sovitukseen on käytetty menetelmää ML, mikä mahdollistaa eri mallien vertailun. Kun paras malli on valittu, parametrien estimaatit täytyy estimoida uudelleen käyttäen menetelmänä REML:ää, mistä myöhemmin lisää. Satunnaistermiä ei välttämättä tarvitse käyttää, jos sitä ei voida kovin luotettavasti arvioida. Tällainen tilanne on esimerkiksi silloin, jos 219

228 TILASTOLLISET TOIMINNOT pitkittäisaineistossa on vain muutamia päiviä, tyypillisesti korkeintaan neljä. Silloin sama malli voidaan sovittaa lineaarista regressiota käyttäen käsitellään päivän vaikutusta tavanomaisena päävaikutuksena: >fit2<-lm(pituus~alusta+kasittely+paiva, data=dat2) Jos tätä mallia halutaan verrata sekamalliin esimerkiksi AIC:tä käyttäen, on malli kuitenkin sovitettava komennolla gls(), sillä muutoin mallien AIC ei välttämättä tule lasketuksi samalla tavalla. Huomaa, että tässäkin on käytetty ML-menetelmää: >fit3<-gls(pituus~alusta+kasittely+paiva, data=dat2) method="ml", Edellä sovitetun satunnaisleikkauspistemallin lisäksi voidaan sovittaa malli, joss sekä leikkauspitseen että kulmakertoimen annetaan vaihdella. Tämä tapahtuu lisäämällä argumenttiin random uusi termi. Esimerkiksi malliin voidaa lisätä satunnaiskulmakerroin alustan vaikutukselle seuraavasti: >fit4<-lme(fixed=pituus~alusta+kasittely, paiva, method="ml", control=lmecontrol(returnobject=true)) random=~1+alusta data=dat2, Valitettavasti malli ei tässä konvergoidu (parametreja ei saada estimoitua), jollei käytetä argumenttia control=lmecontrol(returnobject=true), joka pakottaa R:n palauttamaan tuloksen, vaikkei se ehkä olekaan tarkka. Useimmiten tällainen virhetilanne johtuu väärin määritellystä mallista. Rairuohoaineiston kohdalla on kuitenkin kyse jostakin muusta. Mallin tuloksia voidaan tarkastella tavanomaisesti komennolla summary(). Tulokset on esitetty pitkälti samassa muodossa kuin yleistetyn lineaarisen mallin tulokset, mutta mallin selitysaste ja muut siihen liittyvät suureet puuttuvat. Niinpä mallin hyvyyden tarkasteluun voidaan käyttää sen uskottavuutta, poikkeamaa tai AIC:tä, kuten alla on menetelty. > summary(fit1) Linear mixed-effects model fit by REML Data: dat2 AIC BIC loglik Random effects: Formula: ~1 paiva (Intercept) Residual StdDev:

229 R KIELEN PERUSTEET Fixed effects: pituus ~ alusta + kasittely Value Std.Error DF t-value p-value (Intercept) alustamould alustapaper alustapaper kasittelywater Correlation: (Intr) alstm2 alstp4 alstp8 alustamould alustapaper alustapaper kasittelywater Standardized Within-Group Residuals: Min Q1 Med Q Max Number of Observations: 288 Number of Groups: 6 Malleja voidaan verrata toisiinsa samaan tapaan kuin aiemminkin käyttäen esimerkiksi komennolla AIC(): >AIC(fit1, fit3, fit4) df AIC fit fit fit AIC:n perusteella parhaalta mallilta näyttäisi sellainen, jossa on mukana sekä satunnaisleikkauspiste että -kulmakerroin (fit4). Seuraavassa kuitenkin jatketaan ainoastaan mallilla, jossa on satunnaisleikkauspiste, koska laajemman mallin konvergoituminen oli epävarmaa. Kun paras malli on löydetty, sovitetaan se uudelleen menetelmällä REML, jotta parametrien estimaateista saadaan mahdollisimman tarkat: >fit1.1<-lme(fixed=pituus~alusta+kasittely, method="reml", data=dat2) random=~1 paiva, Rairuohoesimerkisämme parametrien estimaateiksi saadaan samat kummallakin menetelmällä, mutta niihin voi syntyä eroja aineistosta riippuen. Parhaan mallin jälkeen pitää malli diagnosoida mahdollisten menetelmän oletusten rikkoutumisten varalta. Aiemmin käytettiin diagnosointii muun muassa virhetermien tarkastelua. Yllä sovitetulle mallille, joka on tallennettu objektiin fit1, voidaan piirtää virhetermikuvio 221

230 TILASTOLLISET TOIMINNOT komennolla >plot(fit1) Kuten yleisen ja yleistetyn lineaarisen mallin tapauksessa, kuviosta tulkitaan mahdollinen virhetermien heteroskedastisuus. Nyt virhetermeissä näkyy selvästi heteroskedastisuutta, sillä virhetermien arvo kasvaa selvästi sovitetun arvon kasvaessa. Tämä voi johtua useasta tekijästä. Ensinnäkin oletus muuttujan jakaumasta voi olla väärä. Rairuohon osalta tosin tiedämme, että pituudet ovat normaalisti jakautuneita, joten siitä ei voi olla kyse. Toiseksi mallista voi voinut jäädä jokin tärkeä termi pois. Tällainen voisi rairuohon tapauksessa olla esimerkiksi viljelmän sijainti koeasetelmassa. Kolmanneksi, on mahdollista, että virhetermien käyttäytyminen johtuu siitä, ettei aineiston korrelaatiorakennetta ole mallinnettu. Korrelaatio voi olla edellä mainitun spatiaalisen korrelaation lisäksi myös ajallista. Neljänneksi, ilmiö voi johtua myös siitä, ettei virhetermien varianssi ole vakioista, ja tilanne tulee korjata mallittamalla virhetermien varianssi sopivasti. Edellä sovitetuissa malleissa ei ole vielä huomioitu ajallista eri mittaustulosten välistä korrelaatiota. Tämä voidaan kuitenkin huomioida käyttäen argumenttia correlation. Erilaisia korrelaatiorakenteen esittämiseen soveltuvia komentoja on useita, ja valinta niiden välillä 222

231 R KIELEN PERUSTEET voidaan tehdä esimerkiksi AIC:n perusteella. Ensiksi sovitetaan malli kutakin korrelaatiorakennetta käyttäen, ja tämän jälkeen käytetään AIC:tä kriteerinä parhaan mallin valitsemiseksi. Sovitetaan esimerkiksi yksi yksinkertainen ajallinen korrelaatiorakenne: >fit5<-lme(fixed=pituus~alusta+kasittely, random=~1 paiva, method="ml", data=dat2, correlation=corar1(form=~1 paiva)) ja yksi spatiaalinen korrelaatiorakenne: >fit6<-lme(fixed=pituus~alusta+kasittely, random=~1 paiva, method="ml", data=dat2, correlation=corlin(form=~rivi+sarake paiva)) Jos nyt verrataan näitä uusia malleja jo aiemmin parhaaksi valittuun käyttäen AIC:tä, havaitaan, että ne sopivat aineistoon alkuperäistä huonommin: > AIC(fit1, fit5, fit6) df AIC fit fit fit Hajontakuviossa havaittu ilmiökään ei näillä mallin muutoksilla korjaannu. Sen sijaan viljelmän sijainti koeasetelmassa parantaa AIC:ta hieman ja tekee virhetermikuviosta paremman, muttei kuitenkaan vielä täydellistä: >fit7<-lme(fixed=pituus~alusta+kasittely+rivi+sarake, random=~1 paiva, method="ml", data=dat2) >AIC(fit7) [1] >plot(fit7) Virhetermikuvio on esitetty seuraavalla sivulla. 223

232 TILASTOLLISET TOIMINNOT Virhetermeissä esiintyy edelleen heteroskedastisuutta, jota voidaan yrittää mallittaa käyttäen havainnoille niiden varianssin perusteella muodostettuja painoja. Tämä tapahtuu käyttäen argumenttia weights, jolle annetaan jokin varianssirakenteen kuvaava komento. Esimerkiksi hyvin yksinkertainen varianssirakenne voidaan sovittaa komennolla varident(): >fit8<-lme(fixed=pituus~alusta+kasittely, random=~1 paiva, method="ml", data=dat2, weights=varident(form=~1 paiva)) Tämän mallin AIC on alkuperäistä mallia huomattavasti pienempi, ja virhetermikuviokin näyttää tämän jälkeen hyväksyttävältä: > AIC(fit8) [1] > plot(fit8) 224

233 R KIELEN PERUSTEET Yhteenvetona edellä esitetyistä mahdollisuuksista sanottakoon, että ensin kannattaa etsiä paras mahdollinen malli, jossa on mukana vain muuttujien pää- ja yhteisvaikutuksia. Kun tällainen malli on löydetty, voidaan siihen tarvittaessa lisätä satunnaistekijöitä, jos koeasetelmassa sellaisia on, sekä spatiaalisia tai ajallisia riippuvuussuhteita kuvaavia korrelaatiorakenteita. Lisäksi aineistossa mahdollisesti esiintyvää hetereskedastisuutta voidaan mallintaa erilaisia varianssirakenteita käyttäen. Tässä esitetty lineaarinen sekamalli soveltuu vain tilanteisiin, joissa vastemuuttuja on normaalisti jakautunut. Jos vastemuuttuja ei ole normaalinen, vaan noudattaa esimerkiksi binomi- tai Poissonjakaumaa, voidaan mallin sovitukseen käyttää laajennuspaketin lmer komentoja lmer() ja glmer(). Samaan tarkoitukseen sopivia työkaluja löytyy myös laajennnuspaketista VGAM, joka tarjoaa additiivisten mallien teoriaan perustuvia menetelmiä. Aikasarja-analyysi Aikasarja-analyysin avulla on mahdollista analysoida esimerkiksi erilaisia toistuvia ilmiöitä tai selvittää, onko aineistosta havaittavissa jonkinlainen 225

234 TILASTOLLISET TOIMINNOT nouseva tai laskeva trendi. Toisinaan trendi hukkuu jaksottaisten ilmiöiden joukkoon, mutta aikasarja-analyysin avulla jaksottaisuus ja trendi voidaan erottaa toisistaan. Aikasarja-analyysin erona edellä esitettyyn pitkittäisaineiston analysointiin on, että aikasarja koostuu tyypillisesti paljon suuremmasta määrästä havaintoja kuin pitkittäisaineisto. Seuraavassa käytetään esimerkkinä Helsingin Kaisaniemen mittausasemalta kerättyä ilman lämpötila-aineistoa, joka kattaa vuodet Sen voi ladata ilmaiseksi Internetistä osoitteesta mutta se on myös ladattavissa tämän kirjan Internet-sivulta. Tiedosto ladataan R:ään komennolla, jossa yksin esiintyvät miinus-merkit merkitään puuttuviksi havainnoiksi: >dat<-read.table("i3_keskilampotilat.txt", sep="\t", na.strings="-", row.names=1) header=t, Tiedostossa on 180 riviä, yksi rivi kutakin vuotta kohden. Kullakin rivillä on 13 saraketta, yksi sarake kunkin kuukauden ja yksi koko vuoden keskilämpötilaa varten. Nimetään jatkokäsittelyn helpottamiseksi vielä vuosilukua osoittava ensimmäinen sarake nimellä vuosi: >colnames(dat)[1]<-"vuosi" Muunnetaan aineisto lopuksi pitkään muotoon, jossa on kolme muuttujaa: vuosi, kuukausi ja keskilämpötila. Tämän voi tehdä komennolla reshape(), mutta yhtä hyvin myös muulla tavoin. Alla on esitetty tapa, jossa luodaan kolme vektoria, joista sitten luodaan datakehikko lampo1: vuosi<-rep(dat$vuosi, 12) kuukausi<-rep(month.name, each=180) lampo<-as.vector(unlist(c(dat[,1:12]))) lampo1<-data.frame(vuosi, kuukausi, lampo) Nyt datakehikossa lampo1 on aineisto esitetty siten, että kunkin kuukauden aineisto on esitetty aina kerrallaan. Ensin ovat kaikkien tammikuiden havainnot, sitten helmikuiden ja niin edelleen, kunnes viimeisenä ovat joulukuun havainnot. Lämpöaikasarja voidaan piirtää hajontakuvioon joko yksittäisiä pisteitä käyttäen (ylempi kuva) tai yhtenäisenä viivana (alempi kuva): par(mfrow=c(2,1), mar=c(3,3,0,0)) plot(lampo1$lampo) plot(lampo1$lampo, type="l") 226

235 R KIELEN PERUSTEET Kuvioissa näkyy hyvin vuoden lämpökäyrä. Tammikuu on kuvioissa vasemmalla, joulukuu oikealla. Lämpimintä keskikesällä, kylmintä talvella. Sama kuva voidaan muodostaa myös tekemällä aineistosta ensin aikasarjamuotoinen objekti, ja piirtämällä siitä sitten kuva: >dats<-ts(c(dat2[,1], dat2[,2], dat2[,3], dat2[,4], dat2[,5], dat2[,6], dat2[,7], dat2[,8], dat2[,9], dat2[,10], dat2[,12], dat2[,12]), start=1829, frequency=12) >plot(dats) Aineiston käsittelyä tietyillä komennoilla helpottaa, jos sen ensin muuttaa muotoon, jossa kaikki havainnot ovat peräkkäin aikajärjestyksessä. Tämä tapahtuu esimerkiksi silmukalla, joka poimii aineistosta rivien kerrallaan, ja liittää ne peräkkäin yhdeksi vektoriksi: >d<-c() >for(i in 1:180){ > d<-c(d, as.numeric(dat2[i,])) >} Vektorissa on muutamia puuttuvia arvoja, jotka häiritsevät aikasarjaanalyysein tekemistä. Ne kannattaa korvata sopivilla arvoilla ennen 227

236 TILASTOLLISET TOIMINNOT jatkoanalyyseja. Seuraavassa puuttuvat arvot korvataan nollilla: >d[is.na(d)]<-0 Muokatusta vektorista voidaan sitten muodostaa aikasarja-muotoinen objekti komennolla: >ds<-ts(d, start=1829, frequency=12) Tällä tapaa muodostetun aikasarjan perusteella on mahdollista piirtää kuva, jossa aika on kuvattu vaaka-akselilla vuodesta 1829 vuoteen 2008: >plot(ds) Yleisen trendin hahmottamista aikasarjasta voi helpottaa lisäämällä siihen vaikkapa lowess-siloitekäyrä: >lines(lowess(x=time(ds), y=d), lwd=2, col="red") Kuvan piirtämisessä apuna käytetty komento time() on näppärä tapa muuttaa aikasarja-muotoinen objekti ajaksi. Siloitekäyrällä varustettu kuva on esitetty alla. Siloitteesta päätelle Helsingin Kaisaniemen keskilämpötila on noussut viimeisten vajaan kahdensadan vuoden aikana tasaisesti. 228

237 R KIELEN PERUSTEET Aikasarjan hajotelma vuodenaikaisvaihteluun, pitkäaikaistrendiin ja jäljellejäävään satunnaisvaihteluun tapahtuu komennolla stl(). Se vaatii kaksi argumenttia, aikasarjaobjektin nimen, sekä vuodenaikaisvaihtelun erottamiseen vaikuttavan argumentin, joka tässä saa arvon periodic. Tallennetaan tulos objektiin stl1, ja piirretään siitä kuva >stl1<-stl(ds, "periodic") >plot(stl1) 229

238 TILASTOLLISET TOIMINNOT Kuvassa ylimpänä on esitetty itse aineisto. Sen alla on kuvattu loesssiloitekäyrää käyttäen aineistosta erotettu vuodenaikaisvaihtelu sekä pitkäaikaistrendi. Alimpana kuvana on satunnaisvaihtelu, joka jää jäljelle, kun vuodenaikaisvaihtelu ja pitkäaikaistrendi on poistettu aineistosta. Aineiston perusteella laskettu autokorrelaatiofunktio saadaan selville komennolla acf(): >acf(ds) Autokorrelaatiofunktio kertoo ajallisesti peräkkäisten havaintojen samankaltaisuudesta. Sen avulla on helppo havaita aineistosta erilaisia toistuvia piirteitä. Esimerkiksi ylläolevassa kuvassa näkyy selkeästi aina kahdentoista havainnon (kuukauden) välein toistuva positiivinen huippu, jota seuraa negatiivinen huippu. Tämä kuvastanee aineiston vuodenaikaisvaihtelua. Vuodenaikausvaihtelua ja pitkäaikaistrendiä voidaan käsitellä myös laskemalla peräkkäisten havaintojen välinen erotus komennolla diff(). Tulos voidaan esittää kuvana, johon on lisätty lowess-siloitekäyrä: >plot(diff(ds)) >lines(lowess(x=time(ds), col="red") y=c(0, diff(ds))), lwd=2, Muodostuvasta kuviosta on helppo huomata, ettei vuodenaikaistrendi 230

239 R KIELEN PERUSTEET pysyy vuodesta toiseen samana, sillä kuviossa ei ole enää lainkaan merkittävää pitkäaikaistrendiä: Komennolla lag.plot() voidaan tutkia korrelaatiota eri aikapisteroilla tarkemmin. Siinä kukin kuvio esittää alkuperäisen aineiston ja tietyn aikapistemäärän välistä suhdetta: > lag.plot(ds, 12) 231

240 TILASTOLLISET TOIMINNOT Varsinainen aikasarjamalli, tässä ARIMA-malli, voidaan sovittaa aineistoon komennolla arima(). Koska esimerkkimme aikasarjassa on voimakasta autokorrelaatiota, joka jatkuu melko pitkään, sille on syytä määritellä melko korkea degree of differencing. Sopivan asteen määrittely käy sovittamalla aineistoon yksinkertainen malli, ja tarkastelemalla sen virhetermejä. Mallin muoto määritellään argumentilla order(). Sovitetaan aineistoon malli, joka aste on 1: >fit1<-arima(ds, order=c(0,1,0)) Sovitettua mallia voidaan tutkia tulostamalla se ruudulle: >fit1 Call: arima(x = ds, order = c(0, 1, 0)) sigma^2 estimated as 25.08: = log likelihood = , aic Mallille on ilmoitettu AIC, jota voidaan periaatteessa käyttää myös aikasarjamallien vertaamiseen. Diagnostinen kuva, josta nähdään suoraan virhetermien jakauma sekä niiden autokorrelaatiofunktio tuotetaan komennolla tsdiag(): >tsdiag(fit1) Koska aineistossa esiintyvä trendi on varsin pieni, sen tulkitseminen 232

241 R KIELEN PERUSTEET virhetermeistä on hiukan vaikeaa, mutta virhetermien autokorrelaatiokuvassa on havaittavissa selkeää jaksottaisuutta sekä korkeita arvoja vielä pitkän ajan kuluttuakin. Kun edellä esitetyt vaiheet toistetaan, havaitaan, että malli: >fit2<-arima(ds, order=c(0,2,0)) antaa jo paremman tuloksen: >tsdiag(fit2) Kun mallin aste on määritetty, pitää seuraavaksi määritellä mallin order. Tähän voi käyttää alustavasti edellä muodostetulle mallille piirrettyä autokorrelaatiokuvaa. Siinä autokorrelaatio on varsin pientä, joten kenties malliin riittäisi pieni order. Aloitetaan alustavasti mallilla, jonka order on 1: >fit3<-arima(ds, order=c(1,2,0)) Mallin diagnostiikkakuvion perusteella on vaikea päätellä, onko malli oleellisesti parantunut, mutta jos verrataan AIC:tä aiempiin malleihin, huomataan, että se on parantunut. Parhaaksi malliksi osoittautuu tähän mennessä: >fit4<-arima(ds, order=c(2,2,0)) Malliin voidaan lisätä myös MA-komponentti, ja seuraava malli vaikuttaa 233

242 TILASTOLLISET TOIMINNOT aiempiin nähden jälleen ylivoimaiselta: >fit5<-arima(ds, order=c(2,2,3)) Sen avulla on päästy miltei kokonaan eroon autokorrelaatiosta. Kun malliin lisätään edellä esitetyllä tavalla myös vuodenaikaisvaihtelu parametrilla seasonal, saadaan lopulta seuraava malli, joka osoittautuu diagnostiikkaa tarkastelemalla varsin hyväksi: >fit6<-arima(ds, seasonal=list(order=c(2,1,0))) >tsdiag(fit6) order=c(2,2,3), Muodostetun mallin perusteella on mahdollista tehdä ennusteita siitä, mihin suuntaan tilanne tulevaisuudessa kehittyy. Tulevaisuuden ennustamiseen käytetään samaa komentoa predict() kuin yleisten lineaaristen mallien yhteydessä käytettiin tuntemattomien havaintojen arvojen estimointiin. Ennustettavien ajanjaksojen lukumäärä määritellään argumentilla n.ahead. Koska aineistossamme oli kussakin vuodessa 12 kuukautta, laadittaisiin esimerkiksi ennuste seuraaville kymmenelle vuodelle seuraavasti: >fit6.f<-predict(fit6, n.ahead=120) Ennuste voidaan piirtää kuvaksi komennolla ts.plot(). Sille annetaan 234

243 R KIELEN PERUSTEET aikasarjaobjektin nimi, ennustetut arvot, jotka löytyvät ennustetun mallin sisältävästä objektista nimellä pred sekä alkuperäisen aikasarjan ja ennusteen värit: >ts.plot(ds, fit6.f$pred, col=c(1,2), lwd=2) Kuvaan voidaan lisätä ennusteen luottamusväli komennoilla: >lines(fit6.f$pred+2*fit6.f$se, col=2, lty=2, lwd=2) >lines(fit6.f$pred-2*fit6.f$se, col=2, lty=2, lwd=2) Tässä tapauksessa luottamusvälien lisääminen tekee kuviosta vaikeasti luettavan, ja alla oleva kuva on esitetty ilman luottamusvälejä: Ennusteen perusteella Helsingin lämpeneminen tulee siis jatkumaan. Ordinaatiomenetelmät Ordinaatiomenetelmillä voidaan esimerkiksi esittää näytteiden tai havaintojen välisiä suhteita. Ordinaatiomenetelmiä ovat esimerkiksi pääkomponenttianalyysi (PCA) ja moniulotteinen skaalaus (MDS ja NMDS). Pääkomponenttianalyysi voidaan käsittää myös menetelmäksi, jossa 235

244 TILASTOLLISET TOIMINNOT aineistossa oleva informaatio pyritään esittämään alkuperäistä pienemmällä määrällä erillisiä muuttujia. Seuraavassa esitellään PCA ja NMDS käyttäen kirjan Analyzing Ecological Data luvun 12 varpusaineistoa, joka on saatavilla Internet-osoitteesta Aineistossa on yli tuhannesta varpusesta tehtyjä ruumiinkokoa kuvastavia mittauksia, jotka on tallennettu seitsemään muuttujaan.. Aineisto voidaan lukea R:ään komennolla: >sparrows<-read.table("sparrows2.txt", header=true, sep="\t") PCA Pääkomponenttianalyysi on yksinkertaisimmillaan todella helppo toteuttaa. Kun aineisto on yhdessä taulukossa, PCA voidaan tehdä käyttämällä taulukon nimeä argumenttina komennossa princomp(): >pr1<-princomp(sparrows) Objekti pr1 sisältää PCA-tuloksen. Ongelmana tässä lähestymistavassa on, että aineisto pitää käsin transloida vähintääkin siten, että kaikilla muuttujilla on sama keskiarvo. Lisäksi mahdollinen skaalaus samaan varianssiin on myös tehtävä käsin. Tämä voidaan kiertää käyttämällä komenton prcomp(), joka on myös numeerisesti komentoa princomp() tarkempi. Komento prcomp() oletusarvoisesti transloi muuttujat samaan keskiarvoon, mutta käyttämällä lisäksi argumentti scale=true, voidaan muuttujat skaalata samaan varianssiin. PCA tehdään esimerkiksi komennolla: >pr2<-prcomp(sparrows, center=true, scale=true) PCA-tuloksen tavanomainen scree-kuvio tuotetaan komennolla: >plot(pr2) Muodostuva kuvio on esitetty alla. 236

245 R KIELEN PERUSTEET Muita PCA-tuloksen tulkintaan tulosobjektin ruudulle: >pr2 Standard deviations: [1] [7] liittyviä tietoja saa, kun tulostaa Rotation: PC1 PC2 PC PC6 PC7 wingcrd flatwing tarsus head culmen nalospi wt wingcrd flatwing tarsus head culmen nalospi wt PC4 PC Tulosteessa on ensin raportoitu pääkomponenttien keskihajonnat, joiden neliöt on esitetty yllä scree-kuviossa. Tämän jälkeen rotatoitujen muuttujien lataukset on esitetty taulukossa., jonka sarakkeet muodostuvat 237

246 TILASTOLLISET TOIMINNOT muuttujien eigenvektoreista. Komennolla summary() saadaan kustakin pääkomponentista tarkempia tietoja: >summary(pr2) Importance of components: PC1 PC2 PC3 PC4 PC5 PC6 PC7 Standard deviation Proportion of Variance Cumulative Proportion Taulukon ensimmäisellä rivillä on raportoitu kunkin pääkomponentin keskihajonta. Keskimmäisellä rivillä on lueteltu kunkin pääkomponentin kokonaisvarianssista selittämä varianssin määrä. Alimmalla rivillä on kumulatiivinen selitetyn varianssin määrä. Rotatoitu aineisto, toisin sanoen itse pääkomponentit, joita voidaan mahdollisesti käyttää jatkoanalyyseissä muuttujina, saadaan erotettua tulosobjektin komponentista x komennolla pr2$x. Pääkomponenttien perusteella voidaan piitää pääkomponenttianalyysistä kuvio, jossa kutakin havainto edustaa yksi piste: >plot(pr2$x[,1], pr2$x[,2], xlab="pc1", ylab="pc2", pch=19) 238

247 R KIELEN PERUSTEET Toinen, hyvin yleinen tapa esittää pääkomponenttianalyysin tulos, on biplot, joka muodostetaan komennolla: >biplot(pr2) Biplot:ssa kutakin havaintoa merkitään yhdellä pisteellä, tai tässä oikeastaan havainnon numerolla. Havaintojen päälle piirretään muuttujat, joita kuvataan tässä punaisilla nuolilla. Edellä esitettyjen kuvien perusteella varpusaineistosta erottuu kaksi ryhmää, jotka voivat vastata esimerkiksi eri kypsyysvaiheessa olevia yksilöitä, eri sukupuoli tai vaikkapa eri alalajeja. Moniulotteinen skaalaus Moniulotteisesta skaalauksesta on monia erilaisia versioita. Pääkoordinaattianalyysiä vastaava metrinen skaalaus toteutetaan komennolla cmdscale(), ja laajennuspaketissa MASS tuleva epämetrinen skaalaus komennolla isomds(). Seuraavassa esitellään vain epämetristä skaalausta. Ennen MDS-analyysiä on havaintojen väliset etäisyydet laskettava jollakin soveltuvalla tavalla. Etäisyytenä voidaan käyttää esimerkiksi 239

248 TILASTOLLISET TOIMINNOT Euklidista etäisyyttää, joka voidaan laskea komennolla dist(). Muodostetaan siis ensin havaintojen etäisyyksistä matriisi objektiin d komennolla: >d<-dist(sparrows) Kun etäisyydet on laskettu, itse MDS-analyysi tehdään komennolla: >mds<-isomds(d) Valitettavasti MDS-analyysi ei osaa toimia sellaisilla havainnoilla, joiden välinen etäisyys on nolla. Jos tällaisia havaintoja esiintyy, ne voidaan poistaa aineistosta ennen etäisyyksien laskemista, tai havaintoihin voidaan lisätä jokin hyvin pieni etäisyys, jotta analyysi saadaan tehtyä. Esimerkiksi varpusaineiston tapauksessa havaintojen 385 ja 386 välinen etäisyys on nolla. Poistetaan havainto 386 aineistosta, ja tehdään analyysi uudelleen: >d<-dist(sparrows[-386,]) >mds<-isomds(d) Ajon jälkeen komento isomds() tulostaa ruudulle lyhyen raportin analyysin kulusta: initial value iter 5 value iter 10 value final value converged Alimmalta riviltä nähdään ensinnäkin, että ajo on konvergoitunut. MDS:n ideana on esittää aineisto alkuperäistä vähäisemmällä muuttujamäärällä. Kun aineistoa sovitetaan pienempää muuttujamäärään, tulee alkuperäisen ja sovitetun aineiston välille väkisinkin eroa. Tätä eroa MDS mittää stressisuureella. Tulostuksesta nähdään, että analyysin valmistuessa lopullinen stressi oli MDS-analyysin tulos voidaan esittää kuvana, jossa kutakin havaintoa esitetään yhdellä pisteellä. Tällainen kuva voidaan piirtää käyttäen MDS:n muodostamia uusia muuttujia, jotka löytyvät tulosobjektin komponentista points. Kuva voidaan piirtää esimerkiksi seuraavasti: >plot(mds$points[,1], mds$point[,2], pch=19, xlab="comp. 1", ylab="comp. 2") Tuloksena syntyvä kuva näyttää seuraavalta: 240

249 R KIELEN PERUSTEET Ekologisten aineistojen analysointi Edellä esitellyillä ordinaatiomenetelmillä voidaan esittää yhden taulukon informaatio tiivistetyssä muodossa tai tutkia havaintojen välisiä suhteita. Ekologiassa tulee kuitenkin usein vastaan tilanne, jossa analysoitavana on aineisto, joka koostuu useista vastemuuttujista ja useista ennustavista muuttujista. Tällaisia aineistoja voidaan toki analysoida esimerkiksi yleistetyillä lineaarisille malleilla, mutta tällöin voidaan ksäitellä vain yhtä vastemuuttujaa kerrallaan. Toinen vaihtoehto olisi käyttää jotakin useiden vastemuuttujien analysointiin soveltuvaa menetelmää, kuten MANOVA:aa, mutta siinä monet ennustavat tekijät jouduttaisiin muuttamaan luokkamuuttujiksi. Niinpä ekologisten analysointiin käytetäänkin usein muita menetelmiä, kuten kanoninen correspondenssianalyysi (CCA) ja redundanssianalyysi (RDA), jotka ovat molemmat rajoitettuja ordinaatiomenetelmiä. RDA:n voidaan katsoa olevan PCA:n laajennus tilanteeseen, jossa on olemassa sekä vaste- että selittäviä muuttujia. Nimitys rajoitettu ordinaatiomenetelmä tuleekin juuri siitä, että analyysissä käytetään myös ennustavia muuttujia. RDA soveltuu erityisesti tilanteeseen, jossa vastemuuttujien, tyypillissti eliöiden lukumäärän tai biomassan, voidaan katsoa muuttuvan lineaarisesti 241

250 TILASTOLLISET TOIMINNOT selittävien muuttujien funktiona. CCA puolestaan soveltuu tilanteeseen, jossa vaste on gaussista eli eliöllä on jokin optimi selittävien muuttujien, tyypillisesti erilaisten ympäristötekijöiden suhteen. Seuraavassa käytetään esimerkkinä Analyzing Ecological Data luvun 13 RIKZ-aineistoa, joka on saatavilla Internet-osoitteesta Aineisto voidaan lukea R:ään komennolla: >rikz<-read.table("rikzgroups.txt", header=true, sep="\t") RDA RDA-analyysiä varten on yksinkertaisinta tehdä kaksi erillistä taulukkoa, joista toinen sisältää vastemuuttujat, tässä siis lajiaineiston, ja toinen selittävät muuttujat, siis ympäristötekijät. Poimitaan siis tarvittavat muuttujat kahdeksi taulukoksi: >lajit<- rikz[,2:5] >ymparisto<-rikz[,7:17] Tämän jälkeen RDA-analyysi voidaan tehdä laajennuspaketin vegan komennolla rda(): >rda1<-rda(x=lajit, Y=ymparisto, scale=t) Toinen vaihtoehto on käyttää kaavamuotoa, joka tarjoaa analyysiä seuraavissa vaiheissa enemmän joustavuutta. Kaavamuotoa käytettäessä kaikki analysoitavat lajimuuttujat on esitettävä yhdessä matriisissa. Toisesta matriisista luetaan selittävät muuttujat, joista kaikki tai vain osaa voidaan käyttää mallissa: >rda2<rda(lajit~angle1+angle2+exposure+salinity+temperature+nap+pen etrability+grainsize+humus+chalk+sorting1, data=ymparisto) Lyhyen yhteenvedon mallin tuloksista saa tulostamalla tulosobjektin ruudulle: >rda2 Call: rda(formula = lajit ~ angle1 + angle2 + exposure + salinity + temperature + NAP + penetrability + grainsize + humus + chalk + sorting1, data = ymparisto) 242

251 R KIELEN PERUSTEET Inertia Rank Total Constrained Unconstrained Inertia is variance Eigenvalues for constrained axes: RDA1 RDA2 RDA3 RDA Eigenvalues for unconstrained axes: PC1 PC2 PC3 PC RDA-tuloksen tulkinta on pitkälti samanlainen kuin PCA-tuloksenkin. Erona on, että RDA:ssa erotellaan rajoittamaton ja rajoitettu inertia toisistaan. Laajempi yhteenveto tuloksista saadaan seuraavalla komennolla, mutta tulostusta ei kuitenkaan tässä tarkastella sen tarkemmin: >summary(rda2) Tulos voidaan kuvantaa biplot:ina komennolla: >plot(rda2) 243

252 TILASTOLLISET TOIMINNOT RDA:ta parempi menetelmä moniin tilanteisiin on CCA, jota voi käyttää, vaikka aineistossa esiintyvät gradientit olisivat lyhyitäkin. Siksi useimmat analyysin vaiheet kuvataan tarkemmin alla CCA-analyysin yhteydessä. CCA CCA-analyysi tehdään samaan tapaan kuin RDA-analyysikin, käyttäen komentoa cca() laajennuspaketista vegan: mutta >cca1<cca(lajit~angle1+angle2+exposure+salinity+temperature+nap+pen etrability+grainsize+humus+chalk+sorting1, data=ymparisto) Ongelmana CCA-analyysissä on, ettei yhdenkään lajiaineiston rivin kokonaissumma saa olla nolla. Niinpä ennen analyysiä tällaiset rivit pitää aineistosta poistaa. Poistetaan seuraavassa tällaiset rivit, ja ajetaan analyysi uudelleen: >lajit2<-lajit[rowsums(lajit)!=0,] >ymparisto2<-ymparisto[rowsums(lajit)!=0,] >cca2<cca(lajit2~angle1+angle2+exposure+salinity+temperature+nap+pe netrability+grainsize+humus+chalk+sorting1, data=ymparisto2) Koko mallin merkitsevyys voidaan testata permutaatiotestillä. Tähän voidaan käyttää komentoa anova(), joka yrittää olla nopea, ja se jatkaa permutaatioiden tekemistä vain niin pitkään kuin on tarpeen. Toinen vaihtoehto on käyttää komentoa permutest(), jolle voidaan suoraan määritellä tehtävien permutaatioiden määrä. Esimerkki kummankin komennon käytöstä on alla. > anova(cca2) Permutation test for cca under reduced model Model: cca(formula = lajit2 ~ angle1 + angle2 + exposure + salinity + temperature + NAP + penetrability + grainsize + humus + chalk + sorting1, data = ymparisto2) Df Chisq F N.Perm Pr(>F) Model Residual

253 R KIELEN PERUSTEET > permutest(cca2, permutations=999) Permutation test for cca Call: cca(formula = lajit2 ~ angle1 + angle2 + exposure + salinity + temperature + NAP + penetrability + grainsize + humus + chalk + sorting1, data = ymparisto2) Permutation test for all constrained eigenvalues Pseudo-F: Significance: Based on 999 permutations under reduced model. Käytännössä molemmilla menetelmillä päädytään useimmiten samaan tulokseen. Esimerkkimme tapauksessa kumpikin testi kertoo, ettei malli kokonaisuutena oli tilastollisesti merkitsevä, sillä mallin p-arvo on yli 0.8. Yksittäisten muuttujien merkitsevyys voidaan myös testata permutaatiotestillä. Tällöin komennolla anova() annetaan ylimääräinen argumentti by="term", jolla kerrotaan, että halutaan testata nimenomaan testata muuttujien merkitsevyyttä: > anova(cca2, by="term") Permutation test for cca under reduced model Terms added sequentially (first to last) Model: cca(formula = lajit2 ~ angle1 + angle2 + exposure + salinity + temperature + NAP + penetrability + grainsize + humus + chalk + sorting1, data = ymparisto2) Df Chisq F N.Perm Pr(>F) angle angle exposure salinity temperature NAP * penetrability grainsize humus chalk sorting Residual Signif. codes: 0 *** ** 0.01 * Testin perusteella ainoastaan muuttuja NAP näyttäisi oleva edes lähellä tilastollista merkitsevyyttä. Muodostetun CCA:n akselien merkitsevyys voidaan testata komennolla 245

254 TILASTOLLISET TOIMINNOT anova() käyttäen argumenttia by="axis": > anova(cca2, by="axis") Permutation test for cca under reduced model Model: cca(formula = lajit2 ~ angle1 + angle2 + exposure + salinity + temperature + NAP + penetrability + grainsize + humus + chalk + sorting1, data = ymparisto2) Df Chisq F N.Perm Pr(>F) CCA CCA CCA Residual Perinteisesti analyyseihin käytetty kaupallinen ohjelmisto Canoco käyttää permutaatiotesteissä 999 toistoa. Tämä saadaan R:ssä toteutettua komennoilla: >anova(cca2,step=1000) >anova(cca2, by="terms", step=1000) >anova(cca2, by="axis", step=1000) Edellä on havaittu, että malli ei ole merkitsevä, ja suurin osa siinä mukana olevista muuttujistakaan ei saavuta tilastollista merkitsevyyttä. Mallin parantamiseksi voi olla tarpeen tehdä mallin valintaa. Mallin valinta toimii siten, että sovitetaan malli, ja tarkastellaan sen merkitsevyyttä edellä esitetyillä tavoilla. Tavoittena on muodostaa malli, jossa on vain muutamia ympäristötekijöitä selittäjinä. Jos selittäjiä on kovin paljon, on malli varsin samanlainen kuin rajoittamaton malli. Mallin valintaan on myös automaattinen keino, joka esitetään tässä, mutta mallin valinta on parasta tehdä käyttäen biologista tietämystä apuna. Automaattista mallin valintaa varten meillä on jo olemassa täydellinen malli, jossa ovat mukana kaikki mitatut muuttujat. Tämä on objektissa cca2. Mallin valintaa varten tarvitaan lisäksi nollamalli, josta lähdetään liikkelle. Tämä voi esimerkiksi olla todellinen nollamalli, jossa ei ole yhtää selittävää muuttujaa: >cca0<-cca(lajit2~1, data=ymparisto2) Nyt mallin automaattinen valinta voidaan tehdä komennolla step(). Sille annetaan argumenteiksi nollamalli, täydellinen malli ja mallien vertailuperusta, joka tässä on permutaatiotestaus: >cca1<-step(cca0, scope=formula(cca2), test="perm") 246

255 R KIELEN PERUSTEET Mallin automaattinen valinta tallentaa objektiin cca1 parhaaksi katsomansa mallin: > cca1 Call: cca(formula = lajit2 ~ NAP + sorting1 + grainsize, data = ymparisto2) Inertia Rank Total Constrained Unconstrained Inertia is mean squared contingency coefficient Eigenvalues for constrained axes: CCA1 CCA2 CCA Eigenvalues for unconstrained axes: CA1 CA2 CA Parhaaksi valittu malli voi silti olla kokonaisuutena saavuttamatta tilastollista merkitsevyyttä: > anova(cca1) Permutation test for cca under reduced model Model: cca(formula = lajit2 ~ NAP + sorting1 + grainsize, data = ymparisto2) Df Chisq F N.Perm Pr(>F) Model Residual Signif. codes: 0 *** ** 0.01 * Mallin valinta voidaan tehdä myös toisinpäin, aloittaen laajimmasta mallista ja edeten yksinkertaisempaan päin: >cca1<-step(cca0, scope=list(lower=formula(cca0), upper=formula(cca2)), test="perm") Tuloksena muodostuva malli voi olla erilainen kuin aiemmin muodostettu, mutta tässä molemmilla menetelmillä päädytään samaan tulokseen. Parhaan mallin valinnan jälkeen voidaan tulos esittää kuviona. Seuraavassa käytetään siis objektiin cca1 tallennettua parasta mallia. Kuviossa voidaan havaintojen pisteet (site scores) esittää joko käyttäen 247

256 TILASTOLLISET TOIMINNOT rajoittavien muuttujien lineaarikombinaatioita (lc) tai lajipisteiden (species scores) painotettuja keskiarvoja (wa). Nämä arvot ovat mahdollisimman lähellä toisiaan, ja niiden painotettua korrelaatiota kutsutaan lajiympäristö-korrelaatioksi. Se voidaan laskea komennolla: > spenvcor(cca1) CCA1 CCA2 CCA Biplot-kuviossa nuolet voidaan sovittaa parhaalla mahdollisella tavalla havaintopisteisiin (scaling=1) tai lajipisteisiin (scaling=1). Nuolien esittämisessä on ongelmana se, että jos eliön vaste suhteessa ympäristötekijään ei olekaan oletusten mukainen, on kuvassa esitetty tulos ainakin jonkin verran väärä. Biplot:n nuoliesityksen tekemä oletus siitä, että vaste on lineaarista voidaan selvittää seuraavilla komennoilla, jotka tekevät analyysin muuttujalle NAP: >plot(cca1, display=c("bp", "lc", "wa")) >ef<-with(ymparisto2, ordisurf(cca1, NAP, add=true)) display="lc", Jos kuvantamiseen liittyvä oletus täyttyy, ovat kuvaan punaisella piirretyt viivat valittua muuttujaa, tässä siis NAP:ia, kuvaavaa nulta vasten 248

257 R KIELEN PERUSTEET kohtisuorassa. Kuvan perusteella näyttäisi siltä, ettei oletus täyty. Itseasiassa oletus ei näyttäisi täyttyvän yhdenkään muuttujan kohdalla, koska punaiset viivat kaikkien nuolten suhteen ainakin jossakin määrin "käyräisiä". Tällaisessa tilanteessa ympäristötekijöiden ja lajien välinen suhde olisi parempi esittää vastepintana, joka voidaan muodostaa esimerkiksi muuttujien NAP ja sorting1 suhteen vaikkapa seuraavasti: >plot(cca1, display=c("bp", "lc", "wa")) >ef<-with(ymparisto2, ordisurf(cca1, NAP, add=true)) >with(ymparisto2, ordisurf(cca1, sorting1, add=true, col="green")) display="lc", display="lc", Tuloksena on alla esitetty kuva, jossa muuttujan NAP vastepinta on esitetty punaisella käyrästöllä ja muuttujan sorting1 vihreällä käyrästöllä. Vaikka ympäristötekijöiden ja lajimuuttujien välinen suhde olisikin tällä tapaa epälineaarinen, on useimmiten kuitenkin tapana esittää tulokset biplot:na. Siihen on useimmiten tapana sijoittaa lajimuuttujat sekä niitä vastaavat nuolet. Tällainen kuvio voidaan R:ssä tuottaa komennolla: >plot(cca1, display=c("bp", "sp")) 249

258 TILASTOLLISET TOIMINNOT Kuvassa voidaan lisäksi esimerkiksi komennolla: esittää kukin havainto omana pisteenään, >plot(cca1, display=c("bp", "sp", "lc")) Tämä vastaa kaupallisen Canoco-ohjelman tapaa esittää tulokset. Kuvio on esitetty alla. Kuvio ei ole kovin komea, mutta se voidaan muodostaa vaihe vaiheelta siten, että kussakin vaiheessa lisättävien kuvion komponenttien kokoon ja väriin voidaan vaikuttaa. Tehdään sama kuva, mutta hieman kauniimpana yksittäisiä komponentteja lisäten. Kunkin komennon tarkoitus selviää parhaiten, kun niitä kokeilee itse yksi kerrallaan seuraten kuvassa tapahtuvia muutoksia. >plot(cca1, display=c("bp", "sp", "wa"), type="n") >points(cca1, display="sites", pch=19) >text(cca1, display="species", cex=0.75) >points(cca1, display="bp", col="black", lwd=2) >text(cca1, display="bp", cex=1) >title("cca for RIKZ data") 250

259 R KIELEN PERUSTEET Edellä esitetyillä komennoilla piirretty kuva on esitetty alla. Tiedonlouhinta ja monimuuttujamenetelmät Tiedonlouhinnassa käytettävät menetelmät ovat pitkälti samoja kuin perinteiset monimuuttujamenetelmät. Seuraavassa esitellään kaksi laajaa tiedonlouhintamenetelmien ryhmää, ryhmittelyanalyysi ja erotteluanalyysi. Kumpikin aihe yksinäänkin on varsin laaja, joten molemmista ryhmistä on valittu vain menetelmä tai pari, jota tarkastellaan tarkemmin. Ryhmittelyanalyysin tarkoituksena on ryhmitellä havainnot tai muuttujat siten, että samankaltaisimmat sijoitetaan yhteen ja erilaisemmat niistä erilleen. Ryhmittelyanalyysi voidaan toteuttaa joko hierarkkisena, jolloin tuloksena on puukaavio tai epähierarkkisena, jolloin tuloksena on vain havaintojen tai muuttujien ryhmittely eri ryhmiin. Seuraavissa esimerkeissä käytetään jo aiemmin esiteltyä varpusaineistoa, johon on lisätty uudeksi muuttujaksi varpusalalajin koodi. Tämä aineisto luetaan R:ään komennolla: >sparrows<-read.table("sparrows.txt", header=t, sep="\t") 251

260 TILASTOLLISET TOIMINNOT Hierarkkinen ryhmittelyanalyysi Hierarkkinen ryhmittelyanalyysi tehdään kahdessa vaiheessa. Ensin lasketaan havaintojen ja/tai muuttujien väliset etäisyydet jotakin sopivaa etäisyysmittaa käyttäen. Seuraavassa esimerkissä etäisyydet lasketaan Euklidista etäisyyttä käyttäen, mutta muitakin mittoja voidaan käyttää. Esimerkiksi korrelaatiokertoimeen perustuvat mitat 1-korrelaatio ja 1korrelaation neliö ovat varsinkin yhteiskuntatieteellisissä sovelluksissa usein käytettyjä. Kun etäisyydet on saatu laskettua, piirretään niiden perusteella puu jotakin menetelmää käyttäen. Seuraavassa piirretään puu UPGMA- eli average linkage menetelmällä. Lasketaan aluksi havaintojen väliset etäisyydet komennolla dist(): >d<-dist(sparrows[,4:10], method= euclidean ) Tämän jälkeen itse puu voidaan muodostaa komennolla hclust(): >hc<-hclust(d, method= average ) Vastaavaan tapaan muuttujien transponoidusta matriisista: ryhmittelyanalyysi voidaan tehdä >d2<-dist(t(sparrows[,4:10]), method= euclidean ) >hc<-hclust(d2, method= average ) Ryhmittelyanalyysin tulosta on järkevintä tarkastella puuna, joka voidaan yksinkertaisimmillaan tuottaa komennolla: >plot(hc2) Kuvassa samankaltaisimmat muuttujat on sijoitettu yhteen. Esimerkiksi 252

261 R KIELEN PERUSTEET culmen ja nalospi, jotkaovat molemmat nokan kokoa mittaavia muuttujia ovat keskenään kaikkein samankaltaisimmat. Korrelaatiokertoimen käyttö ryhmittelyanalyysissä tapahtuu laskemalla ensin aineiston perusteella esimerkiksi Pearsonin korrelaatiokertoimet sisältävä matriisi: >cors<-cor(sparrows[,4:10]) Tämä voidaan muuttaa etäisyysmatriisiksi esimerkiksi komennolla: >cors<-1-cors Lopuksi matriision muutettava dist-muotoiseksi objektiksi komennolla: >corsd<-as.dist(cors) Tämän jälkeen puu voidaan muodostaa kuten edellä on esitetty komennolla hclust(). Toinen tapa tehdä ja kuvantaa ryhmittelyanalyysi on lämpökarttaa käyttäen. Siinä esitetään niin sanottu kaksisuuntainen ryhmittely eli muuttujien ja havaintojen puukaaviot on esitetty samassa kuviossa. Lämpökartta muodostetaan komennolla heatmap(): >heatmap(as.matrix(sparrows[,4:10])) Aineiston pitää olla matriisissa, datakehikko ei kelpaa, joten se on muunnettu sopivaan muotoon komennolla as.matrix(). Oletusasetuksilla tuotettu lämpökartta ei useinkaan vastaa sitä, mitä lähdettiin hakemaan. Oletusarvoisesti lämpökartta nimittäin skaalaan kaikki rivit samaan keskiarvoon, mutta useimmiten on ainakin aluksi järkevää tarkastella aineiston arvoja sellaisenaan. Skaalaus käännetään pois päältä argumentilla scale= none. Lisäksi rivinimet voi ollatarpeen kääntää pois päältä, koska ne vain muodostavat mustan palkin kuvioon oikeaan laitaan, jos havaintoja on enemmän kuin muutamiakymmeniä. Tämä voidaan tehdä argumentilla labrow=. Jos havainnot kuuluvat eri ryhmiin, kuten tässä kahteen eri alalajiin, voidaan tämä merkitä kuvioon väripalkilla käyttäen argumenttia RowSideColors. Sille pitää antaa tekstimuotoinen vektori, joka sisältää käytetävien värien nimet. Varpusaineistolle tällainen vektori voidaan tehdä uudelleenkoodaamalla muuttuja Species: >cols<-ifelse(sparrows$species==0, black, red ) Tämän jälkeen lämpökartta voidaan piirtää komennolla: 253

262 TILASTOLLISET TOIMINNOT >heatmap(as.matrix(sparrows[,4:10]), scale="none", labrow="", RowSideColors=cols) Tuloksena on seuraava kuvio: Hierarkkisen ryhmittelyanalyysin tuloksen luotettavuuden arviointiin voidaan käyttää bootstrapping-menetelmää. Vaikka analyysi on helppo toteuttaa ohjelmoimalla käyttäen komentoa sample(), löytyy bootstrapping-menetelmästä valmis sovellus laajennuspaketista pvclust. Paketin komennolla pvclust() voidaan tehdä bootstrapping analyysi käyttäen sataa toistoa seuraavasti: >hcb<-pvclust(sparrows[,4:10], method.dist="euclidean", method.hclust="average", nboot=100, r=1) Bootstrapping-analyysissä on käytettävä samoja etäisyys- ja puun koostamismenetelmiä kuin alkuperäistä puuta muodostettaessa. Tulos on mahdollista esittää puun muodossa komennolla: >plot(hcb) Puun kuhunkin haaraan on merkitty sen luotettavuus vihreillä bootstrapping-arvoilla sekä punaisilla arviolta harhattomilla p-arvoilla. Kumpienkin tulkinta on luottamusväliä vastaava eli jos arvo ylittää 0.95, voidaan puun sen haaran tulkita olevan aineiston perusteella varsin hyvin tuettu. Puu on esitetty alla 254

263 R KIELEN PERUSTEET Epähierarkkinen K-means -ryhmittelyanalyysi Epähierarkkisessa ryhmittelyanalyysissä, kuten seuravassa esiteltävässä Kmeans:ssä, aineisto jaetaan tyypillisesti ennalta määrättyyn määrään erilaisia ryhmiä. K-means-menetelmän nimi tuleekin juuri siitä, että aineiston lisäksi sille pitää antaa muodostettavien ryhmien lukumäärä. K-means:n ongelmana on, että tulos voi muuttua ajokerrasta toiseen. Siinä missä hierarkkinen ryhmittelyanalyysi antaa samoilla asetuksilla samalle aineistolle aina saman puun, K-means ei välttämättä anna aina samaa tulosta. Niinpä onkin tarpeen ajaa K-means useita kertoja samalle aineistolle, ja valita tuloksista paras. Paras tulos voidaan valita esimerkiksi käyttäen ryhmien sisäisen varianssin mittaa (within SS) apuna. Tavoitteena on saavuttaa tasapaino ryhmittelyn ja jäljellejäävän varianssin välillä. K-means ryhmittelyanalyysi tehdään komennolla kmeans(). Sille on tarpeen antaa kaksi parametria, ryhmiteltävä aineisto ja ryhmien lukumäärä. Tehdään varpusaineistolle alustavasti kymmenen ryhmää komennolla: 255

264 TILASTOLLISET TOIMINNOT >km10<-kmeans(sparrows[,4:10], 10) Tuloksen kunkin ryhmän within SS saadaan selville komennolla: >km1$withinss [1] [7] Yleensä analyysin hyvyyden arviointiin käytetään näiden summaa: >sum(km1$withinss) [1] Nyt aineistolle on ajettu yksi K-means -analyysi, mutta parhaan tuloksen löytämiseksi voi olla tarpeen ajaa analyysi aineistolle useita kertoja. Tämä on helpointa toteuttaa käyttämällä argumenttia nstart, jolle annetaan tehtävien analyysien lukumäärä. Esimerkiksi sata analyysiä tehtäisiin komennolla: >km2<-kmeans(sparrows[,4:10], 10, nstart=100) Näin löydetyn tuloksen within SS on aiempaa pienempi: > sum(km2$withinss) [1] Ennen varsinaisen tekemistä olisi tarpeen selvittää, mikä on oikea analyysissä käytettävien ryhmien määrä. Seuraava komentojono tekee Kmeans -analyysi käyttäen ryhmää, ja piirtää tuloksista kuvan, johon ryhmien määrän valinnassa voidaan tukeutua: >km<-rep(na, 99) >for(i in 2:100) { >km[i]<-sum(kmeans(sparrows, nstart=10)$withinss) >} i, iter.max=20000, Analyysin tulos voidaan esittää kuvana seuraavalla komennolla: >par(mar=c(5,5,0,0)) >plot(1:100, km, type="l", xlab="ryhmien lukumäärä") 256 lwd=2, ylab="within SS",

265 R KIELEN PERUSTEET Kuvion perusteella sopivin ryhmien lukumäärä olisi jossakin kymmenen ja kahdenkymmenen välillä. Jatketaan siis edellä muodostetun kymmenen ryhmää sisältävän tuloksen perusteella. K-means ryhmittelyanalyysin tulos voidaan kuvantaan käyttäen hajontakuviota tai rinnakkaiskoordinaattikuviota. Rinnakkaiskoordinaattikuvio voidaan piirtää seuraavalla komentojonolla: >k<-c(10) >max.dat<-max(sparrows[,4:10]) >min.dat<-min(sparrows[,4:10]) >par(mfrow=c(4,3), mar=c(2,4,2,0)) >for(i in 1:k) { >matplot(t(sparrows[km2$cluster==i,4:10]), type="l", main=paste("ryhmä:", i), ylab="mittaustulos", col=1, lty=1, ylim=c(min.dat, max.dat)) >} 257

266 TILASTOLLISET TOIMINNOT Rinnakkaiskoordinaattikuviossa kukin ryhmä on esitetty erikseen omana ryhmänään. Kunkin ryhmän rinnakkaiskoordinaattikuviossa kutakin havaintoa vastaa yksi viiva. Hajontakuvio voidaan vastaavasti tuottaa vaikkapa muuttujien culmen ja nalospi suhteen seuraavasti. Sijoitetaan ensin hajontakuvioon alkuperäiset muuttujat, ja sitten niiden päälle samojen muuttujien Kmeans -analyysistä ryhmien keskiarvot. Tämä tapahtuu seuraavilla komennoilla: >par(mar=c(4,4,0,0)) >plot(x=sparrows$culmen, y=sparrows$nalospi, pch=19, xlab="culmen",ylab="nalospi") >points(x=km2$centers[,"culmen"], y=km2$centers[,"nalospi"], pch="*", col="red") Tuloksena olevassa kuvassa kunkin ryhmän keskiarvoa edustaa yksi punainen tähti: 258

267 R KIELEN PERUSTEET Erotteluanalyysi Erotteluanalyysin tarkoituksena on pyrkiä erottelemaan jo tunnetut ryhmät toisistaan joidenkin muuttujien perusteella mahdollisimman hyvin. Tiedonlouhinnassa tähän tarkoitukseen voidaan käyttää muun muassa diskriminattianalyysiä, Bayes- tai neuroverkkoa, lähimmän naapurin menetelmää tai supprt vectormachine:ä (SVM). Näistä seuraavassa esitellään kuitenkin vain diskriminanttianalyysi, ja siitäkin vain sen lineaarinen muoto. Lineaarinen diskriminanttianalyysi eli erotteluanalyysi tehdään laajennuspaketin MASS komennolla lda(). Se vaatii kaksi argumenttia, vastemuuttujan ja selittävät muuttujat kaavan muodossa sekä käytettävän aineiston: >sparrows.lda<-sparrows[,c(1, 4:10)] >lda1<-lda(species~., data=sparrows.lda) Tulosobjekti lda1 sisältää nyt mallin tiedot: 259

268 TILASTOLLISET TOIMINNOT > lda1 Call: lda(species ~., data = sparrows.lda) Prior probabilities of groups: Group means: wingcrd flatwing tarsus head culmen nalospi wt Coefficients of linear discriminants: LD1 wingcrd flatwing tarsus head culmen nalospi wt Tuloksessa on ensin lueteltu kunkin ryhmän frekvenssi aineistossa, eri muuttujien keskiarvot kummassakin ryhmässä, ja lopuksi erotteluanalyysin tulos (LD1). Erotteluanalyysin tuloksen tarkkuutta voidaan arvioida ennustamalla aineiston kuuluminen eri luokkiin analyysin tuloksen perusteella.ennustus voidaan tehdä komennolla: >lda1.pred<-predict(lda1, sparrows.lda)$class Objektiin lda1.pred on tallennettu kunkinhavainnon ennustettu luokka. Ennustettujen ja tunnettujen luokkien perusteella voidaan muodostaan niin sanottu confusion matrix, josta nähdään kuinka hyvin luokka pystytään ennustamaan oikein: >table(lda1.pred, sparrows.lda$species) Suurin osa havainnoista on siis ennustamiseen käytettyjen muuttujien perusteella voitu ennustaa oikein. Vain kahdeksan havaintoa on ennusteessa sijoitettu väärään luokkaan. Todellisuudessa tämä on varmastikin paha yliarvio siitä, miten hyvin luokka voidaan todellisuudessa ennustaa. Oikeampiarvio saataisiin käyttämällä jotakin ristiinvalidointimenetelmää, joista myöhemmin lisää. 260

269 R KIELEN PERUSTEET Erotteluanalyysin tulos voidaan kuvantaa esimerkiksi laajennuspaketin klar komennolla partimat(). Sillä on helppo tuottaa kahden muuttujan erotteluanalyysituloksista kuvio. Esimerkiksi muuttujien culmen ja nalospi kuvio voidaan tuottaa komennolla: >library(klar) > partimat(as.factor(species)~culmen+nalospi,data=sparrows.lda) Kuviossa eri ryhmiä on esitetty eri numeroilla (0 ja 1). Mustat numerot merkitsevät oikein ennustettuja havaintoja, ja punaiset väärin ennustettuja havaintoja. Ryhmien keskiarvot on merkitty kuvioon mustilla täplillä. Sinisen ja punaisen taustavärin reuna vastaa lineaarista erottelufunktiota. Otsikossa on mainittu ennustevirhe, joka tässä tapauksessa näyttää olevan CART-analyysi Classification and regression trees (CART) -analyysi muodostaa puurakenteen, jonka perusteella näytteet voidaan luokitella, jos kyseessä 261

270 TILASTOLLISET TOIMINNOT on luokitteluasteikollinen vastemuuttuja. Puu muodostetaan laajennuspaketin rpart komennolla rpart(). Komentoi toimii samaan tapaan kuin edellä erotteluanalyysin yhteydessä esitelty lda(): >sparrows.lda<-sparrows[,c(1, 4:10)] >library(rpart) >fit1<-rpart(species~.,data=sparrows.lda, method="class") Kun analyysi on tehty, on puu katkaistava sellaiselta kohtaa, että ylisovituksen ongelmilta vältytään. Analyysin yhteydessä tehdään automaattisesti ristiinvalidointi, jonka perusteella puun katkaisukohta voidaan valita. Ristiinvalidoinnin tulos voidaan kuvantaa komennolla: >plotcp(fit1) Kuviossa vaaka-akselilla on parametrin cp arvo, ja pystyakselilla ristiinvalidoinnilla lasketun virheen arvo. Puu voidaan katkaista sellaiselta kohdalta, että virhe on pienin mahdollinen. Tässä pienin mahdollinen virhe saadaan käyttäen kokonaista puuta, jota vastaa ylläolevan käyrän äärioikealla oleva piste. Katkaistaan kuitenkin seuraavassa puu jo ennen tätä, esimerkiksi kohdasta, jossa cp-arvo on Tämä tapahtuu 262

271 R KIELEN PERUSTEET komennolla prune: >fit1p<-prune(fit1, cp=0.020) Tämän jälkeen puu teksteineen piirretään kahdessa vaiheessa: > plot(fit1p, margin=0.1) > text(fit1p, cex=0.75, use.n=true) Muodostuva puu on esitetty alla. Kussakin puun haarassa on esitetty sääntö, jolla päädytään sen alla olevaan vasempaan haaraan. Alimpana olevien haarojen päissä on esitetty siihen haaraan kuuluvien havaintojen kuuluminen eri luokkiin. Esimerkiksi äärivasemmalla esitetyn haaran päässä on merkintä 896/4, mikä tarkoittaa, että sitä edeltävien sääntöjen perusteella tähän haaraan kuuluvista havainnoista 896 kuuluu luokkaan 0 ja 4 luokkaan 1. Tulos voidaan esittää esimerkiksi kahden muuttujan suhteen samaan tapaan kuin LDA-analyysin tulos: >partimat(as.factor(species)~culmen+nalospi, data=sparrows.lda, method="rpart") 263

272 TILASTOLLISET TOIMINNOT Kuvion tulkinta on samanlainen kuin LDA-analyysinkin. Random Forest Edellä esitellyn CART-analyysin laajennuksena voidaan pitää random forest-menetelmää, jonka tarkoituksena on tarkentaa CART-analyysin tulosta yhdistämällä menetelmään sellaisia uusia piirteitä kuin boosting ja bagging. Ajatuksellisesti random forest on siis samanlaisiin puurakenteisiin perustuva kuin CART:kin, mutta siinä sellaisia menetelmällisiä piirteitä, joita CART:ssa ei ole. Random forest analyysi tehdään laajennuspaketin randomforest komennolla randomforest(). Seuraavassa käytetään samaa aineistoa kuin CART-analyysissä. >library(randomforest) >fit2<-randomforest(as.factor(species)~., importance=true, proximity=true) Tulos voidaan tulostaa ruudulle: 264 data=sparrows.lda,

273 R KIELEN PERUSTEET >fit2 Call: randomforest(formula = as.factor(species) ~., data sparrows.lda, importance = TRUE, proximity = TRUE) Type of random forest: classification Number of trees: 500 No. of variables tried at each split: 2 OOB estimate of Confusion matrix: 0 1 class.error = error rate: 0.58% Tuloksessa on kerrottu analyysissä käytetyt asetukset, keskimääräinen ennustevirhe (0.58%) sekä luokittelumatriisi (confusion matrix). Kunkin muuttujan merkittävyysindeksi voidaan esittää kuvana komennolla: > varimpplot(fit2) Kuvan perusteella, käytettiinpä kumpaa tahansa indeksiä, tarkkuuttatai Giniä, tärkeimmät muuttujat ovat head, culmen, nalospi ja tarsus. Edellä muodotetussa tuloksessa on 500 erillistä puuta. Yksittäisen puun 265

274 TILASTOLLISET TOIMINNOT voi erottaa tuloksesta komennolla gettree(), jonka ensimmäinen argumentti on random forest -analyysin tuloksen sisältävä objekti, ja toinen irrotettavan puun numero. >gettree(fit2, 1) Simulointi Simuloinnilla tarkoitetaan prosessia, jossa luodaan uusi aineisto käyttäen ainoastaan joitakin aineiston luomiseen tarvittavia sääntöjä sen luomiseen tietokoneella. Esimerkiksi voimme simuloida normitetusta normaalijakaumasta havaintoja käyttäen R:ää. Jakaumien simulointi R sisältää suuren joukon erilaisia tilastollisia jakaumia, joista uusia havaintoja voidaan simuloida. Seuraavassa esitetään vain muutamia esimerkkejä keskeisimmillä jakaumilla. Normaalijakaumasta havaintoja voidaan simuloida komennolla rnorm(). Oletusarvoisesti havaintoja simuloidaan normitetusta normaalijakaumasta, mutta argumenteilla mean ja sd voidaan asettaa simuloitavan jakauman parametrit, keskiarvo ja keskihajonta, tarkemmin. Esimerkiksi sadan havainnon simulointi normitetusta normaalijakaumasta onnistuu komennolla: >d<-rnorm(100) Vastaavasti esimerkiksi Suomen väestön pituusjakauman simulointi, tosin vain sataa havaintoa käyttäen, onnistuisi komennolla: >d<-rnorm(100, mean=167, sd=5) Vastaavalla tavalla voidaan havaintoja simuloida muistakin jakaumista. Komennolla rf() simuloidaan F-jakauman havaintoja, komennolla rpois() Poisson-jakauman havaintoja, komennolla rbinom() binomijakauman havaintoja ja komennolla rchisq() Khiin neliöjakauman havaintoja. Komennolla runif() voidaan simuloida tasajakaumaa. Esimerkiksi tavanomaisen nopan jakaumaa voidaan simuloida komennolla: >runif(100, min=1, max=6) 266

275 R KIELEN PERUSTEET Multinormaalijakauman simulointi on edellisiä hiukan vaikeampaa, sillä silloin on määriteltävä simuloitavien muuttujien keskiarvon lisäksi niiden keskinäinen kovarianssimatriisi. Simuloidaan seuraavassa esimerkin omaisesti rairuohoaineisto laajennuspaketin MASS komennolla mvrnorm(): >dat<-read.table("rairuoho.txt", header=t, sep="\t") >kov<-cov(dat[,1:6]) >kov day3 day4 day5 day6 day7 day8 day day4 day5 day6 day7 day >m<-colmeans(dat[,1:6]) >m day day day day day7 day >rai<-mvrnorm(n=48, mu=m, Sigma=kov) Mihin edellä esiteltyjä simulaatiomenetemiä sitten voidaan käyttää? Simualatioilla on varsin laaja sovellusalue. Simulaatioiden avulla voidaan tutkia esimerkiksi tilastollisten mallien sopivuutta aineistoon, menetelmien oletusten rikkoutumisen vaikutusta tuloksiin ja simuloimalla voidaan myös luoda näppärästi uusia aineistoa esimerkiksi kurssitarpeisiin. Vastemuuttujan simulointi mallin avulla Jos aineiston on sovitettu jokin tilastollinen malli, esimerkiksi yleinen tai yleistetty lineaarinen malli, voidaan mallin avulla simuloida uusi vastemuuttuja. Tämä kulkee myös nimellä parametrinen bootstrapping. Bootstrapping-menetelmään tutustutaan seuraavassa kappaleessa tarkemmin. Vastemuuttujan simulointi mallin avulla tapahtuu komennolla simulate(). Komento toimii ainakin yleiselle ja yleistetylle lineaariselle mallille. Sovitetaan ensin yksinkertainen malli rairuohoaineistoon: >dat<-read.table("rairuoho.txt", header=t, sep="\t") >fit1<-lm(day7~bed+treatment, data=dat) Tämän jälkeen voidaan simuloida yksi uusi vastemuuttujan arvot sisältävä vektori seuraavasti: >simulate(fit1) 267

276 TILASTOLLISET TOIMINNOT Komennolle voidaan antaa myös simuloitavien vastemuuttujien määrä. Esimerkiksi sata vastemuuttujavektoria voidaan simuloida komennolla: >simulate(fit1, 100) Jos malli on sovitettu käyttäen lineaarista sekamallia, käy simulointi komennolla simulate.lme(), joka löytyy laajennuspaketista nlme. Jos sen sijaan mallin sovittamiseen käytetty additiivista mallia, ei simulointi onnistu helposti yhdellä komennolla. Boostrapping Bootstrapping-menetelmällä voidaan, noin yleisesti ottaen, arvioida esimerkiksi mallin sopivuutta aineistoon, ottaa huomioon mallin sovituksessa tehdyt valinnat ja välttää siten ylisovituksen ongelmia tai arvioida mallin parametrien luottamusvälejä tai muuta vastaavia. Seuraavassa ei keskitytä mihinkään erityiseen sovellukseen, vaan esitetään yleisen lineaarisen mallin bootstrapping-analyysi. Tosin yleisen lineaarisen mallin yhteydessä bootstrapping-menetelmiä harvoin tarvitaan. Bootstrapping-analyysiin voidaan käyttää joko parametrista ei epäparametrista menetelmää. Epäparametrisessa menetelmässä poimitaan alkuperäisestä aineistosta uusia otoksia, parametrisessä menetelmässä simuloidaan mallin perusteella uusia aineistoja. Kummallakin tavalla tuotettujen pseudotoistojen avulla voidaan sitten esimerkiksi arvioida mallin parametrien luottamusväli. Parametrisen bootstrapping-menetelmän toteutus on kuvattu edeltävässä kappaleessa. Epäparametrinen bootstrapping voidaan toteuttaa laajennuspaketin boot komennolla boot(). Ennen analyysiä on kirjoitettava komento, jota bootstrapping-analyysissä käytetään. Esimerkiksi seuraavalla komennolla bs() saadaan arvioitua mallin parametrien 95% luottamusvälit, kun sitä käytetään komennossa boot(). >bs <- function(formula, data, indices) { >d <- data[indices,] >fit <- lm(formula, data=d) >return(coef(fit)) >} Sovitetaan aineistoon malli: >dat<-read.table("rairuoho.txt", header=t, sep="\t") >fit1<-lm(day7~bed+treatment, data=dat) 268

277 R KIELEN PERUSTEET Ja arvioidaan parametrien luottamusvälit: >library(boot) >res<-boot(data=dat, formula=day7~bed+treatment) statistic=bs, R=1000, Verrataanpa alkuperäisen analyysin ja bootstrapping-analyysin tulosta. Alkuperäinen analyysi antaa tulokseksi: > summary(fit1) Coefficients: Estimate Std. Error t value Pr(> t ) (Intercept) < 2e-16 *** bedmould bedpaper e-05 *** bedpaper treatmentwater *** Ja bootstrapping-analyysi antaa parametreille, jotka on lueteltu samassa järjestyksessä kuin yllä, mutta eri nimillä,seuraavan tuloksen: > res ORDINARY NONPARAMETRIC BOOTSTRAP Call: boot(data = dat, statistic = bs, R = 1000, formula = day7 ~ bed + treatment) Bootstrap Statistics : original bias t1* t2* t3* t4* t5* Bootstrapping-analyysin komennolla std. error tuloksista voidaan piirtää kuva. Esimerkiksi >plot(res, index=1) saadaan alla oleva kuva, joka esittää mallin intercept:n bootstrappingtuloksia: 269

278 TILASTOLLISET TOIMINNOT Bootstrapping-analyysin antamat arvot näyttäisivät olevan ainakin suunnilleen normaalisti jakautuneita. Parametrien luottamusvälit arvioidaan seuraavaksi. Tavanomaiset normaaliapproksimaatioon perustuvat luottamusvälit voidaan laskea komennolla: > confint(fit1) 2.5 % 97.5 % (Intercept) bedmould bedpaper bedpaper treatmentwater Bootstrapping-analyysin perusteella luottamusvälit voidaan laskea komennolla boot.ci(). Esimerkiksi intercep:lle luottamussväli laskettaisiin: >boot.ci(res, index=1) BOOTSTRAP CONFIDENCE INTERVAL CALCULATIONS Based on 1000 bootstrap replicates 270

KAAVAT. Sisällysluettelo

KAAVAT. Sisällysluettelo Excel 2013 Kaavat Sisällysluettelo KAAVAT KAAVAT... 1 Kaavan tekeminen... 2 Kaavan tekeminen osoittamalla... 2 Kaavan kopioiminen... 3 Kaavan kirjoittaminen... 3 Summa-funktion lisääminen... 4 Suorat eli

Lisätiedot

Excel syventävät harjoitukset 31.8.2015

Excel syventävät harjoitukset 31.8.2015 Yleistä Excel on taulukkolaskentaohjelma. Tämä tarkoittaa sitä että sillä voi laskea laajoja, paljon laskentatehoa vaativia asioita, esimerkiksi fysiikan laboratoriotöiden koetuloksia. Excel-ohjelmalla

Lisätiedot

Muuttujien määrittely

Muuttujien määrittely Tarja Heikkilä Muuttujien määrittely Määrittele muuttujat SPSS-ohjelmaan lomakkeen kysymyksistä. Harjoitusta varten lomakkeeseen on muokattu kysymyksiä kahdesta opiskelijoiden tekemästä Joupiskan rinneravintolaa

Lisätiedot

Ohjeet asiakirjan lisäämiseen arkistoon

Ohjeet asiakirjan lisäämiseen arkistoon Ohjeet asiakirjan lisäämiseen arkistoon 1. Jos koneellesi ei vielä ole asennettu Open Office ohjelmaa, voit ladata sen linkistä joka löytyy Arkisto => Asiakirjapohjat sivulta seuran kotisivuilta. Jos ohjelma

Lisätiedot

Tiedostojen lataaminen netistä ja asentaminen

Tiedostojen lataaminen netistä ja asentaminen s. 1/5 Tiedostojen lataaminen netistä ja asentaminen Yleistä Internetissä on paljon hyödyllisiä ilmaisohjelmia, jotka voi ladata ja asentaa omalle koneelle. Osa ohjelmista löytyy suomenkielisiltä sivuilta,

Lisätiedot

Uutiskirjesovelluksen käyttöohje

Uutiskirjesovelluksen käyttöohje Uutiskirjesovelluksen käyttöohje Käyttäjätuki: Suomen Golfpiste Oy Esterinportti 1 00240 HELSINKI Puhelin: (09) 1566 8800 Fax: (09) 1566 8801 E-mail: gp@golfpiste.com 2 Sisällys Johdanto... 1 Päänavigointi...

Lisätiedot

Johdatus ohjelmointiin

Johdatus ohjelmointiin Johdatus ohjelmointiin EXAM tentin liitetiedostojen lataaminen, käyttäminen ja palauttaminen Kerro mahdolliset puutteet tai parannusehdotukset: pietari.heino@tut.fi Tällä sivulla on selitetty lyhyesti

Lisätiedot

Pythonin alkeet Syksy 2010 Pythonin perusteet: Ohjelmointi, skriptaus ja Python

Pythonin alkeet Syksy 2010 Pythonin perusteet: Ohjelmointi, skriptaus ja Python Pythonin alkeet Syksy 2010 Pythonin perusteet: Ohjelmointi, skriptaus ja Python 8. marraskuuta 2010 Ohjelmointi Perusteet Peruskäsitteitä Olio-ohjelmointi Pythonin alkeet Esittely Esimerkkejä Muuttujat

Lisätiedot

DOORSin Spreadsheet export/import

DOORSin Spreadsheet export/import DOORSin Spreadsheet export/import 17.10.2006 SoftQA Oy http/www.softqa.fi/ Pekka Mäkinen Pekka.Makinen@softqa.fi Tietojen siirto DOORSista ja DOORSiin Yhteistyökumppaneilla ei välttämättä ole käytössä

Lisätiedot

Kieliversiointityökalu Java-ohjelmistoon. Ohje

Kieliversiointityökalu Java-ohjelmistoon. Ohje Kieliversiointityökalu Java-ohjelmistoon Ohje 2/6 SISÄLLYSLUETTELO 1 YLEISTÄ OHJELMASTA... 3 2 PÄÄ-IKKUNA...4 3 YLÄVALIKKO... 4 3.1 TIEDOSTO... 4 3.2 TOIMINTO... 4 3.3 ASETUKSET... 5 3.4 OHJE... 5 4 VÄLILEHDET...5

Lisätiedot

Viva-16. Käyttöohje. 1.4.2009 Veikko Nokkala Suomen Videovalvonta.com

Viva-16. Käyttöohje. 1.4.2009 Veikko Nokkala Suomen Videovalvonta.com Viva-16 Käyttöohje 1.4.2009 Veikko Nokkala Sisällysluettelo Sisällysluettelo... 2 Ohjelmisto käyttöliittymä... 3 Asentaminen... 3 Käyttöönotto... 3 Katselu... 6 Tallennus... 8 Toistaminen... 9 Selain käyttöliittymä...

Lisätiedot

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python Ohjelmoinnin perusteet Y Python T-106.1208 2.3.2011 T-106.1208 Ohjelmoinnin perusteet Y 2.3.2011 1 / 39 Kertausta: tiedoston avaaminen Kun ohjelma haluaa lukea tai kirjoittaa tekstitiedostoon, on ohjelmalle

Lisätiedot

Send-It ilmoittautumisjärjestelmä (judotapahtumat Suomessa)

Send-It ilmoittautumisjärjestelmä (judotapahtumat Suomessa) Ilmoittautumis järjestelmän otsikko alue Jokaisella tapahtumalla on otsikko-osa joka on samanlainen joka puolella sovellusta. Tämä Judokilpailuissa käytetty otsikko-osa koostuu viidestä linkistä, joita

Lisätiedot

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python Ohjelmoinnin perusteet Y Python T-106.1208 16.2.2010 T-106.1208 Ohjelmoinnin perusteet Y 16.2.2010 1 / 41 Kännykkäpalautetteen antajia kaivataan edelleen! Ilmoittaudu mukaan lähettämällä ilmainen tekstiviesti

Lisätiedot

Valitse ruudun yläosassa oleva painike Download Scilab.

Valitse ruudun yläosassa oleva painike Download Scilab. Luku 1 Ohjeita ohjelmiston Scilab käyttöön 1.1 Ohjelmiston lataaminen Ohjeet ohjelmiston lataamiseen Windows-koneelle. Mene verkko-osoitteeseen www.scilab.org. Valitse ruudun yläosassa oleva painike Download

Lisätiedot

H6: Tehtävänanto. Taulukkolaskennan perusharjoitus. Harjoituksen tavoitteet

H6: Tehtävänanto. Taulukkolaskennan perusharjoitus. Harjoituksen tavoitteet H6: Tehtävänanto Taulukkolaskennan perusharjoitus Ennen kuin aloitat harjoituksen teon, lue siihen liittyvä taustamateriaali. Se kannattaa käydä läpi kokeilemalla samalla siinä annetut esimerkit käyttämässäsi

Lisätiedot

1 Tivax siirto uuteen koneeseen

1 Tivax siirto uuteen koneeseen Tivax siirto uuteen koneeseen 1 1 Tivax siirto uuteen koneeseen 1.1 Tivax ohjelman asentaminen Huom. Siirrossa mahdollisesti esiintyvien ongelmien ratkaisu on veloituksetonta ainoastaan asiakkaille, joilla

Lisätiedot

Tähtitieteen käytännön menetelmiä Kevät 2009 Luento 4: Ohjelmointi, skriptaus ja Python

Tähtitieteen käytännön menetelmiä Kevät 2009 Luento 4: Ohjelmointi, skriptaus ja Python Tähtitieteen käytännön menetelmiä Kevät 2009 Luento 4: Ohjelmointi, skriptaus ja Python 31. tammikuuta 2009 Ohjelmointi Perusteet Pythonin alkeet Esittely Esimerkkejä Muuttujat Peruskäsitteitä Käsittely

Lisätiedot

KÄYTTÖOHJE. Servia. S solutions

KÄYTTÖOHJE. Servia. S solutions KÄYTTÖOHJE Servia S solutions Versio 1.0 Servia S solutions Servia Finland Oy PL 1188 (Microkatu 1) 70211 KUOPIO puh. (017) 441 2780 info@servia.fi www.servia.fi 2001 2004 Servia Finland Oy. Kaikki oikeudet

Lisätiedot

Pedacode Pikaopas. Java-kehitysympäristön pystyttäminen

Pedacode Pikaopas. Java-kehitysympäristön pystyttäminen Pedacode Pikaopas Java-kehitysympäristön pystyttäminen Pikaoppaan sisältö Pikaoppaassa kuvataan, miten Windowstyöasemalle asennetaan Java-ohjelmoinnissa tarvittavat työkalut, minkälaisia konfigurointeja

Lisätiedot

VERKKOVELHO-YLLÄPITOTYÖKALUN KÄYTTÖOHJE

VERKKOVELHO-YLLÄPITOTYÖKALUN KÄYTTÖOHJE VERKKOVELHO-YLLÄPITOTYÖKALUN KÄYTTÖOHJE 1. SISÄÄN KIRJAUTUMINEN Sisään kirjautuminen VerkkoVelho-ylläpitotyökaluun tapahtuu yrityksesi osoitteessa www.omaosoitteesi.fi/yllapito, esim. www.verkkovelho.fi/yllapito.

Lisätiedot

Nero 7:n Windows Vista TM -tuki

Nero 7:n Windows Vista TM -tuki Nero 7:n Windows Vista TM -tuki Nero AG Sivu 1 Tietoja tekijänoikeudesta ja tavaramerkistä Tämä opaskirjanen ja sen sisältö on Nero AG:n omaisuutta ja suojattu tekijänoikeudella. Kaikki oikeudet pidätetään.

Lisätiedot

Harjoitus 1 -- Ratkaisut

Harjoitus 1 -- Ratkaisut Kun teet harjoitustyöselostuksia Mathematicalla, voit luoda selkkariin otsikon (ja mahdollisia alaotsikoita...) määräämällä soluille erilaisia tyylejä. Uuden solun tyyli määrätään painamalla ALT ja jokin

Lisätiedot

Ohjelmassa henkilön etunimi ja sukunimi luetaan kahteen muuttujaan seuraavasti:

Ohjelmassa henkilön etunimi ja sukunimi luetaan kahteen muuttujaan seuraavasti: 1 (7) Tiedon lukeminen näppäimistöltä Scanner-luokan avulla Miten ohjelma saa käyttöönsä käyttäjän kirjoittamaa tekstiä? Järjestelmässä on olemassa ns. syöttöpuskuri näppäimistöä varten. Syöttöpuskuri

Lisätiedot

NAVITA BUDJETTIJÄRJESTELMÄN ENSIASENNUS PALVELIMELLE

NAVITA BUDJETTIJÄRJESTELMÄN ENSIASENNUS PALVELIMELLE NAVITA BUDJETTIJÄRJESTELMÄN ENSIASENNUS PALVELIMELLE Ennen palvelinohjelman asennusta perustetaan tarvittavat kansiot. Oikeustasoista share- tai security-tason oikeudet riittävät; molempien oikeustasojen

Lisätiedot

UpdateIT 2010: Editorin käyttöohje

UpdateIT 2010: Editorin käyttöohje UpdateIT 2010: Editorin käyttöohje Käyttäjätuki: Suomen Golfpiste Oy Esterinportti 1 00240 HELSINKI Puhelin: (09) 1566 8800 Fax: (09) 1566 8801 E-mail: gp@golfpiste.com Sisällys Editorin käyttöohje...

Lisätiedot

ASENNUS- JA KÄYTTÖOHJE

ASENNUS- JA KÄYTTÖOHJE ASENNUS- JA KÄYTTÖOHJE YKSIKKÖHINTA SOPIMUKSEN TOTEUTUNEET MÄÄRÄT-SOVELLUS CMPRO5 VERSIO 2.8 PÄIVITETTY HEINÄKUU 2010 COPYRIGHT 2010 ARTEMIS FINLAND OY. ALL RIGHTS RESERVED. KÄYTTÖOHJE SIVU 2 (12) SISÄLLYSLUETTELO

Lisätiedot

Microsoft Security Essentials (MSE) asennuspaketin lataaminen verkosta

Microsoft Security Essentials (MSE) asennuspaketin lataaminen verkosta Etusivu > Tietohallintokeskus > Ohjeet > Tutoriaalit > Virustorjunta (Microsoft Security Essentials) Virustorjunta (Microsoft Security Essentials) Ohjeet Microsoft Security Essentials -virustorjuntaohjelman

Lisätiedot

2013 -merkistä tunnistat uudet ominaisuudet

2013 -merkistä tunnistat uudet ominaisuudet Tähän käsikirjaan on koottu Ecomiin liittyviä yleisiä aiheita ja toimintatapoja, joiden opiskelemisesta on hyötyä kaikille Ecomin käyttäjille. 2013 2013 -merkistä tunnistat uudet ominaisuudet Ohjeita käsikirjan

Lisätiedot

Octave-opas. Mikä on Octave ja miksi? Asennus

Octave-opas. Mikä on Octave ja miksi? Asennus Octave-opas Mikä on Octave ja miksi? Asennus Käynnistys ja käyttöliittymä Komennot tiedostojen hallintaan SciTE-editor.m-tiedostot Ohjeita muualla Mikä on Octave ja miksi? Octave on numeeriseen laskentaan

Lisätiedot

R-KIELEN PERUSTEET JARNO TUIMALA Helsinki 2010

R-KIELEN PERUSTEET JARNO TUIMALA Helsinki 2010 R-KIELEN PERUSTEET R-KIELEN PERUSTEET JARNO TUIMALA Helsinki 2010 2010 Jarno Tuimala ISBN 978-952-92-7020-0 (nid.) ISBN 978-952-92-7021-7 (PDF) Books on Demand GmbH Norderstedt, Saksa 2010 1. painos Sisällysluettelo

Lisätiedot

Ohjelmointitaito (ict1td002, 12 op) Kevät 2008. 1. Java-ohjelmoinnin alkeita. Tietokoneohjelma. Raine Kauppinen raine.kauppinen@haaga-helia.

Ohjelmointitaito (ict1td002, 12 op) Kevät 2008. 1. Java-ohjelmoinnin alkeita. Tietokoneohjelma. Raine Kauppinen raine.kauppinen@haaga-helia. Ohjelmointitaito (ict1td002, 12 op) Kevät 2008 Raine Kauppinen raine.kauppinen@haaga-helia.fi 1. Java-ohjelmoinnin alkeita Tietokoneohjelma Java-kieli ja Eclipse-ympäristö Java-ohjelma ja ohjelmaluokka

Lisätiedot

Laskuharjoitus 9, tehtävä 6

Laskuharjoitus 9, tehtävä 6 Aalto-yliopiston perustieteiden korkeakoulu Jouni Pousi Systeemianalyysin laboratorio Mat-2.4129 Systeemien identifiointi Laskuharjoitus 9, tehtävä 6 Tämä ohje sisältää vaihtoehtoisen tavan laskuharjoituksen

Lisätiedot

BLOGGER. ohjeita blogin pitämiseen Googlen Bloggerilla

BLOGGER. ohjeita blogin pitämiseen Googlen Bloggerilla BLOGGER ohjeita blogin pitämiseen Googlen Bloggerilla Sisältö Blogin luominen... 1 Uuden blogitekstin kirjoittaminen... 4 Kuvan lisääminen blogitekstiin... 5 Lisää kuva omalta koneelta... 6 Lisää kuva

Lisätiedot

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python Ohjelmoinnin perusteet Y Python T-106.1208 25.2.2009 T-106.1208 Ohjelmoinnin perusteet Y 25.2.2009 1 / 34 Syötteessä useita lukuja samalla rivillä Seuraavassa esimerkissä käyttäjä antaa useita lukuja samalla

Lisätiedot

STS Uuden Tapahtuma-dokumentin teko

STS Uuden Tapahtuma-dokumentin teko STS Uuden Tapahtuma-dokumentin teko Valitse vasemmasta reunasta kohta Sisällöt. Sisällöt-näkymä Valitse painike Lisää uusi Tapahtuma 1 Valitse kieleksi Suomi Välilehti 1. Perustiedot Musta reunus kieliversioneliön

Lisätiedot

PÄIVITÄ TIETOKONEESI

PÄIVITÄ TIETOKONEESI PÄIVITÄ TIETOKONEESI SAMPOLAN KIRJASTO TIETOTORI Sammonkatu 2 33540 Tampere 040 800 7816 tietotori.sampola@tampere.fi PÄIVITÄ TIETOKONEESI 2(16) Sisällys 1. Mihin päivityksiä tarvitaan?... 3 1.1. Windowsin

Lisätiedot

MixW ja Dx-vihjeet (ohje) oh3htu 10.9.2009

MixW ja Dx-vihjeet (ohje) oh3htu 10.9.2009 MixW ja Dx-vihjeet (ohje) oh3htu 10.9.2009 MixW:n käyttäjille mieleen on saada DX-vihjeet MixW:n Dxcluster dialog-ikkunaan sen monipuolisuuden ansiosta. Dxcluster dialog-ikkunassa on muun muassa helposti

Lisätiedot

Sen jälkeen Microsoft Office ja sen alta löytyy ohjelmat. Ensin käynnistä-valikosta kaikki ohjelmat

Sen jälkeen Microsoft Office ja sen alta löytyy ohjelmat. Ensin käynnistä-valikosta kaikki ohjelmat Microsoft Office 2010 löytyy tietokoneen käynnistävalikosta aivan kuin kaikki muutkin tietokoneelle asennetut ohjelmat. Microsoft kansion sisältä löytyy toimisto-ohjelmistopakettiin kuuluvat eri ohjelmat,

Lisätiedot

Office 2013 - ohjelmiston asennusohje

Office 2013 - ohjelmiston asennusohje Office 2013 - ohjelmiston asennusohje Tämän ohjeen kuvakaappaukset on otettu asentaessa ohjelmistoa Windows 7 käyttöjärjestelmää käyttävään koneeseen. Näkymät voivat hieman poiketa, jos sinulla on Windows

Lisätiedot

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python Ohjelmoinnin perusteet Y Python T-106.1208 28.2.2011 T-106.1208 Ohjelmoinnin perusteet Y 28.2.2011 1 / 46 Ohjelmointiprojektin vaiheet 1. Määrittely 2. Ohjelman suunnittelu (ohjelman rakenne ja ohjelman

Lisätiedot

Epooqin perusominaisuudet

Epooqin perusominaisuudet Epooqin perusominaisuudet Huom! Epooqia käytettäessä on suositeltavaa käyttää Firefox -selainta. Chrome toimii myös, mutta eräissä asioissa, kuten äänittämisessä, voi esiintyä ongelmia. Internet Exploreria

Lisätiedot

Käyttöohje. Energent MagiCAD plugin

Käyttöohje. Energent MagiCAD plugin Käyttöohje Energent MagiCAD plugin Sisältö 1. Yleistä 1 Dokumentin sisältö... 1 Ohjelman asennus... 1 Vaadittavat ohjelmistot... 1 Asennus... 1 Ohjelman käynnistys... 2 2. Toiminnallisuudet 3 Insert Energent

Lisätiedot

SQL Server 2008 asennus

SQL Server 2008 asennus SQL Server 2008 asennus 1. Yleistä... 3 2. Edellytykset... 3 3. SQL Server 2008 Express asennus... 4 4. Yhteystiedot... 6 2/6 1. YLEISTÄ Tässä ohjeessa käydään vaiheittain Microsoft SQL Server 2008 tietokantaohjelmiston

Lisätiedot

Mikäli olet saanut e-kirjan latauslinkin sähköpostilla, seuraa näitä ohjeita e-kirjan lataamisessa.

Mikäli olet saanut e-kirjan latauslinkin sähköpostilla, seuraa näitä ohjeita e-kirjan lataamisessa. E-kirjan latausohje Mikäli olet saanut e-kirjan latauslinkin sähköpostilla, seuraa näitä ohjeita e-kirjan lataamisessa. Pikaohjeet 1. Varmista että tietokoneellesi on asennettu Adobe Digital Editions ohjelma.

Lisätiedot

Sonera Yrityssähköposti. Outlook 2013 lataus ja asennus

Sonera Yrityssähköposti. Outlook 2013 lataus ja asennus Sonera Yrityssähköposti. Outlook 2013 lataus ja asennus Sisältö 1/14 Sonera Yrityssähköpostin käyttöönotto Outlook 2013 -sovelluksella SISÄLLYS Outlook 2013 asennuspaketin lataus... 2 Outlook 2013 asennus...

Lisätiedot

Pika-aloitusopas. Sisältö: Projektin luominen Projektin muokkaaminen ja hallinnointi Projektin/arvioinnin tulosten tarkastelu

Pika-aloitusopas. Sisältö: Projektin luominen Projektin muokkaaminen ja hallinnointi Projektin/arvioinnin tulosten tarkastelu Pika-aloitusopas Sisältö: Projektin luominen Projektin muokkaaminen ja hallinnointi Projektin/arvioinnin tulosten tarkastelu Tämä asiakirja on laadittu auttamaan sinua hallinnoimaan nopeasti CEB TalentCentral

Lisätiedot

Sonera Viestintäpalvelu VIP VIP Laajennettu raportointi Ohje

Sonera Viestintäpalvelu VIP VIP Laajennettu raportointi Ohje Sonera Viestintäpalvelu VIP VIP Laajennettu raportointi Ohje Sisällysluettelo VIP Laajennettu raportointi... 3 Luo raportti Laajennetun raportoinnin työkaluilla... 4 Avaa Laajennettu raportointi... 4 Valitse

Lisätiedot

SeaMonkey pikaopas - 1

SeaMonkey pikaopas - 1 SeaMonkey pikaopas SeaMonkey on ilmainen ja yksinkertainen www-sivujen teko-ohjelma. Sillä on kätevää koostaa yksinkertaisia sivuja ilman, että täytyy tietää jotain HTML-koodista. Tämä opas esittelee sivuston

Lisätiedot

Mathcad Flexnet lisenssipalvelimen asennus

Mathcad Flexnet lisenssipalvelimen asennus Mathcad Flexnet lisenssipalvelimen asennus Korjattu 13.01.01 Tärkeää: Ennen lisenssin hakemista tulee luoda PTC tili. Tästä on erillinen ohje, jonka on joko tullut tämän dokumentin yhteydessä tai sen saa

Lisätiedot

Asennuksessa kannattaa käyttää asennusohjelman tarjoamia oletusarvoja.

Asennuksessa kannattaa käyttää asennusohjelman tarjoamia oletusarvoja. 1 1 Tivax Laskutus 4.5 1.1 Tivax ohjelman asentaminen TivaxLaskutus version 4.5 asentamiseksi on oltava asennus CD. Asennusohjelma käynnistetään tuplaklikkamalla asennus CD:llä olevaa Tivax45LaskuSetup.exe

Lisätiedot

Pika-asennusohjeet Suomeksi

Pika-asennusohjeet Suomeksi Pika-asennusohjeet Suomeksi (Virallinen ohje löytyy asennuslevyltä Englanninkielisenä) Tulosta tämä ohje asennuksen avuksi. Ensiksi asennetaan itse ohjelma, sitten rekisteröidytään testerin käyttäjäksi

Lisätiedot

Juha Haataja 4.10.2011

Juha Haataja 4.10.2011 METROPOLIA Taulukkolaskenta Perusteita Juha Haataja 4.10.2011 Lisätty SUMMA.JOS funktion käyttö (lopussa). Tavoite ja sisältö Tavoite Taulukkolaskennan peruskäytön hallinta Sisältö Työtila Omat kaavat,

Lisätiedot

MOODLE TUTUKSI. Pirkko Vänttilä Oulun aikuiskoulutuskeskus 4.8.2008

MOODLE TUTUKSI. Pirkko Vänttilä Oulun aikuiskoulutuskeskus 4.8.2008 2008 MOODLE TUTUKSI Pirkko Vänttilä Oulun aikuiskoulutuskeskus 4.8.2008 SISÄLLYSLUETTELO 1. ALOITUSNÄKYMÄ... 4 2. TUTUSTUMINEN... 5 3. KESKUSTELUT... 8 4. VIESTIT... 10 5. CHATIT... 10 6. TIEDOSTOJA OMALTA

Lisätiedot

Johdatus Ohjelmointiin

Johdatus Ohjelmointiin Johdatus Ohjelmointiin Syksy 2006 Viikko 2 13.9. - 14.9. Tällä viikolla käsiteltävät asiat Peruskäsitteitä Kiintoarvot Tiedon tulostus Yksinkertaiset laskutoimitukset Muuttujat Tiedon syöttäminen Hyvin

Lisätiedot

Sähköposti ja uutisryhmät 4.5.2005

Sähköposti ja uutisryhmät 4.5.2005 Outlook Express Käyttöliittymä Outlook Express on windows käyttöön tarkoitettu sähköpostin ja uutisryhmien luku- ja kirjoitussovellus. Se käynnistyy joko omasta kuvakkeestaan työpöydältä tai Internet Explorer

Lisätiedot

Coolselector Asennusohje

Coolselector Asennusohje MAKING MODERN LIVING POSSIBLE Coolselector Asennusohje Täydellinen valinta on vain muutaman klikkauksen päässä www.danfoss.fi/kylma Yleiset vaatimukset Windows XP asennus Windows 7 asennus Asennuksen poisto

Lisätiedot

ASENNUS JA KÄYTTÖOHJE

ASENNUS JA KÄYTTÖOHJE ASENNUS JA KÄYTTÖOHJE YKSIKKÖHINTALUETTELON HINNOITTELU SOVELLUS CMPRO5 VERSIO 2.8 PÄIVITETTY HEINÄKUU 2010 COPYRIGHT 2010 ARTEMIS FINLAND OY. ALL RIGHTS RESERVED. YH-LUETTELON HINNOITTELU SISÄLLYSLUETTELO

Lisätiedot

Siirtyminen Outlook 2010 -versioon

Siirtyminen Outlook 2010 -versioon Tämän oppaan sisältö Microsoft Microsoft Outlook 2010 näyttää hyvin erilaiselta kuin Outlook 2003. Tämän oppaan tarkoituksena on helpottaa uuden ohjelman opiskelua. Seuraavassa on tietoja uuden käyttöliittymän

Lisätiedot

Oppilaan pikaopas. Project 2013 käyttöliittymä ja näkymät

Oppilaan pikaopas. Project 2013 käyttöliittymä ja näkymät 1 Oppilaan pikaopas Project 2013 käyttöliittymä ja näkymät Kun avaat Project 2013 -ohjelman, näet ensimmäisenä pelkistetyn näkymän. Uusi Project 2013 voi auttaa projektinhallinnassa kuten esim. projektitietojen

Lisätiedot

Enigmail-opas. Asennus. Avainten hallinta. Avainparin luominen

Enigmail-opas. Asennus. Avainten hallinta. Avainparin luominen Enigmail-opas Enigmail on Mozilla Thunderbird ja Mozilla Seamonkey -ohjelmille tehty liitännäinen GPG-salausohjelmiston käyttöä varten. Sitä käytetään etenkin Thunderbirdin kanssa sähköpostin salaamiseen

Lisätiedot

1 Yleistä Web-editorista... 3. 1.1 Web-editori -dokumentin luominen... 3. 2 Pikatoimintopainikkeet... 3. 2.1 Tallenna... 3

1 Yleistä Web-editorista... 3. 1.1 Web-editori -dokumentin luominen... 3. 2 Pikatoimintopainikkeet... 3. 2.1 Tallenna... 3 Web-editori 2 Optima Web-editori -ohje Sisällysluettelo 1 Yleistä Web-editorista... 3 1.1 Web-editori -dokumentin luominen... 3 2 Pikatoimintopainikkeet... 3 2.1 Tallenna... 3 2.2 Peru / Tee uudelleen...

Lisätiedot

Autentikoivan lähtevän postin palvelimen asetukset

Autentikoivan lähtevän postin palvelimen asetukset Autentikoivan lähtevän postin palvelimen asetukset - Avaa Työkalut valikko ja valitse Tilien asetukset - Valitse vasemman reunan lokerosta Lähtevän postin palvelin (SM - Valitse listasta palvelin, jonka

Lisätiedot

LINUX-HARJOITUS, MYSQL

LINUX-HARJOITUS, MYSQL LINUX-HARJOITUS, MYSQL Harjoituksen aiheena on tietokantapalvelimen asentaminen ja testaaminen. Asennetaan MySQL-tietokanta. Hieman linkkejä: http://www.mysql.com/, MySQL-tietokantaohjelman kotisivu. http://www.mysql.com/doc/en/index.html,

Lisätiedot

1 Tivax Professional 4.5

1 Tivax Professional 4.5 Tivax Professional 4.5 1 1 Tivax Professional 4.5 1.1 Tivax ohjelman asentaminen TivaxProfessional versio 4.5 asennetaan joko CD:ltä tai lataamalla asennustiedosto Internetistä. Asennus CD:ltä: Asennusohjelma

Lisätiedot

Henkilö- ja koulutusrekisterin asennusohje

Henkilö- ja koulutusrekisterin asennusohje Henkilö- ja koulutusrekisterin asennusohje Ohjelmaversio 1.0 Dokumenttiversio 1.0 2 Ohjelman lataaminen Voit ladata henkilöstö- ja koulutusrekisteriohjelman asennuspaketin EduSetup.exe sivustolta valitsemalla

Lisätiedot

Tikon Web-sovellukset

Tikon Web-sovellukset Toukokuu 2015 1 (11) Tikon Web-sovellukset Toukokuu 2015 2 (11) 1 Johdanto... 3 2 Silverlight sovellukset... 3 2.1 Windows... 3 2.1.1 Microsoft Silverlight... 3 2.1.2 Tablet-laitteet... 4 2.1.3 Selaimet...

Lisätiedot

Kirkkopalvelut Office365, Opiskelijan ohje 1 / 17 IT Juha Nalli 22.12.2015

Kirkkopalvelut Office365, Opiskelijan ohje 1 / 17 IT Juha Nalli 22.12.2015 Kirkkopalvelut Office365, Opiskelijan ohje 1 / 17 Oppilaat saavat vuoden 2016 alusta käyttöönsä oppilaitoksen sähköpostin ja muita palveluita Microsoftin Office365:sta. Oppilaiden sähköposti on muotoa

Lisätiedot

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python Ohjelmoinnin perusteet Y Python T-106.1208 7.2.2011 T-106.1208 Ohjelmoinnin perusteet Y 7.2.2011 1 / 39 Kännykkäpalautetteen antajia kaivataan edelleen! Ilmoittaudu mukaan lähettämällä ilmainen tekstiviesti

Lisätiedot

Ohjeistus yhdistysten internetpäivittäjille

Ohjeistus yhdistysten internetpäivittäjille Ohjeistus yhdistysten internetpäivittäjille Oman yhdistyksen tietojen päivittäminen www.krell.fi-sivuille Huom! Tarvitset päivittämistä varten tunnukset, jotka saat ottamalla yhteyden Kristillisen Eläkeliiton

Lisätiedot

ETAPPI ry JOOMLA 2.5 Mediapaja. Artikkeleiden hallinta ja julkaisu

ETAPPI ry JOOMLA 2.5 Mediapaja. Artikkeleiden hallinta ja julkaisu ETAPPI ry JOOMLA 2.5 Artikkeleiden hallinta ja julkaisu ETAPPI ry JOOMLA 2.5 Sivu 1(16) Sisällysluettelo 1 Joomla! sivuston sisällöntuotanto... 2 2 Artikkeleiden julkaisu sivustolla... 4 3 Artikkelin julkaisemista

Lisätiedot

DXL Library ja DXL-kielen olemus. Pekka Mäkinen Pekka.Makinen@softqa.fi SoftQA Oy http/www.softqa.fi/

DXL Library ja DXL-kielen olemus. Pekka Mäkinen Pekka.Makinen@softqa.fi SoftQA Oy http/www.softqa.fi/ DXL Library ja DXL-kielen olemus Pekka Mäkinen Pekka.Makinen@softqa.fi SoftQA Oy http/www.softqa.fi/ DOORS extension Language DXL on DOORSin laajennuskieli, jolla voidaan kehittää lisätoiminnallisuutta.

Lisätiedot

RATKI 1.0 Käyttäjän ohje

RATKI 1.0 Käyttäjän ohje RATKI RATKI 1.0 Käyttäjän ohje Ohje 0.5 Luottamuksellinen Vastuuhenkilö Petri Ahola Sisällysluettelo 1. Yleistä... 3 1.1. Kuvaus... 3 1.2. Esitiedot... 3 1.3. RATKIn käyttöoikeuksien hankinta... 3 1.4.

Lisätiedot

Excel Perusteet. 2005 Päivi Vartiainen 1

Excel Perusteet. 2005 Päivi Vartiainen 1 Excel Perusteet 2005 Päivi Vartiainen 1 SISÄLLYS 1 Excel peruskäyttö... 3 2 Fonttikoon vaihtaminen koko taulukkoon... 3 3 Sarakkeen ja rivin lisäys... 4 4 Solun sisällön ja kaavojen kopioiminen... 5 5

Lisätiedot

Ensin klikkaa käynnistä-valikkoa ja sieltä Kaikki ohjelmat valikosta kaikki ohjelmat

Ensin klikkaa käynnistä-valikkoa ja sieltä Kaikki ohjelmat valikosta kaikki ohjelmat Microsoft Office 2010 löytyy tietokoneen käynnistä-valikosta aivan kuin kaikki muutkin tietokoneelle asennetut ohjelmat. Microsoft kansion sisältä löytyy toimisto-ohjelmistopakettiin kuuluvat eri ohjelmat,

Lisätiedot

Excel-taulukkoon X- ja Y-sarakkeisiin tallennettujen koordinaattien muuntaminen paikkatietokohteiksi

Excel-taulukkoon X- ja Y-sarakkeisiin tallennettujen koordinaattien muuntaminen paikkatietokohteiksi Excel-taulukkoon X- ja Y-sarakkeisiin tallennettujen koordinaattien muuntaminen paikkatietokohteiksi Esimerkkinä Excel-taulukkona ladattavat Helsingin pysäköintilippuautomaatit Viimeksi muokattu 27. huhtikuuta

Lisätiedot

A-Tiilikate objektikirjasto

A-Tiilikate objektikirjasto A-Tiilikate objektikirjasto 15.1.2014 A-Tiilikate-objektikirjasto toimii ArchiCAD 14, 15, 16 ja 17 -versioissa. Kirjaston käyttöön tarvitaan Graphisoftin Tarvikkeet-laajennus. Tarvikkeet-laajennuksen käyttöönotto

Lisätiedot

E-ResultsLite ohjelman käyttö Ounasrasteilla

E-ResultsLite ohjelman käyttö Ounasrasteilla E-ResultsLite ohjelman käyttö Ounasrasteilla 1 Tutustu ohjeisiin Avaa ohjelma kaksoisklikkaamalla ohjelman pikakuvaketta. Tutustu ohjelman omiin ohjeisiin valitsemalla: Ohje > Avustus.., ohjeet avautuvat

Lisätiedot

NETIKKA PCTV KÄYTTÖOHJE

NETIKKA PCTV KÄYTTÖOHJE 1 (20) NETIKKA PCTV 2 (20) 1 YLEISTÄ...3 1.1 MIKÄ ON PCTV?...3 2 PCTV:N KÄYTÖN ALOITTAMINEN...4 2.1 VAATIMUKSET PALOMUURILTA...4 2.1.1 IGMP-palvelun käytön salliminen F-Securessa...4 2.2 VAATIMUKSET TIETOKONEELTA...8

Lisätiedot

WCONDES OHJEET ITÄRASTEILLE (tehty Condes versiolle 8)

WCONDES OHJEET ITÄRASTEILLE (tehty Condes versiolle 8) WCONDES OHJEET ITÄRASTEILLE (tehty Condes versiolle 8) 1 UUDEN KILPAILUTIEDOSTON AVAUS Avaa Wcondes ohjelma tuplaklikkaamalla wcondes.lnk ikonia. Ohjelma avaa automaattisesti viimeksi tallennetun kilpailutiedoston.

Lisätiedot

Tuplaturvan tilaus ja asennusohje

Tuplaturvan tilaus ja asennusohje Tuplaturvan tilaus ja asennusohje 1. Kirjaudu lähiverkkokauppaan omilla tunnuksillasi tai luo itsellesi käyttäjätunnus rekisteröitymällä Lähiverkkokaupan käyttäjäksi. a. Käyttäjätunnus on aina sähköpostiosoitteesi.

Lisätiedot

Asiointipalvelun ohje

Asiointipalvelun ohje Asiointipalvelun ohje Yleistä 1. Kirjautuminen 2. Yhteystiedot 3. Vastaustavan valinta 1. Yleistä 2. Palkkatietojen lataaminen tiedostosta 4. Lomake 1. Yleistä 2. Linkit ja vastaajan tiedot 3. Lomakekäsittely

Lisätiedot

Harjoituksen aiheena on tietokantapalvelimen asentaminen ja testaaminen. Asennetaan MySQL-tietokanta. Hieman linkkejä:

Harjoituksen aiheena on tietokantapalvelimen asentaminen ja testaaminen. Asennetaan MySQL-tietokanta. Hieman linkkejä: Linux-harjoitus 6 Harjoituksen aiheena on tietokantapalvelimen asentaminen ja testaaminen. Asennetaan MySQL-tietokanta. Hieman linkkejä: http://www.mysql.com/, MySQL-tietokantaohjelman kotisivu. http://www.mysql.com/doc/en/index.html,

Lisätiedot

R-ohjelmiston lisäpaketit ja data

R-ohjelmiston lisäpaketit ja data R-ohjelmiston lisäpaketit ja data Vesa Pekkanen Matti Kiiski 14. syyskuuta 2012 Tämä on lyhyt johdatus R-ohjelmiston kirjastojen käyttöönottoon ja datan lukemiseen. Hyödyllisiä komentoja: help.start()

Lisätiedot

Tilastolliset ohjelmistot 805340A. Pinja Pikkuhookana

Tilastolliset ohjelmistot 805340A. Pinja Pikkuhookana Tilastolliset ohjelmistot 805340A Pinja Pikkuhookana Sisältö 1 SPSS 1.1 Yleistä 1.2 Aineiston syöttäminen 1.3 Aineistoon tutustuminen 1.4 Kuvien piirtäminen 1.5 Kuvien muokkaaminen 1.6 Aineistojen muokkaaminen

Lisätiedot

Tiedonsiirto helposti navetta-automaation ja tuotosseurannan välillä

Tiedonsiirto helposti navetta-automaation ja tuotosseurannan välillä Tiedonsiirto helposti navetta-automaation ja tuotosseurannan välillä Tiedonsiirto VMS-, Alpro- tai DelProtuotannonohjausjärjestelmästä Ammuohjelmistoon 5/2014 Asennettavat ohjelmat ja versiot VMS-Management

Lisätiedot

Artikkelien muokkaaminen sekä sisältöeditorin peruskäyttö

Artikkelien muokkaaminen sekä sisältöeditorin peruskäyttö Artikkelien muokkaaminen sekä sisältöeditorin peruskäyttö Sisällysluettelo Kirjautuminen ja ylläpito...3 Kirjautuminen sivustolle...3 Ylläpitovalikko...3 Artikkeleiden muokkaaminen...4 Artikkelin asetukset...4

Lisätiedot

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python Ohjelmoinnin perusteet Y Python T-106.1208 1.4.2009 T-106.1208 Ohjelmoinnin perusteet Y 1.4.2009 1 / 56 Tentti Ensimmäinen tenttimahdollisuus on pe 8.5. klo 13:00 17:00 päärakennuksessa. Tämän jälkeen

Lisätiedot

Valitse aineisto otsikoineen maalaamalla se hiirella ja kopioimalla (Esim. ctrl-c). Vaihtoehtoisesti, Lataa CSV-tiedosto

Valitse aineisto otsikoineen maalaamalla se hiirella ja kopioimalla (Esim. ctrl-c). Vaihtoehtoisesti, Lataa CSV-tiedosto Versio k15 Näin laadit ilmastodiagrammin Libre Officen taulukkolaskentaohjelmalla. Ohje on laadittu käyttäen Libre Officen versiota 4.2.2.1. Voit ladata ohjelmiston omalle koneellesi osoitteesta fi.libreoffice.org.

Lisätiedot

Ohjelmoinnin peruskurssi Y1

Ohjelmoinnin peruskurssi Y1 Ohjelmoinnin peruskurssi Y1 CSE-A1111 30.9.2015 CSE-A1111 Ohjelmoinnin peruskurssi Y1 30.9.2015 1 / 27 Mahdollisuus antaa luentopalautetta Goblinissa vasemmassa reunassa olevassa valikossa on valinta Luentopalaute.

Lisätiedot

NAVITA BUDJETTIJÄRJESTELMÄN ENSIASENNUS TYÖASEMALLE

NAVITA BUDJETTIJÄRJESTELMÄN ENSIASENNUS TYÖASEMALLE NAVITA BUDJETTIJÄRJESTELMÄN ENSIASENNUS TYÖASEMALLE 1) Navita Budjettijärjestelmä asennetaan palvelimelle asennetusta Navita\NavitaSetup kansiosta Setup komennolla tämä mahdollistaa Navita-työasemien automaattisen

Lisätiedot

Maiju Mykkänen (D6297@jamk.fi) Susanna Sällinen (E0941@jamk.fi)

Maiju Mykkänen (D6297@jamk.fi) Susanna Sällinen (E0941@jamk.fi) Maiju Mykkänen (D6297@jamk.fi) Susanna Sällinen (E0941@jamk.fi) Tietokannan hallinta-opintojakson selvitysraportti Huhtikuu 2010 Mediatekniikka ICT/Teknologia Tämän teosteoksen käyttöoikeutta koskee Creative

Lisätiedot

Written by Administrator Monday, 05 September 2011 15:14 - Last Updated Thursday, 23 February 2012 13:36

Written by Administrator Monday, 05 September 2011 15:14 - Last Updated Thursday, 23 February 2012 13:36 !!!!! Relaatiotietokannat ovat vallanneet markkinat tietokantojen osalta. Flat file on jäänyt siinä kehityksessä jalkoihin. Mutta sillä on kuitenkin tiettyjä etuja, joten ei se ole täysin kuollut. Flat

Lisätiedot

HENKILÖLISTA-PALVELU Käyttöohjeet versio 13.5.2013

HENKILÖLISTA-PALVELU Käyttöohjeet versio 13.5.2013 HENKILÖLISTA-PALVELU Käyttöohjeet versio 13.5.2013 Henkilölista -palvelu 1 Sisältö 1. Veronumerolaki ja raportointi... 2 2. Henkilölista-palvelun sisältö... 2 2.1. Palvelun käyttötarkoitus ja hyödyt...

Lisätiedot

Nuorten hyvinvointi tilastotietokannan käyttöohjeet Tieke 18.5 2015

Nuorten hyvinvointi tilastotietokannan käyttöohjeet Tieke 18.5 2015 Nuorten hyvinvointi tilastotietokannan käyttöohjeet Tieke 18.5 2015 Taulukon valinta Valitse vasemmalta kansioita, kunnes saat taulukkoluettelon näkyviin. Jos etsit tietoa jostain tietystä aiheesta, voit

Lisätiedot

MICROSOFT EXCEL 2010

MICROSOFT EXCEL 2010 1 MICROSOFT EXCEL 2010 Taulukkolaskentaohjelman jatkokurssin tärkeitä asioita 2 Taulukkolaskentaohjelmalla voit Käyttää tietokonetta ruutupaperin ja taskulaskimen korvaajana Laatia helposti ylläpidettäviä

Lisätiedot

Ohje. Perusdiabetesseurantataulukko: OpenOffice 3.2 Ohjeen versio: 1.0

Ohje. Perusdiabetesseurantataulukko: OpenOffice 3.2 Ohjeen versio: 1.0 Ohje Perusdiabetesseurantataulukko: OpenOffice 3.2 Ohjeen versio: 1.0 Tämän ohjeen tarkoituksen on tutustuttaa sinut Diabetesseurantataulukon käyttöön. Ohjeen lähtökohtana on, että et ennestään hallitse

Lisätiedot

ASCII-taidetta. Intro: Python

ASCII-taidetta. Intro: Python Python 1 ASCII-taidetta All Code Clubs must be registered. Registered clubs appear on the map at codeclubworld.org - if your club is not on the map then visit jumpto.cc/18cplpy to find out what to do.

Lisätiedot

Ylläpitoalue - Etusivu

Ylläpitoalue - Etusivu Crasmanager 5.2 Ylläpitoalue - Etusivu Sivut osiossa sisällön selaus ja perussivujen ylläpito. Tietokannat osiossa tietokantojen ylläpito. Tiedostot osiossa kuvien ja liitetiedostojen hallinta. Työkalut

Lisätiedot