R-ohjelmointi.org

Tilastotieteellistä ohjelmointia R-kielellä

Interaktiivinen kuntakartta, vol 2: Millä alueilla asuvat osingonsaajat?

Jarno kirjoittikin jo aiemmin interaktiivisen kuntakartan muodostamisesta R:llä leafletR-pakettia hyödyntäen. Esitän seuraavassa toisen tavan toteuttaa interaktiivinen kuntakartta hyödyntämällä R:ää, Javascriptiä ja SVG-tiedostomuotoa. Idea syntyi tarpeesta tehdä kuntakarttojen teko mahdollisimman helpoksi R:ää osaamattomalle käyttäjälle. Ratkaisussa on lisäksi etuna kustomoitavuus (kehittäjille) ja paikallisuus (ratkaisu ei nojaa pilvipalveluihin, joka saattaa olla este esimerkiksi arkaluontoisia tietoja käsitellessä).

Tekstin rakenne on seuraava: ensiksi esitän verotilastoihin perustuvan käyttöesimerkin liittyen osingonsaajiin, toiseksi käyn läpi toteutuksen taustalla olevan tekninen toteutuksen.

Pörssiosinkojen saajat kunnittain

Suurin osa pörssiyhtiöistä maksaa osinkoja kerran vuodessä kevään ja kesän aikana. Onkin mielenkiintoista tarkastella, missä suomalaiset sijoittajat asuvat ja onko alueiden välillä eroja pörssiyhtiöihin sijoittamisessa. Tähän tarjoaa mahdollisuuden Tilastokeskuksen ja Verohallinnon yhteistyössä muodostamat verotilastot [http://vero2.stat.fi/PXWeb/pxweb/fi/Vero/].

Tilasto sisältää kunnittain pörssiyhtiöistä osinkoja saaneiden määrän, yleisesti verovelvollisten määrän sekä saatujen osinkojen jakaumaa kuvaavia tunnuslukuja. Seuraavassa haetaan Tilastokeskuksen rajapinnasta tarvittavat tiedot ja siivotaan data valmiiksi kartan piirtämistä varten. Poikkeuksellisesti rajapinnasta on haettava erikseen myös kuntakoodit kuntien nimen ohelle, jotta tilastoaineisto saadaan yhdistettyä karttapohjaan kuntakoodien perusteella.

[Tähän ensimmäinen pätkä koodia, jossa haetaan ja siistitään aineisto]
# Kirjastot
source("https://topiasp.github.io/projects/project3/createMap.R")
library(pxweb)
library(jsonlite)
library(reshape)
library(RColorBrewer)
library(dplyr)
 
setwd('C:\\Users\\lenovo\\Desktop\\kartta\\')
 
# Esimerkkidata: Osinkoja listatuista yhtiöistä saaneet kunnittain + asiakkaiden määrä
 
dat <-  get_pxweb_data(url = "http://vero2.stat.fi/PXWeb/api/v1/fi/Vero/Henkiloasiakkaiden_tuloverot/lopulliset/Alue/191_alue.px",
                 dims = list(Verovuosi = c('2015'),
                             Erä = c('HT_T_10',
                                     'HT_PT_5_1_3'),
                             Alue = c('*'),
                             "Tuloluokka *" = c('T000'),
                             Tunnusluvut = c('N','Median')),
                 clean = TRUE)
#[HT_PT_5_1_3]   5.1.3 - Pääomatulona verotetut osingot (listatut yhtiöt) (TVL 33 §)
 
# Haetaan kuntakoodit erikseen
datMeta <- readLines("http://vero2.stat.fi/PXWeb/api/v1/fi/Vero/Henkiloasiakkaiden_tuloverot/lopulliset/Alue/191_alue.px",
                     warn=F,encoding='UTF-8')
koodisto <- fromJSON(datMeta)
koodisto <- data.frame(kuntakoodi=koodisto$variables$values[[3]],kuntanimi=koodisto$variables$valueTexts[[3]],stringsAsFactors = F)
 
# Pelkät kuntakoodit 
koodisto <- subset(koodisto,nchar(kuntakoodi)==3)
 
# Yhdistetään data & koodisto (samalla tippuu muut aluetasot)
dat <- merge(dat,koodisto,by.x='Alue',by.y='kuntanimi')
 
# Inhimillisemmät nimet
levels(dat$Erä) <- c('asiakkaita','osinkoja')
 
# Tiputetaan turhat muuttujat
dat <- dat[,c('Alue','Erä','values','kuntakoodi','Tunnusluvut')]
 
# Tunnusluvut riveiltä sarakkeiksi
dat <- data.frame(cast(dat,Alue+kuntakoodi~Erä+Tunnusluvut,value='values'))
 
# Poistetaan v.2015 lakkautetut kunnat, joille ei löydy lukuja aineistosta sekä koko maan tiedot
dat <- dat[!is.na(dat$asiakkaita_Saajien.lukumäärä),]
dat <- dat[dat$kuntakoodi!='000',]
 
# Luodaan kuntanimi-muuttuja karttafunktiota varten ja konvertoidaan faktorista characteriksi
dat$kuntanimi <- as.character(dat$Alue)
 
# Korjataan v. 2016 kuntaliitokset 
dat[dat$kuntakoodi==532,c('kuntakoodi','kuntanimi')] <- c('398','Lahti') 
dat[dat$kuntakoodi==164,c('kuntakoodi','kuntanimi')] <- c('301','Kurikka')
dat[dat$kuntakoodi==283,c('kuntakoodi','kuntanimi')] <- c('098','Hollola')
dat[dat$kuntakoodi==319,c('kuntakoodi','kuntanimi')] <- c('783','Säkylä')
dat[dat$kuntakoodi==442,c('kuntakoodi','kuntanimi')] <- c('051','Eurajoki')
dat[dat$kuntakoodi==174,c('kuntakoodi','kuntanimi')] <- c('297','Kuopio')

Tämän jälkeen lasketaan tarvittavat luvut sekä käsitellään vuosien 2016 ja 2017 kuntaliitosten vaikutukset aineistoon. Asiakkaiden ja osingonsaajien lukumäärät voidaan laskea suoraan yhteen kahden kunnan välillä, mutta mediaaniosinkoja ei. Ratkaisin tämän laskemalla osingonsaajilla painotetun keskiarvon kuntaliitoskuntien mediaaniosingosta.

[Toinen pätkä koodia, jossa aggregoidaan]
 
## Lasketaan tunnusluvut ja aggregoidaan uusiksi kuntaliitosten huomioimiseksi
 
kd <- data.frame(dat %>% group_by(kuntakoodi,kuntanimi) %>%
                   summarise(
                   osinkoja_saaneiden_osuus=round(sum(osinkoja_Saajien.lukumäärä)/sum(asiakkaita_Saajien.lukumäärä)*100,2),
                   asiakkaita=sum(asiakkaita_Saajien.lukumäärä),
                   osingonsaajia=sum(osinkoja_Saajien.lukumäärä),
                   mediaaniosinko=weighted.mean(x=osinkoja_Mediaani,w=osinkoja_Saajien.lukumäärä))
)
 
# Luodaan kartat: 1. pelkkä svg ja 2. html-sivu
 
createMap(dataToMap=kd,type='svg',variableToMap ='osinkoja_saaneiden_osuus',title='Osingot 2015'
          ,numberOfClasses = 10)
createMap(dataToMap=kd,type='html',variableToMap= 'osinkoja_saaneiden_osuus',title='Osingot 2015',numberOfClasses = 10)
 
 
# Haetaan maakunnat
library(XML)
 
luokitusavain <- readHTMLTable('http://tilastokeskus.fi/meta/luokitukset/kunta/001-2017/kunta_mk.html')

Kartta syntyy seuraavalla funktiolla, joka tulostaa työkansioon tarvittavat tiedostot eli SVG- tai HTML-tiedoston sekä muut tarvittavat tiedostot:

createMap(dataToMap=kd,type='svg',muuttuja='osinkoja_saaneiden_osuus',title='Osingot 2015', palette='default', numberOfClasses=10)

Funktion syötteet ovat seuraavat:

  • dataToMap: Data.frame, josta kartta piirretään. Jos ’kuntakoodi’-muuttujaa ei löydy, oletetaan, että kuntakoodit ovat ensimmäisessä sarakkeessa. Kaikista numeerisista muuttujista muodostetaan luvut osaksi HTML-tiedostoa. ’kuntanimi’-muuttujasta oletetaan löytyvän kuntien nimet
  • type: voi olla joko ’svg’ tai ’html’ – edeltävä tuottaa svg-tiedoston valitun muuttujan perusteella, jälkimmäinen html-sivun, jossa on lisäksi luokkien rajat ja mahdollisuus valita jokin toinen muuttuja. HTML-versio kartasta löytyy täältä: https://topiasp.github.io/projects/osinkokartta_r_ohjelmointi/ (klikkaamalla muuttujan nimeä ’osinkoja_saaneiden_osuus’, voi värittää kartan toisella värillä).
  • variableToMap: muuttuja, jonka perusteella kartta väritetään
  • title: määrittelee tulostettavan tiedoston sekä näissä käytetyn otsikon.
  • palette: väripaletti. Värien lukumäärän vastattava luokkien lukumäärä (numberOfClasses). Default: RcolorBrewer -paketin RdYlGr-paletti.
  • numberOfClasses: luokkien lukumäärä eli ts. Moneenko (yhtä suureen) luokkaan kunnat jaetaan väritystä varten. Default=10;

image001

Kartta ja pylväskaavio paljastavat, että osingonsaajien osuus kunnan verovelvollisista kasvaa siirryttäessä idästä länteen ja toisaalta pohjoisestä etelään. Osingonsaajien osuus on muuta maata korkeampi Uudenmaan ja Pohjanmaan maakunnissa ja matalampi Pohjois-Pohjanmaalla ja Lapissa. Pohjois-Karjalan yksittäinen vihreä läiskä on Outokumpu.

Suuri osingonsaajien osuus ei toki tarkoita, että kaikki olisivat osinkomiljonäärejä. Vuonna 2015 koko maassa mediaaniosinko oli 168 euroa (osingonsaajia oli 581 000). Mediaaniosinko näyttää lisäksi silmämääräisen arvion perusteella jäävän pienemmäksi niissä kunnissa, joissa osingonsaajien osuus suurempi. Osakesijoittamisen ollessa laajemman kansanosan hupia mahtuu joukkoon enemmän pienempiä osinkoja.

Tarvittavat lyhenteet: QGIS+SVG+R+JS+CSS+HTML

Asiaan vihkiytyneet lukijat saattavat arvaavat toteutuksen rakenteen pelkästään kirjainlyhennelmien perusteella. Toteutuksen ytimessä on SVG-muotoon käännetty kuntakartta. SVG (Scalable Vector Graphics) on XML-merkintäkieleen perustuva vektorikuvien kuvauskieli. Tässä yhteydessä tiedostomuodon etu on manipuloitavuus: koska karttapohja on kuvattu tekstinä, voidaan sitä helposti manipuloida esim. R:n tekstinkäsittelyyn soveltuvilla funktioilla esim. liittäen siihen koodia.

Tarvittavan kuntakartan hain Tilastokeskuksen rajapinnasta [http://www.stat.fi/tup/rajapintapalvelut/kuntapohjaiset_tilastointialueet.html]. Rajapinta ei tarjoa karttoja SVG-muodossa, vaan tein konversion shapefilestä QGIS-paikkatieto-ohjelmistolla (Tilastokeskus on laatinut perusteelliset ohjeet rajapintojen käyttöön paikkatieto-ohjelmilla [http://tilastokeskus.fi/tup/rajapintapalvelut/ohje_qgis_2.0.pdf]). Konversiossa on syytä pitää huoli siitä, että avaimena käytettävät tiedot kulkevat konversion mukana. Kuntakoodeja tarvitaan nimittäin varsinaisen tilastoaineiston yhdistämiseen karttapohjaan.

SVG-tiedoston manipuloinnissa hyödynsin R:ää. Jokainen kunta muodostaa yksittäisen elementin tiedostossa, joten tarvittavan toiminnallisuuden synnyttämiseksi, kuhunkin elementtiin piti liittää pätkä javascript:iä. Luonnollisesti en jaksanut tehdä tätä jokaiselle kunnalle erikseen, vaan tunnistin manipuloitavat rivit R:llä ja liitin tarvittavan koodin ohjelmallisesti. Esimerkiksi osa Helsingin rajat määrittelevän elementistä, johon lisäsin tarvittavan onmouseover:in:


Itse karttapohja ei välttämättä tarvitse (muutamaan pientä operaatiota) enempää manipulaatiota, vaan väritys voidaan tehdä selaisemassa javascriptin avulla. Yksi vaihtoehto on muodostaa pelkkä SVG-tiedosto, johon värit syötetään värit valmiiksi, kuten tein edellä. Tällöin kunkin kunnan väritys hoidetaan R:ssä manipuloimalla SVG-tiedoston elementtien tyyliä.

Toinen vaihtoehto on muodostaa värit selaimessa. Tällöin HTML-tiedostoon tulee syöttää vain tarvittava data, jonka perusteella lasketaan luokkarajat ja väritetään kunnat niiden mukaan. Tämä on toteutettu puolestaan javascriptillä.


Vastaa

Sähköpostiosoitettasi ei julkaista. Pakolliset kentät on merkitty *

Category