tidyverse
Pakett tidyverse
on andmeanalüüsi n-ö komplekspakett,
mis koondab enda alla terve hulga teisi pakette ja nende funktsioone (sh
ggplot2
). Ehkki enamikku sellest, mida need funktsioonid
teevad, saab ära teha ka teiste pakettide ja funktsioonidega, ühendab
tidyverse’i pakette sarnane kasutusloogika ja sarnaste
andmestruktuuride kasutus.
Tidyverse’i pakette saab installida ka ükshaaval (nt
install.packages("tidyr")
). Kiire ülevaate üksikute
pakettide põhifunktsioonidest saad nt erinevatest spikritest:
ggplot2
spikkerdplyr
spikkertidyr
spikkerpurr
spikkerreadr
spikkerstringr
spikkerforcats
spikkerSelles praktikumis kasutame tidyverse
’i kollektsioonist
pakette dplyr
ja
tidyr
(andmete
töötlemiseks) ja ggplot2
(andmete
visualiseerimiseks).
Tidyverse’i installimiseks kasuta käsku
install.packages("tidyverse")
ning laadimiseks
library(tidyverse)
.
Ära muretse, kui paketi laadimise käigus konsooli midagi trükitakse (kui tegemist pole just erroriga).
Loeme sisse ka valimiste andmestiku, mida siin põhiliselt kasutame.
Tidyverse’i pakette ühendab sarnane kindlas järjekorras
asjade tegemise loogika. Üks paketi oluline omadus on võimalus kasutada
nn torusid ehk pipe’e (sümbol
%>%
), mille funktsioon tuleb tegelikult
tidyverse
’iga koos installitavast ja laaditavast paketist
nimega magrittr
.
Torud lubavad tõsta R-i n-ö pesastatud funktsioonidest funktsioone välja
nende käivitamise järjekorra alusel, suunates iga
eelmise käsu väljundi järgmisse käsku.
Kui R-i baaspaketis on kõige viimane käsk graafiliselt kõige esimene,
siis torud lubavad teha neid asju loogilisemas järjekorras. Näiteks kui
tahame 1) võtta tabelist kandidaatide soo tulba, 2) teha soo tunnuse
väärtustest sagedustabeli, 3) leida absoluutsageduste põhjal suhtelised
sagedused, siis oleks baaspaketi ja tidyverse
paketi
lahenduskäigud graafiliselt justkui peegelpildis.
# Leia mees- ja naiskandidaatide suhtelised sagedused
# baaspakett
prop.table(table(valimised$sugu))
# tidyverse
valimised$sugu %>% table() %>% prop.table()
# Kui saad teate 'could not find function "%>%"', tähendab see seda,
# et tidyverse'i pakett on ilmselt lihtsalt library(tidyverse) käsuga laadimata jäänud.
Või kui tahaksime lahendada natuke keerulisemat ülesannet, nt leida kandidaatide ametinimetustes (vaba tekstiga tunnus) esinevad 50 sagedamat sõna, oleks baaspaketi käsk üpris keeruliselt loetav.
# baaspakett
head(sort(table(gsub("[[:punct:]]", "", tolower(unlist(str_split(valimised$amet, " "))))), decreasing = T), 50)
# tidyverse
valimised$amet %>% # võta valimiste andmestikust tulp "amet"
str_split(" ") %>% # lõika ameti kirjeldused tühikute koha pealt sõnadeks
unlist() %>% # tee sõnalistist tavaline vektor
tolower() %>% # tee kõik vektori sõnad väiketähelisteks
gsub("[[:punct:]]", "", .) %>% # kustuta sõnade küljest kirjavahemärgid
table() %>% # tee puhastatud sõnadest sagedustabel
sort(decreasing = T) %>% # sorteeri sagedustabel kahanevas järjekorras
head(50) # võta sorteeritud tabelist esimesed 50 sõna
Lisame koodi ühe rea, mis jätaks ametinimetustest alles ainult viimase sõnavormi (nt Riigikogu liige -> liige).
# tidyverse
valimised$amet %>%
str_split(" ") %>%
lapply(., function(x) x[length(x)]) %>% # igast ametinimetusest võta ainult viimane sõnavorm
unlist() %>%
tolower() %>%
gsub("[[:punct:]]", "", .) %>%
table() %>%
sort(decreasing = T) %>%
head(50)
## .
## liige esimees juhataja nõunik direktor
## 227 45 41 34 33
## pensionär vallavanem õpetaja tegevjuht juht
## 31 26 24 23 20
## abivallavanem abilinnapea üliõpilane aseesimees projektijuht
## 19 17 14 10 10
## koordinaator minister linnapea oü puudub
## 8 8 7 7 7
## vanem ettevõtja omanik professor spetsialist
## 7 6 6 6 6
## treener õppejõud arendusjuht jurist kodune
## 6 6 5 4 4
## konsultant näitleja peaspetsialist perearst toimetaja
## 4 4 4 4 4
## tudeng abi arst disainer muusik
## 4 3 3 3 3
## müügijuht produtsent raamatupidaja teadur vabakutseline
## 3 3 3 3 3
## ajakirjanik asetäitja audiitor dotsent ekspert
## 2 2 2 2 2
Nagu baaspaketis ei ole vahet, kas komadega eraldatud argumendid on
eraldi ridadel või ühel real, ei ole seda vahet ka
tidyverse’is. Samuti ei ole vahet, kas torudega eraldatud
funktsioonid jätta samale reale või viia need eraldi ridadele.
Tidyverse’i toru kiiremaks kasutamiseks võid kasutada ka
klahvikombinatsiooni Ctrl+Shift+M
(Macis
Shift+Cmd+M
).
Tõele au andes on uuemates R-i versioonides ka baaspaketis juba oma
toru |>
, mis töötab enam-vähem samamoodi nagu
tidyverse’i toru. Selles aga ei saa näiteks viidata
funktsioonis andmetele tagasi punktiga.
# Mitu erinevat eesnime kandidaatide hulgas leidub?
# töötab
gsub("^([^ ]+?) .*$", "\\1", valimised$nimi) |>
unique() |>
length()
# ei tööta
valimised$nimi |>
gsub("^([^ ]+?) .*$", "\\1", .) %>%
unique() |>
length()
Kumba või kas üldse kasutada on maitse küsimus, aga kui juba muid
tidyverse’i funktsioone on vaja kasutada, tundub loogilisem
kasutada ka vastavat toru %>%
.
Baaspaketis oleme harjunud andmestikest mingi konkreetse alamosa väljavõtmiseks kasutama kantsulgusid ning nende sees võrratusi. Kordamiseks põhilised võrratustes kasutatud tehted:
Sümbol | Näide | Selgitus | Sobiv tunnusetüüp |
---|---|---|---|
== |
a == b |
a võrdub b-ga | arvulised, kategoriaalsed, loogilised |
!= |
a != b |
a ei võrdu b-ga | arvulised, kategoriaalsed, loogilised |
> |
a > b |
a on suurem kui b | arvulised, loogilised |
< |
a < b |
a on väiksem kui b | arvulised, loogilised |
>= |
a >= b |
a on suurem/võrdne b-ga | arvulised, loogilised |
<= |
a <= b |
a on väiksem/võrdne b-ga | arvulised, loogilised |
Lisaks on kasulik funktsioon is.na()
, mis otsib välja
ainult read või elemendid, mille väärtus on NA (nt
is.na(a)
) või ei ole NA (!is.na(a)
).
Liittehted:
Sümbol | Näide | Selgitus |
---|---|---|
& |
a == b & a != c |
a on võrdne b-ga JA a ei ole võrdne c-ga |
| |
a == b | a == c |
a on võrdne b-ga VÕI a on võrdne c-ga |
%in% |
a %in% c(b, c, d) |
a väärtus on b VÕI c VÕI d |
!%in% |
!a %in% c(b, c, d) |
a väärtus ei ole b EGA c EGA d |
Keerulisemate võrratuste puhul võib pilt minna päris kirjuks.
# ainult Keskerakonna nimekirja kandidaatide andmed
valimised[valimised$nimekiri == "Eesti Keskerakond",]
# kõikide erakondade, v.a Keskerakonna nimekirja alla 30-aastaste kandidaatide andmed
valimised[valimised$nimekiri != "Eesti Keskerakond" & valimised$vanus < 30,]
# nende Eesti 200 või Roheliste kandidaatide nimed, kes on alla 30-aastased
valimised[(valimised$nimekiri == "Erakond Eesti 200" | valimised$nimekiri == "Erakond Eestimaa Rohelised") & valimised$vanus < 30, "nimi"]
# või
valimised[valimised$nimekiri %in% c("Erakond Eesti 200", "Erakond Eestimaa Rohelised") & valimised$vanus < 30, "nimi"]
# kõikide vähemalt 70-aastaste, v.a Eesti 200 ja Roheliste nimekirja kuuluvate kandidaatide nimed, sünniajad ja tähtkujud
valimised[valimised$nimekiri != "Erakond Eesti 200" & valimised$nimekiri != "Erakond Eestimaa Rohelised" & valimised$vanus >= 70, c("nimi", "sünniaeg", "tähtkuju")]
# või
valimised[!valimised$nimekiri %in% c("Erakond Eesti 200", "Erakond Eestimaa Rohelised") & valimised$vanus >= 70, c("nimi", "sünniaeg", "tähtkuju")]
Tidyverse lubab meil kasutada funktsiooni
filter()
ridade filteerimiseks ning
funktsiooni select()
tulpade valimiseks.
Sealjuures säilitab select()
andmetabeli struktuuri.
# ainult Keskerakonna nimekirja kandidaatide andmed
# valimised[valimised$nimekiri == "Eesti Keskerakond",]
valimised %>%
filter(nimekiri == "Eesti Keskerakond")
# ainult nime tulp
valimised %>%
select(nimi)
# kõik tulbad peale nime
valimised %>%
select(-nimi)
Kui tahame pärast toru võtta mingi tulba välja vektorina (või
faktorina), saame viidata tervele tabelile punktiga:
... %>% .$tulp
. Punkt on nn placeholder, mis
laseb torudega toimetades viidata vahetult eelmise käsu väljundile.
Tulba küsimiseks vektorina võib kasutada ka tidyverse’i
funktsiooni pull()
. Kui tahta funktsiooni
kasutada faktoril, tuleb faktor esmalt tavaliseks tekstivektoriks
teisendada.
Mitme tingimusega filtreerimiseks võime kasutada ära torusid ja rakendada igat filtrit eraldi käsuna või liita tingimused samamoodi, nagu seda saab teha baaspaketis.
# kõikide erakondade, v.a Keskerakonna nimekirja kandidaatide andmed, kes on alla 30-aastased
# valimised[valimised$nimekiri != "Eesti Keskerakond" & valimised$vanus < 30,]
valimised %>%
filter(nimekiri != "Eesti Keskerakond") %>%
filter(vanus < 30)
# või
valimised %>%
filter(nimekiri != "Eesti Keskerakond", vanus < 30)
# või
valimised %>%
filter(nimekiri != "Eesti Keskerakond" & vanus < 30)
# nende Eesti 200 või Roheliste kandidaatide nimed, kes on alla 30-aastased
# valimised[valimised$nimekiri %in% c("Erakond Eesti 200", "Erakond Eestimaa Rohelised") & valimised$vanus < 30, "nimi"]
valimised %>%
filter(nimekiri %in% c("Erakond Eesti 200", "Erakond Eestimaa Rohelised"), vanus < 30) %>%
select(nimi)
# võrdle
valimised %>%
filter(nimekiri %in% c("Erakond Eesti 200", "Erakond Eestimaa Rohelised"), vanus < 30) %>%
pull(nimi)
# kõikide vähemalt 70-aastaste, v.a Eesti 200 või Roheliste nimekirja kuuluvate kandidaatide nimed, sünniajad ja tähtkujud
# valimised[!valimised$nimekiri %in% c("Erakond Eesti 200", "Erakond Eestimaa Rohelised") & valimised$vanus >= 70, c("nimi", "sünniaeg", "tähtkuju")]
valimised %>%
filter(!nimekiri %in% c("Erakond Eesti 200", "Erakond Eestimaa ROhelised"), vanus >= 70) %>%
select(nimi, sünniaeg, tähtkuju)
Saame filtreerimisel kasutada ka teiste pakettide (sh vaikimisi
laaditud baaspaketi ja stats
paketi) funktsioone.
Harjutus 1
Leia valimiste andmestikust torusid kasutades mõne sind huvitava kandidaadi (või mitme kandidaadi) kontaktandmed.
Harjutus 2
Laadi RStudiosse kursuse küsimustiku andmestik. Leia torusid kasutades, millisel aastal on olnud kursusel kõige rohkem kohvijoojaid. Ärme esialgu sellepärast muretseme, kui palju osalejaid mingil aastal üldse kursuselt läbi käis, ehkki see mõjutab oluliselt ka kohvijoojate absoluutarve.
table()
.which.max()
.names()
.Andmete järjestamiseks mingi tulba väärtuste alusel võib kasutada
funktsiooni arrange()
.
valimised %>%
arrange(hääli_kokku) %>% # kasvavas järjekorras
select(nimekiri, nimi, hääli_kokku, e.hääli)
valimised %>%
arrange(desc(hääli_kokku)) %>% # kahanevas järjekorras
select(nimekiri, nimi, hääli_kokku, e.hääli)
Võime järjestada andmeid ka mitme tunnuse järgi korraga.
Tulpade lisamiseks tabelisse saab kasutada funktsiooni
mutate()
.
Lisame näiteks valimiste tabelisse tulba, kuhu arvutame iga kandidaadi häältesaagi ilma e-häälteta.
Kui tahame, et lisatud tulbad ka andmestikku alles jääksid, peame andmestiku kas üle kirjutama või suunama lisatud tulpadega tabeli uude objekti.
Tidyverse’i üks suuri plusse on see, et me ei pea vaheväljundeid eraldi objektidesse salvestama, kui tahame neid ainult korraks konkreetseks eesmärgiks kasutada. Nii võime ka kogu andmete puhastamise ja korrastamise protsessi väljundi suunata otse graafikule.
# Kuva karpdiagrammil paberhäälte protsendi jaotumist valimisnimekirjades
valimised %>%
mutate(paberhäälte_protsent = hääli_paberil/hääli_kokku*100) %>%
ggplot(aes(y = reorder(nimekiri, paberhäälte_protsent), # järjesta nimekirjad protsendi tunnuse alusel (vaikimisi rühma keskmise järgi)
x = paberhäälte_protsent)) +
geom_boxplot() +
labs(y = "Nimekiri", x = "Paberhäälte protsent")
Harjutus 3
Näita joonisel, milline oli kandidaatide vanuste jaotus erakondades ning kas vanus mõjutas kuidagi ka (logaritmitud) häältesaaki.
geom_vline()
, mis tahab oma
aes()
-funktsiooni argumendiks xintercept
’i ehk
x-teljega lõikumise kohta. Selle väärtuseks peaks määrama terve
andmestiku kandidaatide mediaanvanuse.valimised %>%
ggplot() +
geom_boxplot(aes(y = nimekiri, x = vanus)) +
geom_vline(aes(xintercept = median(vanus)), color = "red", linetype = "dashed", linewidth = 1)
log(tunnus)
). Punktide läbipaistvust saab
kontrollida argumendiga alpha
, mille väärtus saab jääda 0
(täiesti läbipaistev) ja 1 (täiesti läbipaistmatu) vahele. Nn
trendijoone saab joonistada funktsiooniga
geom_smooth()
.valimised %>%
ggplot(aes(x = vanus, y = log(hääli_kokku))) +
geom_point(alpha = 0.3) +
geom_smooth()
Harjutus 4
Oletame, et keegi küsib meilt Keskerakonna nimekirjas kandideerinute
meiliaadresse. Meiliaadressid on tulbas kontaktandmed
, aga
seal on ka telefoninumbrid, tavalised aadressid, Facebooki lehed jm.
Peaksime niisiis kasutama pisut regulaaravaldisi, et meiliaadressid
eraldi kätte saada ja uude tulpa lisada. Ära muretse, kui sa
regulaaravaldisi veel ei tunne.
nimekiri
väärtus on
“Eesti Keskerakond”.meil
, kuhu saad väärtused käsuga
ifelse(test = grepl("@", kontakt), yes = str_split(kontakt, "; ") %>% unlist() %>% .[grepl("@", .)], no = "")
.
Käsus küsitakse esmalt, kas kandidaadi kontaktandmetes on üldse @-märki,
kui on, siis lõigatakse kontaktandmed semikooloni ja tühiku järjendi
koha pealt tükkideks ja jäetakse alles ainult see tükk, mis sisaldab ka
@-märki. Kui meiliaadressi kontaktandmetes ei ole, jäetakse tulpa tühi
väärtus.meil
väärtus ei ole
tühi (""
).Keskerakonna_meiliaadressid.txt
nii, et tulpasid eraldaks
tabulaator \t
, teksti ümber ei oleks jutumärke, reanimesid
ei kirjutataks faili kaasa ning faili kodeering oleks UTF-8.valimised$kontakt # millise struktuuriga kontaktandmed on esitatud?
valimised %>%
filter(nimekiri == "Eesti Keskerakond") %>%
mutate(meil = ifelse(test = grepl("@", kontakt), # kui kontaktandmetes on @-sümbol,
yes = str_split(kontakt, "; ") %>% # siis lõika kontaktandmete tekst semikooloni ja tühiku järjendi koha pealt tükkideks,
unlist() %>% # tee tulemuseks saadud listist tavaline vektor
.[grepl("@", .)], # ja jäta alles ainult see tükk, mis sisaldab @-sümbolit
no = "")) %>% # kui @-sümbolit ei ole, ära pane meili tulpa midagi
select(nimi, meil) %>%
filter(meil != "") %>%
write.table("Keskerakonna_meiliaadressid.txt", quote = F, sep = "\t", row.names = F, fileEncoding = "UTF-8")
Kõige lihtsam viis teha kokkuvõtteid, on lugeda väärtusi kokku.
Kiireim viis selleks on kasutada funktsiooni
count()
, mis loeb täpsustatud
tunnuste alusel (gruppides) vaatlused kokku ja esitab
nende sagedused uues tabelis.
valimised %>% count()
valimised %>% count(nimekiri)
valimised %>% count(sugu)
valimised %>% count(nimekiri, sugu)
Kui tahame täpsustada ka, mis on sagedustega tulba nimi (vaikimisi on
selleks n
), saame count()
funktsioonis
kasutada argumenti name
.
Funktsioon summarise()
laseb teha meie
andmetest kokkuvõtteid lisaks vaatluste (gruppides) kokkulugemisele ka
muul moel. Tulemus talletatakse samuti eraldi tabelitesse.
# kandidaatide arv kokku
valimised %>%
summarise(kandidaate_kokku = n()) # funktsioon n() loeb vaatlusi kokku
# see töötab samamoodi nagu valimised %>% count(name = "kandidaate_kokku")
# kandidaatide arv, keskmine vanus, mediaanvanus
valimised %>%
summarise(kandidaate_kokku = n(),
keskmine_vanus = mean(vanus),
mediaanvanus = median(vanus))
# erinevate eesnimede ja perekonnanimede arv
valimised %>%
summarise(eesnimesid = gsub("^([^ ]+?) .*$", "\\1", nimi) %>% unique() %>% length(),
perekonnanimesid = gsub("^.* ([^ ]+)$", "\\1", nimi) %>% unique() %>% length())
Samad arvandmed saaksime tabelita kujul kätte ka ilma
summarise()
-funktsioonita.
nrow(valimised)
mean(valimised$vanus)
median(valimised$vanus)
length(unique(gsub("^([^ ]+?) .*$", "\\1", valimised$nimi)))
length(unique(gsub("^.* ([^ ]+)$", "\\1", valimised$nimi)))
Oluliselt kasulikumaks muutub summarise()
funktsioon aga
siis, kui seda kasutada koos funktsiooniga
group_by()
, mis grupeerib andmeid ühe või
enama tunnuse põhjal ning laseb kokkuvõtteid teha iga grupi kohta
eraldi.
# Kandidaatide arv, keskmine vanus ja mediaanvanus valimisnimekirjades
valimised %>%
group_by(nimekiri) %>%
summarise(kandidaate_kokku = n(),
keskmine_vanus = mean(vanus),
mediaanvanus = median(vanus))
# Mees- ja naiskandidaatide arv, keskmine vanus, mediaanvanus, keskmine häältesaak ja keskmine paberhäälte protsent valimisnimekirjades
valimised %>%
group_by(nimekiri, sugu) %>%
summarise(kandidaate_kokku = n(),
keskmine_vanus = mean(vanus),
mediaanvanus = median(vanus),
keskmine_häältesaak = mean(hääli_kokku),
keskmine_paberhäälte_protsent = mean(hääli_paberil/hääli_kokku*100))
Sisuliselt teevad siin group_by()
ja
summarise()
koos sama asja, mida funktsioon
tapply()
, mida oleme ka kursusel kasutanud.
tapply(valimised$vanus, valimised$nimekiri, mean)
tapply(valimised$vanus, list(valimised$nimekiri, valimised$sugu), mean)
Vahe on selles, et tapply()
käsu väljund on vektor või
maatriks, aga group_by()
+summarise()
annavad
väljundiks data.frame tüüpi nn pika andmetabeli, kus iga
grupeerivate tunnuste kombinatsioon on omaette real (nt Eesti
Keskerakond + M, Eesti Keskerakond + N, Isamaa Erakond + M, Isamaa
Erakond + N jne) ning kuhu võib lisada ka muid kokkuvõtteid.
Nagu ülal näidatud, võib grupeerida andmeid ka mitme tunnuse põhjal.
group_by()
+summarise()
kombinatsioon hülgab
pärast oma töö lõpetamist ühe grupeerimise aluseks oleva tunnuse, aga
kui meil on grupeerimise aluseks mitu tunnust, siis teised jätab alles.
Nii et pärast summarise()
funktsiooni jooksutamist on meie
andmed edasi grupeeritud ainult tunnuse nimekiri
põhjal.
Seega saame küsida iga nimekirja põhjal ainult seda rida (meeste või
naiste rida), kus keskmine häältesaak on suurem. Tulemuseks saame
tabeli, kus on erakonnad, kus mehed said keskmiselt rohkem hääli, ja
erakonnad, kus naised said keskmiselt rohkem hääli.
valimised %>%
group_by(nimekiri, sugu) %>%
summarise(keskmine_häältesaak = mean(hääli_kokku)) %>% # andmed jäävad grupeerituks nimekirja alusel
filter(keskmine_häältesaak == max(keskmine_häältesaak)) %>% # igas nimekirjas jäta alles ainult suurima häältesaagiga rida
arrange(sugu, desc(keskmine_häältesaak)) # järjesta tabel soo ja (kahaneva) häältesaagi tulpade põhjal
Kui me loobuksime pärast summarise()
funktsiooni
kõikidest gruppidest (.groups = "drop"
või
ungroup()
), saaksime vastuseks ainult ühe valimisnimekirja
rea, kus on kõikide nimekirjade ja sugude lõikes kõige suurem keskmine
häältesaak.
valimised %>%
group_by(nimekiri, sugu) %>%
summarise(keskmine_häältesaak = mean(hääli_kokku),
.groups = "drop") %>% # loobume guppidest
filter(keskmine_häältesaak == max(keskmine_häältesaak))
# või
valimised %>%
group_by(nimekiri, sugu) %>%
summarise(keskmine_häältesaak = mean(hääli_kokku)) %>%
ungroup() %>% # loobume gruppidest
filter(keskmine_häältesaak == max(keskmine_häältesaak))
Funktsioonid group_by()
+summarise()
ja
count()
ja teevad väärtusi kokku lugedes
sisuliselt sama asja, ainult et count()
ei jäta andmeid
kunagi grupeerituks. Samuti on
group_by()
+summarise()
väljundiks nn tibble-tüüpi
tabel, count()
väljundiks tavaline
data.frame-tüüpi tabel.
valimised %>% group_by(nimekiri, sugu) %>% summarise(n = n()) # andmed jäävad nimekirja järgi grupeerituks
## `summarise()` has grouped output by 'nimekiri'. You can override using the
## `.groups` argument.
## # A tibble: 19 × 3
## # Groups: nimekiri [10]
## nimekiri sugu n
## <chr> <chr> <int>
## 1 EESTIMAA ÜHENDATUD VASAKPARTEI M 15
## 2 EESTIMAA ÜHENDATUD VASAKPARTEI N 10
## 3 Eesti Keskerakond M 84
## 4 Eesti Keskerakond N 41
## 5 Eesti Konservatiivne Rahvaerakond M 102
## 6 Eesti Konservatiivne Rahvaerakond N 23
## 7 Eesti Reformierakond M 79
## 8 Eesti Reformierakond N 46
## 9 Erakond Eesti 200 M 76
## 10 Erakond Eesti 200 N 49
## 11 Erakond Eestimaa Rohelised M 34
## 12 Erakond Eestimaa Rohelised N 24
## 13 Erakond Parempoolsed M 85
## 14 Erakond Parempoolsed N 40
## 15 ISAMAA Erakond M 96
## 16 ISAMAA Erakond N 29
## 17 Sotsiaaldemokraatlik Erakond M 70
## 18 Sotsiaaldemokraatlik Erakond N 55
## 19 Üksikkandidaadid M 10
## nimekiri sugu n
## 1 EESTIMAA ÜHENDATUD VASAKPARTEI M 15
## 2 EESTIMAA ÜHENDATUD VASAKPARTEI N 10
## 3 Eesti Keskerakond M 84
## 4 Eesti Keskerakond N 41
## 5 Eesti Konservatiivne Rahvaerakond M 102
## 6 Eesti Konservatiivne Rahvaerakond N 23
## 7 Eesti Reformierakond M 79
## 8 Eesti Reformierakond N 46
## 9 Erakond Eesti 200 M 76
## 10 Erakond Eesti 200 N 49
## 11 Erakond Eestimaa Rohelised M 34
## 12 Erakond Eestimaa Rohelised N 24
## 13 Erakond Parempoolsed M 85
## 14 Erakond Parempoolsed N 40
## 15 ISAMAA Erakond M 96
## 16 ISAMAA Erakond N 29
## 17 Sotsiaaldemokraatlik Erakond M 70
## 18 Sotsiaaldemokraatlik Erakond N 55
## 19 Üksikkandidaadid M 10
Üsna hiljutine uuendus on võimalus grupeerida
andmeid ka teiste funktsioonide sees, ilma
group_by()
-funktsiooni kasutamata. Sellisel juhul tuleb
funktsiooni sisse lisada argument .by =
, mis täpsustab, mis
tunnuse alusel andmeid rühmitatakse. Ka sellise kasutuse puhul ei jää
andmed pärast funktsiooni kasutamist ühegi tunnuse alusel
grupeerituks.
# Teeme kokkuvõttest täiesti uue andmetabeli
valimised %>%
summarise(keskmine_häältesaak = mean(hääli_kokku), .by = nimekiri)
# Lisame algsesse andmetabelisse kokkuvõttega uue tulba
valimised %>%
mutate(nimekirja_keskmine_häältesaak = mean(hääli_kokku), .by = nimekiri)
Harjutuses 2 saadud vastus selle kohta, mis aastal on kursusel olnud kõige rohkem kohvijoojaid, ei rahulda meid päriselt, sest see on esitatud absoluutarvuna ega võta arvesse seda, kui palju mingil aastal üldse osalejaid oli. Grupeerimine aitab meil aga arvutada kohvijoojate osakaalu iga aasta kohta eraldi.
Lisaks funktsioonile n()
, mis loeb vaatlusi kokku, ning
juba tuttavatele funktsioonidele min()
, max()
,
mean()
, median()
jm, on kasulik mh ka näiteks
funktsioon n_distinct()
, mis loeb kokku
mingi tunnuse kõik unikaalsed väärtused kas siis terves andmestikus või
selle alamosades.
Harjutus 5
Leia valimiste andmestikust, millistes valimisnimekirjades on protsentuaalselt kõige rohkem Kalade tähtkujust kandidaate.
nimekiri
) ja tähtkuju alusel.prop
, kuhu lisad iga
tähemärgi esindajate osakaalu kõikidest tähemärkidest igas grupis (=
valimisnimekirjas).tähtkuju
väärtus on Kalad
.valimised %>%
group_by(nimekiri, tähtkuju) %>%
summarise(arv = n()) %>% # andmed jäävad nimekirja põhjal grupeerituks
mutate(prop = arv/sum(arv)) %>%
ungroup() %>%
filter(tähtkuju == "Kalad") %>%
filter(prop == max(prop))
# või
valimised %>%
count(nimekiri, tähtkuju) %>%
mutate(prop = n/sum(n), .by = nimekiri) %>%
filter(tähtkuju == "Kalad") %>%
filter(prop == max(prop))
Nii valimiste kui ka küsimustiku andmestikes on iga osaleja eraldi
real ning igat osalejat iseloomustab tulpades iga tunnuse puhul üks
kindel väärtus. Samuti näeme tidyverse
’iga andmete
kokkuvõtteid tehes, et kõikide grupeerivate tunnuste unikaalsed
kombinatsioonid on eraldi ridadel ning nende kombinatsioonide mingid
väärtused (vaatluste summa, keskmine, mediaan vmt) on pandud omaette
tulpa. Sellist andmeformaati nimetatakse pikaks
tabeliks (long format). Vahel võib aga juhtuda, et üks
tunnus on jaotatud hoopis erinevatesse tulpadesse, mispuhul ridu on
vähem, tulpasid on rohkem ja tunnuste kombinatsioonide väärtused on
jagatud mitme tulba vahel (lai tabel ehk wide
format).
Pika ja laia tabeli erinevust ilmestavad hästi näiteks just
group_by()
+summarise()
ja
tapply()
funktsioonide väljundid.
## `summarise()` has grouped output by 'nimekiri'. You can override using the
## `.groups` argument.
## # A tibble: 19 × 3
## # Groups: nimekiri [10]
## nimekiri sugu hääli_kokku
## <chr> <chr> <int>
## 1 EESTIMAA ÜHENDATUD VASAKPARTEI M 11086
## 2 EESTIMAA ÜHENDATUD VASAKPARTEI N 3519
## 3 Eesti Keskerakond M 74257
## 4 Eesti Keskerakond N 18997
## 5 Eesti Konservatiivne Rahvaerakond M 80400
## 6 Eesti Konservatiivne Rahvaerakond N 17566
## 7 Eesti Reformierakond M 106916
## 8 Eesti Reformierakond N 83716
## 9 Erakond Eesti 200 M 46149
## 10 Erakond Eesti 200 N 35180
## 11 Erakond Eestimaa Rohelised M 2624
## 12 Erakond Eestimaa Rohelised N 3262
## 13 Erakond Parempoolsed M 8814
## 14 Erakond Parempoolsed N 5223
## 15 ISAMAA Erakond M 42723
## 16 ISAMAA Erakond N 7395
## 17 Sotsiaaldemokraatlik Erakond M 29646
## 18 Sotsiaaldemokraatlik Erakond N 26938
## 19 Üksikkandidaadid M 5888
## M N
## Eesti Keskerakond 74257 18997
## Eesti Konservatiivne Rahvaerakond 80400 17566
## Eesti Reformierakond 106916 83716
## EESTIMAA ÜHENDATUD VASAKPARTEI 11086 3519
## Erakond Eesti 200 46149 35180
## Erakond Eestimaa Rohelised 2624 3262
## Erakond Parempoolsed 8814 5223
## ISAMAA Erakond 42723 7395
## Sotsiaaldemokraatlik Erakond 29646 26938
## Üksikkandidaadid 5888 NA
Laiast tabelist pika tegemiseks saab kasutada funktsiooni
pivot_longer()
ning pikast tabelist laia
tegemiseks funktsiooni pivot_wider()
.
# laiast pikk
tapply(valimised$hääli_kokku, list(valimised$nimekiri, valimised$sugu), sum) %>%
as.data.frame() %>% # maatriksist data.frame-tüüpi objekt
rownames_to_column(var = "nimekiri") %>% # reanimed tulpa "nimekiri"
pivot_longer(data = ., # andmetabel eelmiste funktsioonide väljundist
cols = c("M", "N"), # tulbad, mida ühe tunnuse alla koondada
names_to = "sugu", # uus tulbanimi, kuhu tunnuse kategooriad (nt "M" ja "N") panna
values_to = "hääli_kokku") # uus tulbanimi, kuhu tunnuse väärtused panna
# pikast lai
valimised %>%
group_by(nimekiri, sugu) %>%
summarise(hääli_kokku = sum(hääli_kokku)) %>%
pivot_wider(data = ., # andmetabel eelmiste funktsioonide väljundist
names_from = "sugu", # tulp, mis sisaldab kategooriate nimesid, mida eraldi tulpadesse panna
values_from = "hääli_kokku") # tulp, mis sisaldab tunnuse väärtusi, mida eraldi tulpade lahtritesse panna
Laiast pika tabeli teeb ka funktsioon as.data.frame()
,
kui kasutame seda mingil table()
-funktsioonige tehtud
objektil.
NB! ggplot2
tahab, et tegemist oleks
pika tabeliga!
arrange()
- järjesta andmestik mingi tunnuse
aluselcount()
- loe andmestikus vaatlusi kokkufilter()
- vali andmestikust ridugroup_by()
- grupeeri andmestiku vaatlused mingi(te)
tunnus(t)e aluselgsub()
- asenda mingi sümbol või sümbolite järjend
vektoris teise sümboli või sümbolite järjendigalapply()
- rakenda mingit funktsiooni kõikidele vektori
või listi elementidele (tulemuseks vaikimisi list)mutate()
- lisa andmestikku uus tulpn()
- loe vaatlusi kokkun_distinct()
- leia erinevate väärtuste
arvpivot_longer()
- tee laiast tabelist pikkpivot_wider()
- tee pikast tabelist laipull()
- vali andmestikust tulp vektorinarownames_to_column()
- tee andmetabeli reanimedest
omaette andmestiku tulpselect()
- vali andmestikust tulp(asid) (tulemuseks
jääb data.frame
objekt, mitte vektor)str_split()
- lõika tekst mingi sümboli, nt tühiku koha
pealt eraldi elementideks (tulemuseks vaikimisi list)summarise()
- tee andmestikust kokkuvõtteid (tulemuseks
uus tabel)tolower()
- tee vektori elemendid läbivalt
väiketäheliseksungroup()
- tühista andmetabeli vaatluste
rühmitus(ed)unique()
- küsi ainult vektori unikaalseid (st
erinevaid) väärtusiunlist()
- tee list-tüüpi objektist tavaline
vektorValim ja populatsioon. Hüpoteesid ja tõenäosus.