Praktikum 19 Ruumiandmete analüüs R-iga

19.1 Miks teha kaarte koodipõhiselt?

Miks teha midagi koodipõhiselt, kui saame (võrdlemisi) samasuguseid kaarte teha ka QGISis või mõnes veebirakenduses?

Erinevalt nn osuta-ja-klõpsa tarkvaradest, kus andmete analüüs toimub puhtalt programmi kasutajaliidese erinevate vidinatega suheldes ja kindlas järjekorras kuskil ikoonidel klõpsides, jääb koodi kirjutades selge jälg sellest, mida, mis järjekorras ja kuidas tehti. See aitab nii endal kui ka teistel paremini mõista, kuidas mingi konkreetse tulemuseni jõuti.
Ühtlasi võib kood tööprotsesse oluliselt lihtsustada ja kiirendada, eriti juhtudel, kus andmed võivad vahepeal muutuda või tuleb teha korduvalt sarnaseid asju. Kujutame ette näiteks olukorda, kus tegime lõputöö või publikatsiooni jaoks kaardi ning kuu aega hiljem palub juhendaja või toimetaja paari detaili kaardil muuta, ülejäänud kaart aga peaks jääma täpselt samaks. Samas oleme vahepeal enda ruumiandmetega väga palju edasi tegelenud. Millised olid täpselt kasutatud andmed, värvid, joone paksus, mõõtkava, mudeldamiseks kasutatud meetod jm? Koodis on see info kõik olemas ja see toimib sellisel juhul kui täpne “retsept” sellest, kuidas esimesel korral oma kaardini jõudsime. Niisiis pole tarvis kogu kaarditegemise protsessi uuesti läbi teha, vaid muuta koodis ära vaid vajalikud detailid.

19.2 R, RStudio ja R Markdown

R on vabavaraline väga võimas programmeerimiskeel ja rakendustarkvara andmeanalüüsiks, statistilisteks arvutusteks ning andmete visualiseerimiseks. R pakub väga palju statistilisi ja graafilisi meetodeid ning täieneb pidevalt uute tööriistade ja funktsioonidega. Üks R-i tugevaid külgi on just võimalus teha kõrge kvaliteediga jooniseid ja graafikuid. Kuna tegu on koodipõhise tarkvaraga, siis annab see kasutajatele suhteliselt vabad käed ning võimaldab kontrollida isegi kõige väiksemaid detaile.

Pakettide ehk teekide (package) eesmärk on lisada mingeid funktsioone. Paljud paketid tulevad R-iga kohe kaasa, aga üldiselt peab neid (eriti spetsiifilisemate ülesannete täitmiseks) juurde installima. Hetkel on R-i kodulehel cran.r-project.org üle 20 100 paketi. Pakett koosneb koodist, andmetest, dokumentatsioonist ja testidest ning seda on lihtne teistega jagada. Ka ruumiandmete analüüsimiseks, andmete töötlemiseks ja visualiseerimiseks on R-is omaette paketid, ehkki põhiosa tavalisest andmetöötlusest saab edukalt teha ka ilma lisapakette installimata.

RStudio on R-i integreeritud arenduskeskkond (integrated development environment ehk IDE). See koosneb tekstiredaktorist (1), konsoolist (2) ning tööriistadest graafikute kuvamiseks, koodi silumiseks, kogu keskkonna ja ajaloo majandamiseks jpm. RStudiost on nii vabavaraline kui ka kommertsversioon. Meie kasutame vabavaralist.

Rstudio kasutajaliidese peamised osad

Joonis 19.1: Rstudio kasutajaliidese peamised osad

1 - skriptiaken. Siia saab kirjutada oma koodi koos kommentaaridega (kommentaari algust tähistavad trellid). Skripti saab salvestada ja teinekord uuesti kasutada (File → Save As). Skriptifaili laiend on .R. Mingi skripti rea jooksutamiseks liigu hiirega sellele reale ja vajuta kas nuppu või vajuta klahvikombinatsiooni Ctrl+Enter (Windowsis) / Cmd+Enter (Macis).
2 - konsool. Siia kuvatakse kogu jooksutatud skript. Lisaks saab siin ka eraldi koodi jooksutada, mis sel juhul skripti ei salvestu.
3 - töökeskkond (Environment), käskude ajalugu (History) jm. Töökeskkonnas näed kõiki mingi sessiooni jooksul loodud muutujaid (mingit infot säilitavaid objekte, nt tabeleid) ja funktsioone.
4 - failid (Files), joonised (Plots), paketid (Packages) jm. Failide all näed neid faile, mis on parasjagu sinu töökataloogis (working directory). Töökataloogi aadressi näed ka konsooli päises.
Lisaks tavalisele .R-laiendiga skriptiformaadile on üha enam kasutusel ka R Markdowni failiformaat (laiendiga .Rmd).
R Markdown on formaat tavalise teksti ning koodi kombineerimiseks ning võimaldab kirjutada täielikult reprodutseeritavaid artikleid, raamatuid, raporteid ning koostada veebilehti, interaktiivseid lahendusi jpm. Nii see juhend kui ka kogu kursuse materjalid on kirjutatud R Markdownis.

R Markdown koosnebki tavaliselt tekstist nagu see siin.

# Ning kooditükkidest nagu see siin. Kooditükid on Rstudios kolme ` vahel.
# Trellid teksti ees tähistavad kommentaari nagu tavalises R-i skriptifailis 
# ning seda koodi jooksutamisel ei arvestata. See on lihtsalt inimesele lugemiseks.
# Kood ise tuleb kirjutada ilma trellideta.
# Näiteks allolev kood salvestab arvu 8 muutujasse nimega "lemmiknumber".
# Muutuja "lemmiknumber" tekib koodi jooksutamisel ka Environment-jaotisesse.
lemmiknumber <- 8
# Nüüd saame selle arvulise muutujaga teha näiteks liitmis- ja lahutamistehteid
lemmiknumber+1
## [1] 9
lemmiknumber-10
## [1] -2

Igat koodiploki rida võib jooksutada ka eraldi (Ctrl+Enter/Cmd+Enter).
Laadime Moodle’ist alla tänase praktikumi failid, pakime need lahti ning asetame need failid enda selle kursuse kausta. Avame Rstudio ning seal faili ruumiandmed_r.Rmd, valides ülevalt vasakust nurgast File → Open file.

19.3 Pakettide installimine

Kõigepealt installime vajalikud paketid. Selleks jooksutame allolevat koodi. Kui kasutad R-i skripti, siis tuleb allolevad read (ja kõik edaspidised koodiread) lihtsalt skriptiaknasse kopeerida ning neid Ctrl+Enter/Cmd+Enter abil jooksutada. R Markdownis saab koodi jooksutada ja nii, kui klikid koodiploki paremal üleval nurgas rohelisele nupule (Run current chunk). Selle tulemusena tõmbab R kõik vajalikud paketid ja installib need. Sellega võib minna natuke aega. Kui protsess on lõppenud, siis kaob konsooli paremas nurgas väike punane STOP-märk. Kui konsooli trükitakse vahepeal punast teksti, mis ei alga sõnaga Error:, ei tasu selle pärast muretseda. R lihtsalt teavitab sind sellest, millega ta parajasti tegeleb.

install.packages("tidyverse")
install.packages("sf")
install.packages("ggspatial")

Selleks, et installitud pakettide funktsioone kasutama hakata, tuleb need paketid ka laadida. Selleks on käsk library(). Paketid tuleb installida ainult ühe korra, aga laadida tuleb need alati uuesti, kui oled vahepeal Rstudio sulgenud.

library(tidyverse)
library(sf)
library(ggspatial)

Kui paketid on laaditud, siis teeme R Markdowni failis veel ühe väikese muudatuse, et faili vaatamine oleks mugavam. Nimelt ei peaks koodi jooksutamise tulemust kohe siin koodi all näitama. Selleks valime Tools → Global options → R Markdown ning võtame ära linnukese valiku Show output inline for all R Markdown documents eest. Seejärel vajutame all servas OK.

Viimase asjana paneme paika töökataloogi ehk Working directory. Siin kasutame seda peamiselt selleks, et saaks andmeid lugeda lähtuvalt nende asukohast seoses meie R Markdowni faili asukohaga. Sellepärast tulekski see fail panna samasse kausta, kus on ka kaust data ülejäänud Moodle’ist alla laetud failidega. Working directory seadistamiseks saab valida ülevalt menüüribalt Session → Set working directory → To Source File Location. Seejärel jooksutame allolevat koodiplokki. Kui kõik on õigesti, peaks tulemuseks olema meie praeguse R Markdowni faili asukoht.

getwd()

Kui kopeerid koodiridu R-i skriptifaili, siis hoolitse selle eest, et sisseloetavate failide kaust data oleks funktsiooniga getwd() näidatud kaustas.

19.4 Kood

Vaatame paari näidet koodist, et mõista, kuidas üldiselt asjad töötavad.

# Arvutuste tegemine. Koodi jooksutades näidatakse tulemust. 
5 + 11
## [1] 16

Väärtustele (ja ka andmestikele, funktsioonidele) saab anda <- abil nime ning selle nimega neile edaspidi viidata.

a <- 3
b <- 7
a + b
## [1] 10
x <- 2
y <- 4
a + b + x + y
## [1] 16

Sama tehet saame teha ka funktsiooni abil. Funktsiooni puhul kirjutatakse kõigepealt funktsiooni nimi (nt c või sum) ning sellele järgnevad sulud, kus saab funktsiooni argumentidele väärtuseid anda. Põhimõtteliselt käib see samamoodi nagu inimkeeles: funktsioon on justkui mingi sihiline tegusõna (tee midagi), millele tuleb lisada, mida, millega või kuidas tehakse. Need viimased ongi argumendid, mida täpsustatakse sulgude sees. Kombineerime funktsiooniga c() (concatenate) arvulistest väärtustest nimekirja ning liidame funktsiooniga sum() kõik nimekirja väärtused kokku.

nimekiri <- c(a, b, x, y)
nimekiri
## [1] 3 7 2 4
sum(nimekiri)
## [1] 16

Muutujatele saab omistada lisaks arvulistele väärtustele mõistagi ka teistuguseid, nt tekstilisi väärtusi.

tekst <- "tekstilised väärtused on alati jutumärkide vahel"
tekst
## [1] "tekstilised väärtused on alati jutumärkide vahel"

Tekstiliste väärtustega arvutustehteid teha ei saa, küll aga igasugu muid asju.

nchar(tekst) # näita teksti pikkust tähemärkides
## [1] 48
gsub("e", "E", tekst) # asenda tekstis väikesed e-d suurtega
## [1] "tEkstilisEd väärtusEd on alati jutumärkidE vahEl"
substr(tekst, 1, 10) # näita tekstist esimest 10 tähte
## [1] "tekstilise"

Muutujates saab hoida ka terveid andmetabeleid (data frame’e).

nimed <- c("Oskar", "Mari", "Juhan") # nimekiri nimedest
vanused <- c(10, 25, 99) # nimekiri vanustest (sama pikk kui nimede nimekiri)
tabel <- data.frame(nimed, vanused) # tabel kahest nimekirjast
tabel
##   nimed vanused
## 1 Oskar      10
## 2  Mari      25
## 3 Juhan      99

19.5 Andmete sisselugemine

Andmete sisselugemiseks tuleb kasutada vastavalt andmestiku tüübile funktsioone, millest enamik sisaldab mingil kujul sõna read. Tabelandmestiku puhul nt read.delim() ja vektorkujul ruumiandmete puhul st_read() (paketist sf).

kihelkonnad <- st_read("data/kihelkonnad/kihelkonnad.shp")
# Seda koodi võiks lugeda järgmiselt: 
# ava meie praeguse R Markdowni failiga samas kaustas olevast kaustast data/kihelkonnad 
# fail kihelkonnad.shp ja anna sellele nimeks kihelkonnad.

Näeme, et sisse loetakse multipolügooni tüüpi ruumiandmed, mis on Eesti 1997. aasta koordinaatide referentssüsteemis. Kõige läänepoolsem x-koordinaat on 369020.1, kõige idapoolsem 739155.1; kõige lõunapoolsem y-koordinaat on 6377141, kõige põhjapoolsem 6634006.
Atribuuttabelis on 120 rida ja 11 tulpa.
Loeme sisse ka atlase punktikihi, kus on 279 rida ja 13 tulpa.

atlas <- st_read("data/atlas.gpkg")

Kui st_read() funktsiooniga andmete sisselugemine ei tööta, tähendab see tõenäoliselt, et pakett on jäänud installimata (install.packages("sf")) või laadimata (library(sf)).
Andmestikest ülevaate saamiseks võime vajutada paremal Environment jaotises vastava muutuja nimel või kasutada näiteks funktsiooni head(), mis kuvab tabeli esimesed read (vaikimisi 6 esimest rida).

head(kihelkonnad)
## Simple feature collection with 6 features and 11 fields
## Geometry type: MULTIPOLYGON
## Dimension:     XY
## Bounding box:  xmin: 416505.7 ymin: 6404452 xmax: 502423.3 ymax: 6547085
## Projected CRS: Estonian Coordinate System of 1997
##   ID Parish_id    Name     Ger_name
## 1  1       Vor  Vormsi        Worms
## 2  2       Muh    Muhu         Mohn
## 3  3       Khn   Kihnu        Kühnö
## 4  4       Ruh   Ruhnu         Runö
## 5  5       Jaa   Jaani St. Johannis
## 6  6       Vll Valjala        Wolde
##                                                                               Comment
## 1                                                         Khk-piir ühtib vallapiiriga
## 2                                                                 Piirid kontrollitud
## 3 Ei olnud omaette kihelkond, ent loetakse siiski etnograafiliselt eraldi piirkonnaks
## 4                                                                        Kontrollitud
## 5                       Katastripiiride põhjal üle kontrollitud (P. Päll, 2013-01-15)
## 6                       Katastripiiride põhjal üle kontrollitud (P. Päll, 2013-01-15)
##   Problem Shape_Leng Dialect_en Shape_Le_1 Shape_Area Dialect_et
## 1    <NA>  137619.56    Western  119120.89   95574580      Lääne
## 2    <NA>  166662.20    Insular  152068.60  208717779     Saarte
## 3    <NA>   57101.22    Insular   43719.90   17486775     Saarte
## 4    <NA>   26172.08    Insular   22586.64   11903885     Saarte
## 5    <NA>   78056.11    Insular   72996.58  120846149     Saarte
## 6    <NA>  134426.80    Insular  125282.86  210185513     Saarte
##                         geometry
## 1 MULTIPOLYGON (((457464.6 65...
## 2 MULTIPOLYGON (((463501.9 64...
## 3 MULTIPOLYGON (((500539.8 64...
## 4 MULTIPOLYGON (((456664 6404...
## 5 MULTIPOLYGON (((445725.1 64...
## 6 MULTIPOLYGON (((437423 6465...

Nagu öeldud, saab tavaliste tabelite (st mitteruumiandmete) sisselugemiseks kasutada näiteks funktsiooni read.delim(), aga read-käskusid on tegelikult väga palju (trüki nt konsooli sisse read ja vajuta tabulaatorit, et näha võimalikke variante). Loeme sisse murdekorpuse sagedusandmed.

# tulpade eraldaja (sep) on semikoolon
# faili kodeering (encoding) on "UTF-8"
korpus <- read.delim("data/eiole_pole_mk_props.csv", sep = ";", encoding = "UTF-8")

Vaatame esimesi ridu.

head(korpus)
##   Murre Murrak     eiole       pole
## 1 Kirde    Jõh 0.9117647 0.08823529
## 2 Kirde    Iis 0.9062500 0.09375000
## 3   Ida    Pal 0.7191011 0.28089888
## 4  Kesk    Äks 0.9142857 0.08571429
## 5  Kesk    Amb 0.7530864 0.24691358
## 6  Kesk    Juu 0.5405405 0.45945946

19.6 Kaartide tegemine

Populaarne R-i pakett andmete visualiseerimiseks on ggplot2, mis on ka Tidyverse’i pakettide kogumiku osa. Sellega saab teha nii kõiksugu jooniseid kui ka kaarte. Pakett põhineb nn graafikagrammatika (Grammar of Graphics) kontseptsioonil, mis võimaldab luua jooniseid erinevate komponentide ja kihtide kombineerimise teel. Sisuliselt toimub komponentide lisamine kihtidena pisut sarnaselt sellele, mida oleme siiani QGISis teinud. Kõigepealt lisatakse aluskiht, seejärel mingi sisukiht ning seejärel kõikvõimalikud märkused ja lisad (ehkki kihtide lisamise järjekord ei ole väga rangelt määratud). Proovime paketi ggplot2 abil teha oma sisseloetud andmetest kaarte.

ggplot() + 
    geom_sf(data = kihelkonnad)

  • Funktsiooniga ggplot() algab iga ggploti graafik.
  • Sellele lisame ruumiandmete kihi geom_sf() funktsiooniga, mille sees saame täpsustada andmestiku nime, kust ruumiandmed tulevad. geom-kihte võib lisada ka mitu tükki.
ggplot() +
    geom_sf(data = kihelkonnad) +
    geom_sf(data = atlas)

Värvime maakondade polügoonid helehalli värvi (fill), polügoonide piirjooned samuti heledamaks halliks (color). Punktid teeme läbipaistvamaks (alpha) ja pisut suuremaks (size) ja kasutame halli taustaga kaarditeema asemel mustvalget teemat (theme_bw()). Värvinimesid ja HEX-värvikoode, mida saab kasutada, leiad näiteks siit.

ggplot() +
    geom_sf(data = kihelkonnad, fill = "grey90", color = "grey70") +
    geom_sf(data = atlas, alpha = 0.5, size = 3) +
    theme_bw()

Lisame joonisele ka pealkirja (title) ja viite kasutatud andmetele (caption). Lisame ka mõõtkava (annotation_scale paketist ggspatial). Mõõtkava võib paigutada nt alumisse vasakusse (bl), alumisse paremasse (br), ülemisse vasakusse (ul) või ülemisse paremasse nurka (ur).

ggplot() +
    geom_sf(data = kihelkonnad, fill = "grey90", color = "grey70") +
    geom_sf(data = atlas, alpha = 0.5, size = 3) +
    theme_bw() +
    labs(title = "Murdeatlase punktid", caption = "Andmed: EKI (2015), Andrus Saareste (1955)") +
    annotation_scale(location = "bl")

Praegu oleme kujutanud kaardil lihtsalt ruumiandmeid (kus mingid polügoonid või punktid asuvad?), aga ei kajasta kuidagi visuaalselt andmestiku tunnuseid. Juhul, kui mõni kujunduselement (nt värv, suurus, kuju, läbipaistvus) on seotud atribuuttabeli tunnusega, tuleb selle tunnuse nimi ja seda kujutav visuaalne atribuut tuua välja geom()-kihil aes()-funktsiooni sees (aesthetics).

# Värvime kihelkondade polügoonid vastavalt murdeala nimele
ggplot() +
    geom_sf(data = kihelkonnad, aes(fill = Dialect_et))

# Vrd
#ggplot() +
#    geom_sf(data = kihelkonnad, fill = "red")
ggplot() +
    geom_sf(data = kihelkonnad) +
    geom_sf(data = atlas, alpha = 0.5, size = 3, aes(color = KeelendBin))

# Vrd
#ggplot() +
#    geom_sf(data = kihelkonnad) +
#    geom_sf(data = atlas, alpha = 0.5, size = 3, color = "red")

Kui mõni kujunduselement (alpha, fill, color, size, shape vm) on niisiis niisama geom_sf() funktsiooni sees, kehtib see kõikidele kihi objektidele ühtmoodi (nt kõik punktid on punased). Kui see on aga omakorda veel aes()-funktsiooni sees, eristatakse objektide kujundust vastavalt mingile andmestiku atribuudile/tunnusele (nt ühed punktid on punased, teised sinised, vastavalt sellele, kas tegemist on ei ole või pole punktiga).

Atribuuttabeliga seotud kujunduselementide välimuse muutmiseks (enamasti nt värvipaleti vahetamiseks) saab kasutada eraldi scale_...-funktsioone. Näiteks täitevärvi (fill) värvipaletti saab vahetada funktsioonidega, mis algavad scale_fill_..., ilma täitevärvita sümboli või äärejoone (color) värvipaletti saab vahetada funktsioonidega, mis algavad scale_color_....
Värvime maakonnad nt Viridise diskreetse, st mittepideva värviskaalaga (_d) ja punktid Breweri kvalitatiivsete (st mittearvuliste) tunnuste jaoks mõeldud värvidega.

# Vahetame maakondade värviskaalat
ggplot() +
    geom_sf(data = kihelkonnad, aes(fill = Dialect_et)) +
    scale_fill_viridis_d()

# Vahetame punktide värviskaalat
ggplot() +
    geom_sf(data = kihelkonnad) +
    geom_sf(data = atlas, alpha = 0.5, size = 3, aes(color = KeelendBin)) +
    scale_color_brewer(type = "qual", palette = "Dark2")

Võime määrata värvid ka käsitsi, nt scale_color_manual(values = c("pink", "green")).

19.7 Andmete valimine

Ruumiandmete filtreerimiseks on meil kasutada dplyr pakett, mis võimaldab paari funktsiooni abil suure osa andmetöötlusest ära teha ja mis saab laaditud koos tidyverse’i paketi laadimisega.
Filtreerime kihelkondade kihilt ainult saarte murde alla kuuluvad polügoonid. Selleks võime esmalt küsida, mis on üldse kihelkondade kihi tulbanimed.

names(kihelkonnad)
##  [1] "ID"         "Parish_id"  "Name"       "Ger_name"   "Comment"   
##  [6] "Problem"    "Shape_Leng" "Dialect_en" "Shape_Le_1" "Shape_Area"
## [11] "Dialect_et" "geometry"

Nüüd filtreerime kihelkondade kihilt need read ja need kihelkondade polügoonid, kus tulbas Dialect_et on väärtus Saarte.

kihelkonnad %>%
    filter(Dialect_et == "Saarte")
## Simple feature collection with 18 features and 11 fields
## Geometry type: MULTIPOLYGON
## Dimension:     XY
## Bounding box:  xmin: 369020.1 ymin: 6404452 xmax: 502423.3 ymax: 6551381
## Projected CRS: Estonian Coordinate System of 1997
## First 10 features:
##    ID Parish_id       Name     Ger_name
## 1   2       Muh       Muhu         Mohn
## 2   3       Khn      Kihnu        Kühnö
## 3   4       Ruh      Ruhnu         Runö
## 4   5       Jaa      Jaani St. Johannis
## 5   6       Vll    Valjala        Wolde
## 6   7       Mus   Mustjala       Mustel
## 7   8       Kaa     Kaarma       Karmel
## 8   9       Kär      Kärla       Kergel
## 9  10       Khk Kihelkonna     Kielkond
## 10 11       Jäm     Jämaja        Jamma
##                                                                                Comment
## 1                                                                  Piirid kontrollitud
## 2  Ei olnud omaette kihelkond, ent loetakse siiski etnograafiliselt eraldi piirkonnaks
## 3                                                                         Kontrollitud
## 4                        Katastripiiride põhjal üle kontrollitud (P. Päll, 2013-01-15)
## 5                        Katastripiiride põhjal üle kontrollitud (P. Päll, 2013-01-15)
## 6                        Katastripiiride põhjal üle kontrollitud (P. Päll, 2013-01-15)
## 7                        Katastripiiride põhjal üle kontrollitud (P. Päll, 2013-01-15)
## 8                        Katastripiiride põhjal üle kontrollitud (P. Päll, 2013-01-15)
## 9                        Katastripiiride põhjal üle kontrollitud (P. Päll, 2013-01-15)
## 10                       Katastripiiride põhjal üle kontrollitud (P. Päll, 2013-01-15)
##    Problem Shape_Leng Dialect_en Shape_Le_1 Shape_Area Dialect_et
## 1     <NA>  166662.20    Insular  152068.60  208717779     Saarte
## 2     <NA>   57101.22    Insular   43719.90   17486775     Saarte
## 3     <NA>   26172.08    Insular   22586.64   11903885     Saarte
## 4     <NA>   78056.11    Insular   72996.58  120846149     Saarte
## 5     <NA>  134426.80    Insular  125282.86  210185513     Saarte
## 6     <NA>  114295.25    Insular  109866.84  226931935     Saarte
## 7     <NA>  170224.11    Insular  160600.13  373623450     Saarte
## 8     <NA>   77964.86    Insular   77959.20  228263844     Saarte
## 9     <NA>  394865.11    Insular  364986.01  459481464     Saarte
## 10    <NA>  113085.92    Insular   95051.81  142890724     Saarte
##                          geometry
## 1  MULTIPOLYGON (((463501.9 64...
## 2  MULTIPOLYGON (((500539.8 64...
## 3  MULTIPOLYGON (((456664 6404...
## 4  MULTIPOLYGON (((445725.1 64...
## 5  MULTIPOLYGON (((437423 6465...
## 6  MULTIPOLYGON (((401102.4 64...
## 7  MULTIPOLYGON (((415976.4 64...
## 8  MULTIPOLYGON (((404232.4 64...
## 9  MULTIPOLYGON (((375155.3 64...
## 10 MULTIPOLYGON (((383088.7 64...

Nn toru %>% suunab mingi objekti või väljundi uue funktsiooni sisse. Praegusel juhul võtsime niisiis kihelkondade kihi ja selle suunasime filter()-funktsiooni. Võime filtreerimise väljundi omakorda suunata järgmisse funktsiooni, näiteks joonise tegemise funktsiooni. Sellisel juhul pole geom_sf() funktsioonis vaja eraldi andmestikku täpsustada, sest toru ütleb ära, et andmestik tuleb eelnevate käskude väljundist.

kihelkonnad %>%
    filter(Dialect_et == "Saarte") %>%
    ggplot() +
    geom_sf()

Teine variant on salvestada filtreeritud andmed eraldi muutujasse ja kasutada seejärel ggplot() funktsiooni nii nagu ennegi.

kihelkonnad %>% filter(Dialect_et == "Saarte") -> saarte_murre
# saame suunamist teha ka vasakult paremale ->
# sama tulemuse saaks koodiga
# saarte_murre <- kihelkonnad %>% filter(Dialect_et == "Saarte")
ggplot() +
    geom_sf(data = saarte_murre)

Ridade filtreerimisel töötavad sarnased operaatorid, mida oleme näinud ka QGISis:

  • > on suurem kui
  • < on väiksem kui
  • >= on suurem kui või võrdne
  • <= on väiksem kui või võrdne
  • == on võrdne
  • != ei ole võrdne
  • %in% kuulub hulka

Valime atlase punktikihilt ainult pole punktid ja kuvame need kihelkondade kaardil. Kihelkondade kiht peab tulema enne punktikihti, et see punkte ära ei kataks.

names(atlas) # vaatame tulbanimesid
##  [1] "ANIMI"      "ONIMI"      "MNIMI"      "SaKhkLyh"   "SaKhk"     
##  [6] "SaKyla"     "SaKJEes"    "SaKJPrk"    "SaKJSynd"   "Keelend"   
## [11] "SaKom"      "KeelendBin" "KeelendNum" "geom"
head(atlas) # vaatame esimesi ridu
## Simple feature collection with 6 features and 13 fields
## Geometry type: POINT
## Dimension:     XY
## Bounding box:  xmin: 425475.3 ymin: 6507561 xmax: 535475 ymax: 6590791
## Projected CRS: Estonian Coordinate System of 1997
##                ANIMI         ONIMI         MNIMI SaKhkLyh        SaKhk
## 1        Leibre küla   Vigala vald Rapla maakond      Vig       Vigala
## 2      Paldiski linn Paldiski linn Harju maakond      HMd Harju-Madise
## 3 Haabersti linnaosa       Tallinn Harju maakond      Kei        Keila
## 4       Muraste küla    Harku vald Harju maakond      Kei        Keila
## 5       Ilmandu küla    Harku vald Harju maakond      Kei        Keila
## 6         Selja küla    Käina vald  Hiiu maakond      Käi        Käina
##      SaKyla SaKJEes SaKJPrk SaKJSynd     Keelend                     SaKom
## 1 Leilavere    <NA>    <NA>       NA ei (äi) ole                      <NA>
## 2    Leetse    <NA>    <NA>       NA        põle                      <NA>
## 3   Kakumäe    <NA>    <NA>       NA        pole                      <NA>
## 4   Muraste    <NA>    <NA>       NA ei (äi) ole                      <NA>
## 5   Ilmandu    <NA>    <NA>       NA ei (äi) ole                      <NA>
## 6     Selja    <NA>    <NA>       NA        pole T. s. Eduard Mäehans 1890
##   KeelendBin KeelendNum                     geom
## 1     ei ole          1 POINT (523059.3 6507561)
## 2       pole          0 POINT (505646.8 6579844)
## 3       pole          0   POINT (535475 6586658)
## 4     ei ole          1 POINT (525130.3 6590791)
## 5     ei ole          1 POINT (527089.1 6589553)
## 6       pole          0 POINT (425475.3 6522034)
atlas %>% filter(KeelendBin == "pole") -> pole_punktid
ggplot() +
    geom_sf(data = kihelkonnad, fill = "grey90", color = "grey70") + 
    geom_sf(data = pole_punktid, alpha = 0.5, color = "darkblue", size = 3) + 
    theme_bw()

Atlase punktikihi puhul meil murrete infot teada ei ole (on ainult maakondade info). Selleks, et kuvada korraga nt keskmurde kihelkondi JA keskmurde atlase punkte, peaksime atlase punktidele nende kihelkonna info põhjal leidma ka murrete nimed.

19.8 Andmestike ühendamine

Ruumiandmete omavahel ühendamiseks (st puhtalt koordinaadipõhiseks andmete ühendamiseks) saab kasutada funktsiooni st_join() (paketist sf). Selleks, et ühendamisel säiliks andmestiku vektortüübina punktandmestik, mitte polügoonid, peaksime vasakule poole panema atlase andmestiku nime ja paremale kihelkondade oma.

atlas_khk <- st_join(atlas, kihelkonnad)
head(atlas_khk)
## Simple feature collection with 6 features and 24 fields
## Geometry type: POINT
## Dimension:     XY
## Bounding box:  xmin: 425475.3 ymin: 6507561 xmax: 535475 ymax: 6590791
## Projected CRS: Estonian Coordinate System of 1997
##                ANIMI         ONIMI         MNIMI SaKhkLyh        SaKhk
## 1        Leibre küla   Vigala vald Rapla maakond      Vig       Vigala
## 2      Paldiski linn Paldiski linn Harju maakond      HMd Harju-Madise
## 3 Haabersti linnaosa       Tallinn Harju maakond      Kei        Keila
## 4       Muraste küla    Harku vald Harju maakond      Kei        Keila
## 5       Ilmandu küla    Harku vald Harju maakond      Kei        Keila
## 6         Selja küla    Käina vald  Hiiu maakond      Käi        Käina
##      SaKyla SaKJEes SaKJPrk SaKJSynd     Keelend                     SaKom
## 1 Leilavere    <NA>    <NA>       NA ei (äi) ole                      <NA>
## 2    Leetse    <NA>    <NA>       NA        põle                      <NA>
## 3   Kakumäe    <NA>    <NA>       NA        pole                      <NA>
## 4   Muraste    <NA>    <NA>       NA ei (äi) ole                      <NA>
## 5   Ilmandu    <NA>    <NA>       NA ei (äi) ole                      <NA>
## 6     Selja    <NA>    <NA>       NA        pole T. s. Eduard Mäehans 1890
##   KeelendBin KeelendNum ID Parish_id         Name     Ger_name
## 1     ei ole          1 37       Vig       Vigala       Fickel
## 2       pole          0 27       HMd Harju-Madise St. Matthias
## 3       pole          0 26       Kei        Keila        Kegel
## 4     ei ole          1 26       Kei        Keila        Kegel
## 5     ei ole          1 26       Kei        Keila        Kegel
## 6       pole          0 46       Käi        Käina       Keinis
##                                                                                     Comment
## 1            Kihelkonnapiirid mõisapiiride järgi üle kontrollitud (Peeter Päll, 2012-11-26)
## 2 Kihelkonnapiirid mõisapiiride järgi üle kontrollitud (Peeter Päll, 2012-11-12) + Ris piir
## 3            Kihelkonnapiirid mõisapiiride järgi üle kontrollitud (Peeter Päll, 2012-11-12)
## 4            Kihelkonnapiirid mõisapiiride järgi üle kontrollitud (Peeter Päll, 2012-11-12)
## 5            Kihelkonnapiirid mõisapiiride järgi üle kontrollitud (Peeter Päll, 2012-11-12)
## 6            Kihelkonnapiirid mõisapiiride järgi üle kontrollitud (Peeter Päll, 2012-11-27)
##   Problem Shape_Leng Dialect_en Shape_Le_1 Shape_Area Dialect_et
## 1    <NA>   109783.2    Western   109656.3  361383036      Lääne
## 2    <NA>   112767.7        Mid   110349.6  173357161       Kesk
## 3    <NA>   145259.7        Mid   142289.8  627679360       Kesk
## 4    <NA>   145259.7        Mid   142289.8  627679360       Kesk
## 5    <NA>   145259.7        Mid   142289.8  627679360       Kesk
## 6    <NA>   125610.6    Insular   119959.6  199587278     Saarte
##                       geom
## 1 POINT (523059.3 6507561)
## 2 POINT (505646.8 6579844)
## 3   POINT (535475 6586658)
## 4 POINT (525130.3 6590791)
## 5 POINT (527089.1 6589553)
## 6 POINT (425475.3 6522034)

Funktsioon st_join() vaatab niisiis iga punkti puhul, millise kihelkonna polügooni sisse see punkt jääb, ning lisab punktile vastava kihelkonna info (sh info selle kohta, millise murdeala alla kihelkond kuulub).

kesk_khk <- kihelkonnad %>% filter(Dialect_et == "Kesk")
kesk_atlas <- atlas_khk %>% filter(Dialect_et == "Kesk")

ggplot() +
    geom_sf(data = kesk_khk) +
    geom_sf(data = kesk_atlas) +
    labs(title = "Keskmurde kihelkonnad ja murdeatlase punktid")

Võtame kaardilt ära ka koordinaadistiku ja värvime tausta tumehalliks

ggplot() +
    geom_sf(data = kesk_khk) +
    geom_sf(data = kesk_atlas, alpha = 0.5, size = 3, aes(color = KeelendBin)) +
    labs(title = "Keskmurde kihelkonnad ja murdeatlase punktid") +
    theme(panel.grid = element_blank(), # kaota koordinaadistik
          axis.text = element_blank(), # kaota telgede tekst
          axis.ticks = element_blank(), # kaota telgede kriipsud
          panel.background = element_rect(fill = "grey40")) # lisa joonisele taust, mis oleks täidetud halli värviga

Väiksema ala puhul võime punktide asemel kuvada ehk hoopis konkreetsete keelendite silte.

ggplot() +
    geom_sf(data = kesk_khk) +
    geom_sf_text(data = kesk_atlas, aes(label = Keelend), size = 3) + # sildid
    labs(title = "Keskmurde kihelkonnad ja murdeatlase keelendid") +
    theme(panel.grid = element_blank(),
          axis.text = element_blank(),
          axis.ticks = element_blank(),
          axis.title = element_blank(), # kaotame x- ja y- telje pealkirjad
          panel.background = element_rect(fill = "grey40"))

Muude andmestike (nt ruumiandmete + mitteruumiandmete) ühendamiseks saab kasutada muid ..._join()-funktsioone (paketist dplyr, mis peaks laaditama automaatselt, kui laadid paketi tidyverse). Näiteks left_join() ühendab kaks andmestikku nii, et uude andmestikku jäävad vasakpoolsest andmestikust kõik read ja parempoolsest andmestikust need read, mis tal on vasakpoolsega ühised. Säilib ka vasakpoolsete andmete andmetüüp (nt kui vasakpoolne andmestik on ruumiandmete andmestik ja parempoolne tavaline tabel, on ühendamisel tekkiv andmestik ka ruumiandmete andmestik). Teiste join-meetodite kohta saad lugeda, kui trükid konsooli ?join ja vajutad Enterit.

Kui tahame ühendada nüüd kihelkondade polügoonide andmeid (kihelkonnad) ja murdekorpuse sagedusandmeid (korpus), peame kõigepealt tegema kindlaks, millised on need tulbanimed, mis mõlemas andmestikus sisaldavad samu väärtusi.

names(kihelkonnad)
##  [1] "ID"         "Parish_id"  "Name"       "Ger_name"   "Comment"   
##  [6] "Problem"    "Shape_Leng" "Dialect_en" "Shape_Le_1" "Shape_Area"
## [11] "Dialect_et" "geometry"
names(korpus)
## [1] "Murre"  "Murrak" "eiole"  "pole"

Ühendame kihelkondade kihi tulba Parish_id põhjal ja korpuse kihi tulba Murrak põhjal. Mõlemad sisaldavad kihelkondade lühendeid.

yhendatud <- left_join(kihelkonnad, korpus, by = c("Parish_id" = "Murrak"))

Värvime nüüd kihelkonnad vastavalt sellele, kui suur on mingis kihelkonnas pole kasutamise osakaal.

ggplot() +
    geom_sf(data = yhendatud, aes(fill = pole))

Valime värviskaala, kus helesinine märgib väikest osakaalu, tumesinine suurt osakaalu ja vahepealsed väärtused jäävad nende vahele. Kihelkonnad, kust andmed puuduvad, värvime helehalliks.

ggplot() +
    geom_sf(data = yhendatud, aes(fill = pole)) +
    scale_fill_gradient(low = "lightblue", high = "dodgerblue4", na.value = "grey80") +
    theme_bw()

19.9 Jooniste eksportimine

Kaarte saab eksportida paremal olevast Plots aknast, valides Export (see toimib juhul, kui oled enne määranud, et R Markdowni koodiplokkide väljundeid ei kuvataks markdowni faili sees; vastasel juhul ei kuvata Plots jaotises midagi). Samuti võib koodi lõppu lisada funktsiooni ggsave("failinimi.png"). Seejärel salvestatakse fail Working directory asukohta, mida saad vaadata funktsiooniga getwd().

ggplot() +
    geom_sf(data = yhendatud, aes(fill = pole)) +
    scale_fill_gradient(low = "lightblue", high = "dodgerblue4", na.value = "grey80") +
    theme_bw()
ggsave("minu_kaart.png")

Veidi rohkem kontrolli joonise parameetrite üle saad, kui kasutad png(), tiff() vmt funktsiooni, lisad selle järele oma joonise koodi ja kõige lõppu dev.off().

png(filename = "minu_kaart.png", width = 12, height = 8, units = "cm", res = 400)
ggplot() +
    geom_sf(data = yhendatud, aes(fill = pole)) +
    scale_fill_gradient(low = "lightblue", high = "dodgerblue4", na.value = "grey80") +
    theme_bw()
dev.off()

19.10 Ülesanne

  1. Loe sisse kultuurimälestiste polügoonid failist asustusyksus_malestised.gpkg.
malestised <- ...
  1. Filtreeri andmestikust välja ainult Tartumaa asustusüksuste andmed.
tartumaa_malestised <- ...
  1. Värvi Tartu maakonna asustusüksused vastavalt sellele, kui palju on seal kultuurimälestisi kokku. Vali sobiv värvipalett. Selleks, et rõhutada erinevusi väikeste väärtuste vahel ja peita erinevusi suurte väärtuste vahel, võib kasutada scale-funktsiooni sees näiteks argumenti trans = "log1p".
ggplot() +
    geom_sf(...) +
    scale_fill_...(trans = "log1p")
  1. Salvesta see Rmd-fail või eraldi R-i skriptifail joonise tegemiseks vajaliku koodiga ja tehtud kaart nimega praktikum19_yl1.png.

19.11 R-i raamatud ja juhendid

R-i ja ruumiandmete kohta on hea ja ülevaatlik kursus ka aadressil http://aasa.ut.ee/Rspatial/.

R for Data Science
Geocomputation with R
R Cookbook
R Graphics Cookbook
R Markdown: The Definitive Guide