Kun aineisto on saatu ajettua R-ympäristöön, on seuraavaksi syytä tutustua siihen tarkemmin ja tarkistaa että muuttujat ovat oikeassa muodossa, jotta ne käyttäytyvät analyyseissä halutulla tavalla. Varsinkin alkuvaiheessa välttyy useilta turhauttavilta erroreilta jos muuttujat ovat halutussa muodossa.
Kaikki R-kielessä käytetyilä muuttujilla on oma luokka (class), joka vaikuttaa muuttujan käyttömahdollisuuksiin. Datan käsittelyssä yleisimpiä luokkia ovat:
- character eli merkkijono:
"a"
,"kaatunut"
- Date eli päivämäärä:
22-06-2020
- factor eli kategorinen muuttuja:
"vasen"
,"oikea"
- integer eli kokonaisluku:
3L
(L
pitää muuttujan kokonaislukuna R:ssä) - logical eli totuusarvo:
TRUE
taiFALSE
- numeric eli numeerinen:
2
,3.14
Kun haluaa selvittää, missä muodossa R-ympäristöön tallennetun aineiston muuttujat ovat, se onnistuu helpoiten funktiolla str(data)
, joka näyttää havaintojen sekä muuttujien määrän, muuttujien luokan sekä esimerkin muutamasta aineistossa olevasta havainnosta.
str(mtcars)
‘data.frame’: 32 obs. of 11 variables:
$ mpg : num 21 21 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 …
$ cyl : num 6 6 4 6 8 6 8 4 4 6 …
$ disp: num 160 160 108 258 360 …
$ hp : num 110 110 93 110 175 105 245 62 95 123 …
$ drat: num 3.9 3.9 3.85 3.08 3.15 2.76 3.21 3.69 3.92 3.92 …
$ wt : num 2.62 2.88 2.32 3.21 3.44 …
$ qsec: num 16.5 17 18.6 19.4 17 …
$ vs : num 0 0 1 1 0 1 0 1 1 1 …
$ am : num 1 1 1 0 0 0 0 0 0 0 …
$ gear: num 4 4 4 3 3 3 3 4 4 4 …
$ carb: num 4 4 1 1 2 1 4 2 2 4 …
Lisäksi yksittäisen muuttujan arvon voi tarkistaa funktiolla class()
class(mtcars$cyl)
[1] “numeric”
Kaikki edellä mainitut luokat ovat R:ssä objekteja (object). Edellä mainittujen luokkien lisäksi R tukee lukuisia erilaisia objekteja (kuten vektoreita, listoja, data frameja ym), joita ei tässä yhteydessä käsitellä syvällisemmin.
Tidyverse
Datan tarkastelun jälkeen on vuorossa muutoksia vaativien asioiden korjaaminen. Tähän ns. datan puhdistamiseen on R:ssä monia paketteja, joista yksi suosituimmista on tidyverse
-paketti.
Tidyverse koostuu useammasta paketista, joista datan muokkauksessa ja visualisoinnissa erityisen hyödyllisiä ovat:
readr
– Aineiston tuominen RStudioondplyr
– Aineiston tehokas muokkaaminentidyr
– Aineiston muuttaminen tidy -muotoonggplot2
– Laadukkaiden kuvaajien tekeminen
Kaikki yllä mainitut paketit ovat hyödyllisiä aineiston muokkaamisessa sekä visualisoinnissa, ja niihin kaikkiin kannattaa tutustua tarkemmin esim. tidyverse
n kotisivulla. Samalta sivulta löytyy myös ns. Cheatsheetit, joihin on kerätty selkeät esimerkit kunkin paketin tärkeimmistä funktioista. Tässä ohjeessa keskitytään vain dplyr
-pakettiin.
Dplyr
on kehitetty tehokasta aineiston muokkaamista varten, ja sen hyödyllisyys rakentuu muutaman yksinkertaisen funktion ympärille. Koska aineiston muokkaaminen on useimmien eniten aikaa vievä vaihe data-analysiikassa, on se syytä opetella jo alusta asti tekemään mahdollisimman suoraviivaisesti.
Dplyr
:n tärkeimmät aineiston muokkaukseen tarkoitetut funktiot ovat:
filter()
– Suodattaa halutut rivit haluttujen ehtojen perusteella.select()
– Valitsee kolumnit haluttujen ehtojen perusteella.mutate()
– Luo uuden kolumnin aiempien muuttujien funktionasummarize()
– Yhdistää useamman havainnon tiedot yhteenvedoksi.group_by()
– funktio jolla voidaan valita ryhmittelevä muuttuja. Toimii edellä mainittujen funktioiden kanssa.
Aineiston puhdistaminen
Aloitetaan lataamalla RStudioon tarvittavat paketit. Kun uutta pakettia käyttää ensimmäisen kerran, tulee se ladata käyttämällä funktiota install.packages()
jossa sulkeisiin tulee halutun paketin nimi lainausmerkeissä.
install.packages("tidyverse")
Kun paketti on tallennettu jo aiemmin, se tulee ladata RStudioon aina kun ohjelmiston avaa uudelleen käyttämällä funktiota library()
library(tidyverse)
Koska aineiston putsaaminen kannattaa opetella alusta saakka mahdollisimman tehokkaasti, aloitamme tässä ohjeessa dplyr
-pakettiin tutustumisen heti käyttäen ns. pipea (koodissa %>%). Pipe mahdollistaa useiden funktioiden käyttämisen putkeen, sillä se syöttää automaattisesti edellisrivien datan seuraavaan funktioon. Pipen käyttömahdollisuuksista syvällisemmin esim. kirjassa R for Data Science.
Tämän artikkelin esimerkeissä funktioita käytetään niin, että tulos tulee näkyviin RStudion alareunassa olevaan consoleen. Oikeassa elämässä aineisto kuitenkin halutaan tallentaa R-ympäristöön, joka onnistuu tallentamalla (<-
) lopputulos uuteen objektiin:
df <- mtcars %>%
filter(am==1)
Nyt suodatettu aineisto on tallennettu Environment-laatikkoon nimellä df (data frame).
Esimerkeissä käytetään aineistoa mtcars, jonka tarkemmat tiedot löytyvät internetistä tai hakemalla RStudiosta ?mtcars
. Esimerkeissä käsitellään funktioiden käyttöä aloittelijatasolla, jotta niiden ymmärtäminen olisi ensimmäistä kertaa R:ä käyttävälle helpompaa. Monimutkaisempia käyttötarkoituksia varten alla käsiteltyihin funktioihin kannattaa tutustua esim. Tidyversen kotisivulla tai kirjoista R for Data Science ja Advanced R.
Filter
Useimmiten kerätystä aineistosta joudutaan rajaamaan osa havainnoista pois ennen analyysien tekemistä. Lisäksi aineistosta voidaan tehdä alaryhmäanalyysejä, joihin halutaan sisällyttää vain tietty potilasjoukko mukaan. Kuvitellaankin tilanne, että haluamme tehdä analyysejä mtcars-aineistosta vain niillä autoilla, joissa on manuaalivaihteisto. Tämä tieto löytyy muuttujasta “am”, jossa 0=automaatti ja 1=manuaalivaihteisto.
Käyttämällä funktiota filter()
voimme “suodattaa” mukaan vain ne rivit, joilla am muuttuja saa arvon 1. Siten tässä tilanteessa haluamme, että muuttuja am
on yhtä kuin 1. R:ssä kahden objektin vertaamiseen käytetään merkkiä ==
.
filter(mtcars, am==1)
Nyt jäljelle jää ainoastaan muuttujat, joiden am sarakkeessa on arvo 1 (manuaali).
Täysin sama lopputulos saadaan kirjoittamalla ensin aineiston nimi (mtcars) ja sen perään pipe (%>%
), jolloin filter() funktion ensimmäiseksi arvoksi tulee data mtcars
. Koodi on myös luettavampaa, jos aina pipen jälkeen koodin aloittaa uudelta riviltä.
mtcars %>%
filter(am==1)
Pipen hyödyllisyys ei tule juuri ilmi yksittäisen funktion kohdalla, mutta tämän artikkelin lopussa yhdistellään useampia funktioita, jossa pipen hyödyllisyys tulee todella esiin.
Mikäli halutaan lisätä muita ehtoja suodattamiseen, voidaan valita ne käyttämällä merkkejä &
(ja), |
(tai). Esimerkkinä alla on valittu vain ne autot, joissa on manuaalivaihteisto ja V-moottori, sekä 4- tai 6 sylinteriä
mtcars %>%
filter(am==1 & vs==0 & (cyl==4 | cyl==6))
Select
Aineistot usein sisältävät ylimääräisiä muuttujia, tai muuttujia joita ei sisällytetä kaikkiin analyyseihin. Koska aineiston analysointi on helpompaa jos mukana on vain muuttujat joita käytetään, on välillä syytä jättää osa muuttujista pois aineistosta.
Select()
-funktiolla voidaan valita vain halutut muuttujat uuteen aineistoon. Yksinkertaisimmin valinta voidaan tehdä joko kirjoittamalla jokainen mukaan haluttu muuttuja erikseen.
mtcars %>%
select(mpg, cyl, disp)
Sama valinta voidaan tehdä myös valitsemalla muuttujat järjestyksessä erottaen ne merkillä:
.
mtcars %>%
select(mpg:disp)
Yksi käytännöllinen tapa on myös jättää vain tietyt ei-halutut muutujat pois merkillä -
.
mtcars %>%
select(-vs, -drat)
Muuttujat voi myös valita niiden järjestysnumeron perusteella.
mtcars %>%
select(1,2,3)
mtcars %>%
select(1:3)
mtcars %>%
select(-4:-11)
Näiden lisäksi funktiolla on monia vaihtoehtoisia tapoja, joihin voi tutustua esim täällä.
Mutate
Usein aineisto sisältää muuttujia, joita täytyy muokata, jotta niitä voidaan käyttää analyyseissä. Tyypillisiä esimerkkejä ovat syntymäajan muuttaminen iäksi, jatkuvan muuttujan muuttaminen kategoriseksi, ja tapauksien määrän muuttaminen ilmaantuvuudeksi.
Mutate()
-funktiolla voidaan luoda uusia muuttujia jo aineistossa olevista muuttujista matemaattisia yhtälöitä hyödyntäen. Usein ensimmäinen tarve aineiston muokkaukselle tulee, kun muuttujien luokkia tulee muuttaa. Esimerkiksi mtcars aineistossa sylinterien määrä (cyl
) voitaisiin vaihtaa numeerisesta (numeric) kategoriseksi (factor).
mtcars %>%
mutate(cyl= factor(cyl))
Mikäli monta muutosta halutaan tehdä kerralla, se onnistuu erottamalla muutokset pilkulla. Esimerkiksi jos myös muuttuja vs
halutaan muuttaa myös kategoriseksi:
mtcars %>% mutate(cyl= as.factor(cyl),
vs = as.factor(vs))
Aineiston muuttujien luokkien muuttamiseen on kehitetty omat funktiot, joita voi käyttää täysin samalla tavalla kuin edellisen esimerkin as.factor()
funktiota:
as.character()
– merkkijonoas.Date()
– päivämäärä
– numeerinenas.numeric()
Mutate()
:n vahvuus on erityisesti siinä, kun uusi muuttuja halutaan tehdä aiemmasta muuttujasta laskutoimituksen avulla. Esimerkiksi ajoneuvon paino on muuttujassa wt
tuhansina (1000) paunoina. Jos paino halutaan paunoiksi, tulee wt
muuttaa 1000-kertaiseksi:
mtcars %>%
mutate(wt = wt*1000)
Jos paino halutaankin saada kilogrammoiksi, voidaan luoda uusi muuttuja kg
, joka saadaan muuttamalla wt
ensin paunoiksi kertomalla se tuhannella, ja sen jälkeen jakamalla se muuntokertoimella 2.0246:
mtcars %>%
mutate(kg = wt*1000/2.2046)
Näin saamme muuttujan kg, jossa ajoneuvon paino on kilogrammoina.
Summarise
Aineistosta kannattaa aluksi poistaa ylimääräiset havainnot, sekä turhat muuttujat filter()
ja select()
-funktioiden avulla, sekä muokata muuttujat haluttuun muotoon mutate()
-funktiolla. Tämän jälkeen aineisto on valmiina tarkempaa tarkastelua ja analysointia varten.
Summarise()
-funktio tekee nimensä mukaisesti yhteenvedon useammasta aineiston rivistä uudeksi riviksi. Näin ollen, summarise()
menee osittain jo datan analysoinnin puolelle, vaikka sillä voidaan tehdä myös aineiston puhdistamiseen liittyviä toimenpiteitä. Funktio toimii syöttämällä siihen haluttuja funktioita, joiden perusteella yhteenveto muodostuu.
Esimerkiksi jos haluamme tietää aineistossa olevien autojen hevosvoimien (hp
) keski-arvon (mean) sekä keskihajonnan (sd), voidaan se selvittää seuraavasti:
mtcars %>%
summarise(hp_mean=mean(hp), hp_sd=sd(hp))
hp_mean hp_sd
1 146.6875 68.56287
Nyt saamme tulokseksi uuden rivin, jossa muuttuja hp_mean
kertoo hp
-muuttujan keskiarvon, sekä hp_sd
keskihajonnan.
Summarise()
toimii samalla tavalla myös muiden tunnuslukujen kanssa:
- Keskiarvo, mediaani:
mean()
,median()
- Keskihajonta, kvartaaliväli:
sd()
,IQR()
- Minimi, maksimi ja kvantiili:
min()
,max()
,quantile()
- Havaintojen määrä:
n()
,n_distinct()
Näitä voidaan siis käyttää täysin samalla tavalla kuin edellisessä esimerkissä käytettiin mean()
ja sd()
funktioita.
Group_by
Group_by()
-funktio toimii kätevästi edellä esiteltyjen funktioiden lisänä. Sen avulla dataan tehtävät muutokset ja analyysit voidaan tehdä rymittelevän muuttujan perusteella jaettuna. Esimerkiksi edellisen esimerkin hevosvoimien keskiarvo ja keskihajonta voidaan katsoa erikseen 4-, 6- ja 8- sylinterisille autoille, lisäämällä ennen summarise()
-funktiota group_by() ja ryhmitteleväksi muuttujaksi cyl
.
mtcars %>%
group_by(cyl) %>%
summarise(hp_mean=mean(hp), hp_sd=sd(hp))
cyl hp_mean hp_sd
4 82.6 20.9
6 122. 24.3
8 209. 51.0
Samat tulokset saadaan katsottua myös manuaali- ja automaattivaihteisissa autoissa erikseen vaihtamalla ryhmitteleväksi muuttujaksi am
-muuttujan.
mtcars %>%
group_by(am) %>%
summarise(hp_mean=mean(hp), hp_sd=sd(hp))
am hp_mean hp_sd
0 160. 53.9
1 127. 84.1
Funktioiden yhdistely pipen avulla
Ohjelmoinnissa kannattaa aina pyrkiä mahdollisimman siistiin koodiin, jossa ei ole turhia vaiheita tai tyhjiä rivejä. Kun koodia lukee itse tai joku toinen, on tärkeää, että se on mahdollisimman ymmärrettävää ja helppolukuista.
Edellä esiteltyjä funktioita voi hyvinkin käyttää niin, että yhtä funktiota käyttää aina kerrallaan, ja tallentaa datan aina uuteen objektiin (esim. df1, df2, jne.). Tuolloin kuitenkin koodin alkuosaan tehty muutos vaatii aina jokaisen erillisen koodin ajamisen, joka vie aikaa ja altistaa virheille. Lisäksi Environment täyttyy aineiston eri vaiheista, joka altistaa väärän objektin käyttämiselle, joka myös johtaa turhiin virheisiin ja erroreihin.
Tämän ongelman voi kiertää yhdistelemällä edellä kuvatut fuktiot samaan pipeen ja tallentaa suoraan yhdeksi puhdistetuksi aineistoksi.
df <- mtcars %>%
filter(am==1) %>% # vain manuaalit mukaan
select(1:6) %>% # vain muuttujat 1-6 mukaan
mutate(kg = wt*1000/2.2046) #paino muutetaan kiloiksi
Nyt aineisto, joka on tallennettu objektiksi df
on puhdistettu ja valmiina tarkempia tarkasteluja ja analyysejä varten.
df %>%
group_by(cyl) %>%
summarise(kg_mean=mean(kg), kg_sd=sd(kg))
cyl kg_mean kg_sd
4 926. 186.
6 1250. 58.1
8 1529. 128.
Näitä edellä käytyjä funktioita hyödyntäen pystyy tehdä lähes kaiken alkuvaiheessa tarvittavan aineiston putsaamisen ja perusanalyysit. Funktioihin kannattaa aluksi tutustua valmiiden aineistojen kanssa, mutta melko nopeasti kannattaa siirtyä tosielämän aineistoihin. Aineiston putsaamiseen pääsee kunnolla kiinni vain ja ainoastaan itse tekemällä. Seuraavaksi siis omien aineistojen kimppuun!
Lisää tietoa aiheesta:
- Tidyverse – Hyödyllinen R-paketti data-analytiikassa
- R for Data Science – Ilmainen oppikirja
- Advanced R – Ilmainen oppikirja edistyneempään ohjelmointiin