Datavaalit osa 1 – vaali- ja kuntadatan kokoaminen ja paketointi

Datavaalit Syksyn kunnallisvaalien yhteydessä on mahdollisuus kokeilla vaaleihin ja päätöksentekoon liittyvän tiedonlouhinnan mahdollisuuksia ja tuoda esiin kehityskohteita päätöksentekoon kytkeytyvien tietoaineistojen saatavuuden ja yhteiskunnan läpinäkyvyyden lisäämiseksi. Aiheen tiimoilta on käynnistynyt ruohonjuuritason Datavaalit-tempaus, jossa eri toimijat keräävät, pöyhivät, ja julkaisevat vaaleihin liittyvää dataa ja sen pohjalta tehtäviä havaintoja. Datavaalit-tempauksella ei ole muodollista organisaatiota, vaan aiheesta kiinnostuneet ovat tervetulleita liittymään mukaan itselleen sopivalla tavalla. Ideoita ja tietolähteitä on koottuna täällä. Jos aihepiiri kiinnostaa, nyt on hyvä aika hypätä kelkkaan. Louhos-tiimimme on mukana Datavaalit-tempauksessa kehittämällä yhteisövetoista soRvi-ohjelmakirjastoa yhteiskunnan tietovirtojen seulontaan.

Vaalitilastojen kokoaminen Aloitimme kunnallisvaaleihin valmistautumisen keräämällä Helsingin Sanomien pyynnöstä kattavan paketin kuntatason sosioekonomista dataa ja aiempiin vaaleihin liittyviä tilastoja valmiiksi esikäsitellyssä taulukkomuodossa yhdistämällä Tilastokeskuksen ja Maanmittauslaitoksen avoimia kuntatason aineistoja. Data sisältää kuntatason tietoja väestöstä, koulutuksesta, työttömyydestä, ja muista indikaattoreista yhdistettynä kunnallisvaalien tuloksiin vuosilta 2000, 2004 ja 20008 sekä eduskuntavaalien tuloksiin vuosilta 2007 ja 2011. Aineistoja hyödynnetään mm. maanantain 21.5.2012 HS Open-tapahtumassa, jossa koodaajien, graafikoiden ja toimittajien muodostamat tiimit pöyhivät tätä ja muita kunnallisvaaleihin liittyviä datoja. Jäämme mielenkiinnolla odottamaan, mitä tapahtuman osallistujat löytävät näiden tietoaineistojen kätköistä.

Hakurutiinit soRviin Esikäsitellyt kuntatason tietoaineistot ovat ladattavissa yllä olevan linkin kautta HS:n palvelimelta, mutta tämän blogipostauksen lopussa olevalla soRvi-kirjastoon pohjautuvalla koodilla niiden automaattinen luku onnistuu myös suoraan alkuperäislähteistä. Koodissa käytetyt hakurutiinit ovat toistaiseksi saatavilla vain soRvin GitHub-kehitysversion kautta. Tiedot on nyt koostettu kaksiulotteisiksi taulukoiksi, sillä näiden käsittely ja yhdistely muihin tietoihin onnistuu helposti tavanomaisilla taulukko-ohjelmilla. Haittana on, että taulukon metatietoja joudutaan kokoamaan tekstimuotoon otsikkoriville. Automatisoidun analyysin kannalta moniulotteiset taulukot ja tietokantapohjaiset esitysmuodot olisivat optimaalisempia. Pyrimme jatkossa kehittämään soRvi-kirjastoa myös tältä osin ja uudet ehdotukset ja kontribuutiot ovat tervetulleita.

Ongelmia Tilastokeskuksen aineistoilla Aineistoja kootessamme havaitsimme, että Tilastokeskuksen avointen aineistojen luku vaatii pelkästään Windowsilla toimivaa ja suljetusti lisensoitua PX-Edit-ohjelmaa. Tämä muodostaa merkittävän pullonkaulan Tilastokeskuksen avointen aineistojen automatisoidulle saatavuudelle ja käytölle: 2621 avoimesta datataulukosta vain 29% (761 tiedostoa) oli automatisoidusti luettavissa verkon yli R-kielen valmiilla hakurutiineilla. Toistaiseksi PX-Edit näyttää olevan ainoa loppuun viilattu ohjelma Tilastokeskuksen käyttämän dataformaatin lukuun, mutta ohjelma toimii vain Windowsilla, sen käyttöä verkon yli ei saa kohtuullisella työmäärällä automatisoitua, ja lisenssiehdot hankaloittavat vaihtoehtoisten lukurutiinien tuottamista. Toivommekin Tilastokeskuksen jakavan avoimet aineistonsa jatkossa myös XML-tiedostoina tai muussa standardimuodossa, jolloin niiden luku ja automatisoitu yhdistely muihin tietoaineistoihin sujuvoituisi merkittävässä määrin kasvattaen entisestään tämän laadukkaan datakokoelman merkitystä ja arvoa.

Alla vielä lähdekoodi, jolla Tilastokeskuksen vaali- ja kunta-aineistojen haku ja yhdistely alkuperäislähteistä onnistuu soRvin kehitysversiolla >0.1.70.


# This file is a part of the soRvi program 0.1.70
# louhos.github.com/sorvi/

# Copyright (C) 2012 Leo Lahti, Juuso Parkkinen and Joona Lehtomäki. 
# All rights reserved. Contact: <http://louhos.github.com/contact.html>

# This program is open source software; you can redistribute it and/or
# modify it under the terms of the FreeBSD License (keep this notice):
# http://en.wikipedia.org/wiki/BSD_licenses

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


##########################################################################

#
# This script was used to retrieve and preprocess 
# Finnish election data tables for HSOpen 5/2012
#

##########################################################################

library(sorvi)
tabs <- NULL

print("Tilastokeskus")

# (C) Tilastokeskus 2012
# "http://pxweb2.stat.fi/Database/Kuntien%20perustiedot/Kuntien%20perustiedot/Kuntaportaali.px

statfi <- GetMunicipalityInfoStatFi() 
municipalities <- rownames(statfi)
write.table(statfi[municipalities, ], file = "HSOpen/Tilastokeskus-KuntienAvainluvut.csv", sep = ";", quote = FALSE, row.names = FALSE)

tabs <- statfi[municipalities, ]

##########################################################################

print("MML")

# (C) MML 2012
# http://www.maanmittauslaitos.fi/aineistot-palvelut/digitaaliset-tuotteet/ilmaiset-aineistot/hankinta

data(MML)
mml <- GetMunicipalityInfoMML(MML)    
write.table(mml[municipalities, ], file = "HSOpen/MML.csv", sep = ";", quote = FALSE, row.names = FALSE)

tabs <- cbind(tabs, mml[municipalities, ])

##########################################################################

print("Eduskuntavaalit 2007-2011")

tab <- GetParliamentaryElectionData("municipality")

# Match election data with other municipality data and write to output
write.table(tab[municipalities,], file = "HSOpen/Eduskuntavaalit_2007_2011.csv", sep = ";", quote = FALSE, row.names = FALSE)

tabs <- cbind(tabs, tab[municipalities, ])

##############################################################################

print("Kunnallisvaalit 2000")

tab <- GetMunicipalElectionData2000("all.municipality.level.data")

# Match election data with other municipality data
write.table(tab[municipalities,], file = "HSOpen/Kunnallisvaalit2000.csv", sep = ";", quote = FALSE, row.names = FALSE)

tabs <- cbind(tabs, tab[municipalities, ])

###############################################

print("Kunnallisvaalit 2004")

tab <- GetMunicipalElectionData2004("all.municipal")

inds <- match(municipalities, rownames(tab))

write.table(tab[inds,], file = "HSOpen/Kunnallisvaalit2004.csv", sep = ";", quote = FALSE, row.names = FALSE)

tabs <- cbind(tabs, tab[inds, ])

##############################################################################

print("Kunnallisvaalit 2008")

tab <- GetMunicipalElectionData2008("all.municipal")

inds <- match(municipalities, rownames(tab))

write.table(tab[inds,], file = "HSOpen/Kunnallisvaalit2008.csv", sep = ";", quote = FALSE, row.names = FALSE)

tabs <- cbind(tabs, tab[inds, ])

###############################################

# Kaikki taulukot - kooste:

write.table(tabs, file = "HSOpen/HSOpenKuntadata.csv", sep = ";", quote = FALSE, row.names = FALSE)

Kategoria(t): Uncategorized | 2 kommenttia

soRvi Sitran hankehaun viimeiselle kierrokselle, esitelmiä kotimaassa ja ulkomailla

Suomalaisen avoimen datan työkalupakin soRvin kehitystyö jatkuu aktiivisena. Tässä
lyhyesti uusimpia kuulumisia.

Sitran hankehaun viimeiselle kierrokselle
Hanke valittiin Sitran Uusi demokratia-hankehaun viimeiselle kierrokselle yli 140 hankeidean joukosta. Päätöksistä tiedotetaan huhtikuun lopulla. Haussa on rahoitusta osa-aikaiselle projektikoordinaattorille ja opinnäytetyön tekijälle, mikä tukisi toteutuessaan merkittävästi yhteisövetoista hankettamme. Koordinaattorin vakanssi saattaa siis pian tulla hakuun – seuraa blogia.

Kaupunkitutkimuksen päivät, Helsinki 3-4.5.2012
soRvi on mukana kaupunkitutkimuksen päivillä Helsingissä esitelmällä Avoin suomalainen kaupunkidata – välineet, haasteet ja tulevaisuus. Esitys on suunnattu ennen kaikkea yhteiskunnan avoimia datavirtoja työssään nyt tai tulevaisuudessa hyödyntäville tutkijoille sekä virkamiehille ja keskittyy kaupunkitutkimuksen kannalta keskeisiin tietoaineistoihin ja analyysivälineisiin; soRvi tarjoaa kattavan ja avoimen menetelmäkirjaston kotimaisten aineistojen hakuun, yhdistelyyn ja visualisointiin.

Share-konferenssi, Belgrad 26.4.2012
Belgradin Share-konferenssi on 2000 osallistujan kolmipäiväinen digitaalinen festivaali, jossa digitaalisen kulttuurin uusimpia virtauksia käsitellään työpajojen, esitelmien, hackathonien ja audiovisuaalisen viihteen tahdittamana. soRvi on tapahtumassa mukana viemässä suomalaista avoimen datan osaamista maailmalle; esitelmöimme avoimen datan ja algoritmien avaamista uusista mahdollisuuksista yhteiskunnan läpinäkyvyyden lisäämisessä Suomessa saatujen kokemusten pohjalta.

Instanssi-festivaalin videot verkossa
Hankkeen uusimpia tuloksia esiteltiin maaliskuussa Jyväskylässä digitaalisen tekemisen Instanssi-festivaaleilla. Esitelmä on nyt ladattavissa verkossa YouTuben kautta.

Datavaalit 2012 tulossa
Datavaalit 2012 on ehdotus kunnallisvaaleihin tähtäävästä kunnallisidatan scrappaus- ja julkaisukokonaisuudesta, jonka ensisijaisena kohderyhmänä olisivat datajournalistit ja avoimen demokratian sovellusten kehittäjät. Louhos/soRvi tukee yhteisövetoista hanketta menetelmäkehityksen osalta.

Kategoria(t): Uncategorized | Jätä kommentti

Louhos-projekti laajenee

Julkisten tietoaineistojen määrä kasvaa yhteiskunnassa kiihtyvää tahtia. Laaja saatavuus ja käyttö on omiaan nostamaan yhteisten tietovarantojemme arvoa, mutta aineistojen sujuva saatavuus ja käyttö edellyttää tehokkaita välineitä. Louhos on yhteisövetoinen kokoelma avointa lähdekoodia ja välineitä suomalaiselle avoimelle datalle. Se edistää julkisten aineistojen saatavuutta ja tuottaa uusia välineitä yhteiskunnan tietovirtojen analysointiin. Projekti palvelee kansalaisia, opiskelijoita, ja tietovirtojen parissa työskenteleviä ammattilaisia.

Näitä päämääriä edistetään nyt seuraavin uudistuksin:

Louhos-projekti laajenee tarjoamaan yleisen ja keskitetyn koodivaraston suomalaisen avoimen datan yhteisön tarpeisiin. Koodi suomalaisten datavirtojen avaamiseen on tervetullutta kaikilla ohjelmointikielillä. Projekti auttaa yhdistämään voimavarat ja koordinoimaan yhteistyötä.

GitHub käyttöön Projektin ylläpito on siirretty GitHubiin. Kaikki palaute ja materiaali avoimen datan hakuun, esikäsittelyyn, analyysiin ja visualisointiin sekä projektin kehittämiseen liittyen on tervetullutta.

Wikisivu avattu Kehitystyön tueksi on luotu avoin wikisivusto. Wikin nykyinen painopiste on Louhoksen tämän hetken pääprojektissa, joka on kattava Suomi-datan R-kirjasto soRvi.

Kotisivu uudistui Louhoksen uudet kotisivut löytyvät osoitteesta http://louhos.github.com. Projektille löytyy myös englanninkielinen esittelysivu.

Mukana menossa Instanssi-festareilla Louhos on mukana digitaalisen tekemisen Instanssi-festivaaleilla Jyväskylässä 9-11.3.2012. Tsekkaa esittelytraileri.

Ota yhteyttä, jos puuhaat avoimen datan parissa. Osallistumismahdollisuuksia on listattuna täällä. Toivotamme uudet tekijät tervetulleiksi suomalaisiin datanavaustalkoisiin!

Kategoria(t): Suomi, tiedonlouhinta, visualisointi | Avainsanat: , | Jätä kommentti

Uuden kuntajaon mukainen kuntien yhdistäminen ja visualisointi

Valtiovarainministeriön valmistelema suunnitelma kuntien yhdistämisestä on herättänyt viime aikoina runsaasti keskustelua. Esimerkiksi Suomen kuvalehti julkaisi vuorovaikutteisen visualisoinnin kaavailluista kuntarajoista.

Uuden kuntajaon visualisointi Suomen kartalla edellyttää nykyisten
kuntarajojen yhdistämistä, jonka tekninen toteuttaminen herätti kysymyksiä datajournalismin keskustelulistalla. Kuntien yhdistelyrutiineille näytti olevan kysyntää, joten päätimme julkaista esimerkin kuntarajojen yhdistämisestä R:ssä soRvi-pakettia hyödyntäen.

Esimerkkikoodi yhdistää kunnat, visualisoi uudet kunnat (kuvat 1-2) ja uusien kuntien väkiluvun (kuva 3) Suomen kartalla. Lopuksi tulostetaan uusien kuntarajojen mukainen ESRI shape-tiedosto, jonka jatkokäsittely onnistuu muillakin paikkatieto-ohjelmistoilla, kuten avoimen lähdekoodin Quantum GIS:llä. Valmiisiin paikkatieto-ohjelmistoihin (QGIS, ArcGIS) verrattuna soRvin käyttö mahdollistaa paikkatiedon kytkemisen muihin kuntakohtaisiin aineistoihin, joita voidaan ladata ja esikäsitellä soRvin avulla; alla paikkatietoja yhdistetään esimerkinomaisesti Tilastokeskuksen PC-axis-muotoisiin aineistoihin. Kaikki analyysivaiheet voidaan näin toteuttaa kätevästi saman laskentaympäristön sisällä. Suuri etu on myös, että lähtötaulukkoa muuntamalla voidaan tuottaa nopeasti erilaisia kuntaliitoksia.

Alla oleva esimerkkikoodi edellyttää uuden kuntajaon määrittelemistä työhakemistoon lisättävällä tiedostolla. Koodi hakee nykyiset kuntarajat Maanmittauslaitokselta ja kytkee nämä YLEn yhteenvedon pohjalta mukailtuihin kuntaliitoksiin. Kuntaliitokset määritellään Louhoksen github-sivulta haettavassa tiedostossa. Vaihtoehtoisia kuntaliitoksia voi määritellä itse muokkaamalla tätä tiedostoa ja tallettamalla sen työhakemistoon.

Vastaan tulleita haasteita: 1) Esimerkki mahdollistaa vain nykyisten kuntarajojen mukaisten kuntien yhdistämisen. Kuntien jakaminen vaatisi jakolinjojen ja kuntakohtaisten polygonien uudelleen määrittelyä. Näitä ei tiettävästi ole saatavilla koneluettavassa muodossa, joten rajoite koskee kaikkia paikkatieto-ohjelmia. 2) (3.3.2012) soRvin funktioita on nyt päivitetty siten, että uudet naapuruskunnat saadaan visualisoitua eri värein kuvaan 1. Sen sijaan kuva 2, joka näyttää lisäksi nykyiset kunnat rajaviivoin ei vielä väritä uusia naapuruskuntia eri värein. Toistettava esimerkki löytyy alta blogikommenteista. Tämän varmaankin saisi toteutettua pienellä lisäkoodauksella. Ratkaisuehdotuksia otetaan vastaan.

Tässä vielä esimerkkikoodi ja sillä tuotetut uuden kuntajaon visualisoinnit (klikkaa kuvista suurempi versio):


# Suomen kuntien yhdistäminen ja visualisointi uuden kuntajaon mukaan

# Copyright (C) 2012 Leo Lahti ja Joona Lehtomäki
# Contact: sorvi-commits@lists.r-forge.r-project.org
# All rights reserved.

# This program is free software; you can redistribute it and/or modify
# it under the terms of the FreeBSD License:
# http://en.wikipedia.org/wiki/BSD_licenses

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

# This script was implemented with soRvi version 0.1.55

library(sorvi)
library(rgeos)
library(rgdal)
if (!gpclibPermit()) { gpclibPermit() }

# ----------------------------------------------

# Lue nykyiset kuntarajat Maanmittauslaitoksen aineistosta
# (C) MML 2011
data(MML)
fi.kunnat <- MML[["1_milj_Shape_etrs_shape"]][["kunta1_p"]]

# Länsi-Turunmaan nimi vaihtui Paraisiksi vuoden 2012 alusta,
# lisää muutos dataan
kunnat <- as.character(fi.kunnat$Kunta.FI)
kunnat[[which(kunnat == "Länsi-Turunmaa")]] <- "Parainen"
fi.kunnat$Kunta.FI <- factor(kunnat)

# ----------------------------------------------

# Lue uusi kuntajako tekstitiedostosta uusi.kuntajako.tab
# tai luo vaihtoehtoinen määrittelytiedosto
kuntajako.file <- "uusi.kuntajako.tab"

# Hae uusi kuntajako verkosta, ellei sitä ole määritelty työhakemistossa
if (!kuntajako.file %in% dir()) {
download.file("http://antagomir.github.com/louhos/files/uusi.kuntajako.tab",
destfile = kuntajako.file)
}

lines <- readLines(kuntajako.file)

uudet.kunnat <- list()
for (li in lines) {
if (!li == "") {
uusi.kunta <- strsplit(li, "\\:")[[1]][[1]]
yhdistyvat <- Strip(strsplit(strsplit(li, "\\:")[[1]][[2]], "\\,")[[1]])
uudet.kunnat[[uusi.kunta]] <- yhdistyvat
}
}

map <- NULL
for (i in 1:length(uudet.kunnat)) {
uusi <- names(uudet.kunnat)[[i]]
vanhat <- uudet.kunnat[[i]]
map <- rbind(map, cbind(rep(uusi, length(vanhat)), vanhat))
}
map <- as.data.frame(map)
colnames(map) <- c("Uusi", "Vanha")

# ----------------------------------------------

# Maarita uusi kunta kullekin nykyisen jaon mukaiselle kunnalle

# Listaa erikseen kunnat, joita ei ole lueteltu uudessa kuntajaossa:
unknown <- setdiff(fi.kunnat$Kunta.FI, map$Vanha)
map <- data.frame(list(Uusi = c(as.character(map$Uusi), unknown),
Vanha = c(as.character(map$Vanha), unknown)))

print(paste("Tiedoston", kuntajako.file,
"uudesta kuntajaosta puuttuvat kunnat:", paste(unknown, collapse = ",")))

nykyinen.kunta <- fi.kunnat$Kunta.FI
uusi.kunta <- droplevels(map$Uusi[match(fi.kunnat$Kunta.FI, map$Vanha)])

# ----------------------------------------------

# Yhdista nykyisten kuntien alueet uusi.kunta-muuttujan
# osoittamiin uusiin kuntiin
reg <- unionSpatialPolygons(fi.kunnat, uusi.kunta, avoidGEOS = T)

# Nimea uudet kunnat taulukkoon
attr <- data.frame(Uusi.kuntajako = names(reg))

# ----------------------------------------------

# Yhdista uudet alueet ja nimet / Merge into a SpatialPolygonsDataFrame
uusi.kuntajako <- SpatialPolygonsDataFrame(reg, attr, match.ID = F)

# ----------------------------------------------

# Laske vakiluku uusille kunnille:
# Hae kuntatason tilastoja:
municipality.info <- GetMunicipalityInfo()
vakiluku <- municipality.info[["Väkiluku 31.12.2010"]]
names(vakiluku) <- rownames(municipality.info)
uusi.vakiluku <- sapply(split(vakiluku[as.character(map$Vanha)], map$Uusi), sum)
uusi.kuntajako$Vakiluku <- uusi.vakiluku[as.character(uusi.kuntajako$Uusi.kuntajako)]

# ----------------------------------------------

# Visualisoi uusi kuntajako
pic <- PlotShape(uusi.kuntajako, "Uusi.kuntajako",
type = "discrete", main = "Uusi kuntajako")

# Vaihtoehtoinen visualisointi. Esitä uudet kunnat väreillä ja
# näytä nykyiset kuntarajat viivoilla.
fi.kunnat$uusi.kunta <- uusi.kunta
pic2 <- PlotShape(fi.kunnat, "uusi.kunta",
type = "discrete", main = "Uusi kuntajako", ncol = 12)

# Visualisoi uusien kuntien vakiluku
pic3 <- PlotShape(uusi.kuntajako, "Vakiluku", type = "sequential",
main = "Uusien kuntien vakiluku",
palette = colorRampPalette(c("white", "blue"), space = "rgb"),
colorkey = FALSE, ncol = 100)

# -----------------------------------------------

# Tulosta kuvat PNG-tiedostoon
png("uusi.kuntajako.png"); print(pic); dev.off()
png("uusi.kuntajako2.png"); print(pic2); dev.off()
png("uusi.kuntajako3.png"); print(pic3); dev.off()

# -----------------------------------

# Kirjoita uuden kuntajaon mukaiset rajat ESRI-shapefileen
# HUOM: kirjoitus epäonnistuu, jos työhakemistossa on jo
# ennestaan saman niminen shp-file
writeOGR(uusi.kuntajako, "uudet_kunnat.shp", "uusi.kuntajako",
driver="ESRI Shapefile")

Kategoria(t): kunnat, Maanmittauslaitos, Paikkatieto, sorvi, Suomi, Uncategorized, visualisointi | 2 kommenttia

Presidenttiehdokkaiden kannatus ja suomalaisten hyvinvointi

Vaalituloksia ja sosioekonomisia mittareita yhdistämällä voidaan löytää yhteyksiä suomalaisten sosiaalisen taustan ja presidenttiehdokkaiden kannatuksen välillä. Tämä vuorovaikutteinen visualisointi paljastaa yleisiä trendejä presidenttiehdokkaiden kannatuksen yhteyksistä vaikkapa kuntien ikärakenteeseen ja koulutusasteeseen. Visualisointi piti nyt pistää linkin taakse, koska WordPressin oletuspalvelu ei tue vuorovaikutteisuutta.

Vastaava visualisointi on julkaistu aiemmin Tiedonlouhintaa-blogissa, minkä innoittamana lisäsimme samoille aineistoille valmiit hakurutiinit soRvi-pakettiin. Nyt vastaavan kuvaajan luominen on toistettavissa R-kielellä muutamalla komentorivillä ilman aikaa vieviä esikäsittelyvaiheita. Koodi hakee avoimia kuntatason tilastoja Tilastokeskukselta, ja vaalitulokset HS Next-blogissa julkaistusta yhteenvetotaulukosta. Vaalitulokset voitaisiin hakea myös suoraan Tilastokeskuksen tai Oikeusministeriön sivuilta. Lisätään näihinkin hakurutiinit tuonnempana. Kontribuutiot ovat tervetulleita myös tämän blogin lukijoilta. Olemme alkaneet kasata listaa soRviin suunnitelluista hakurutiineista githubin wiki-sivustolle.

Alla vielä esimerkkinä ruutukaappaus ja  lähdekoodi presidenttiehdokkaiden kannatukseen ja sosioekonomisiin indikaattoreihin liittyen:

Niinistön kannatus ja kuntien koulutusaste vaalipiireittäin


# This script is posted to Louhos blog: http://louhos.wordpress.com
# Copyright (C) 2008-2012 Juuso Parkkinen and Leo Lahti
# Contact: <sorvi-commits@lists.r-forge.r-project.org>
# All rights reserved.

# This program is open source software; you can redistribute it
# and/or modify it under the terms of the FreeBSD License
# (keep this notice): http://en.wikipedia.org/wiki/BSD_licenses

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

# Install soRvi R package
# http://sorvi.r-forge.r-project.org/asennus.html
# This script was implemented with soRvi version 0.1.49

# This script was inspired by the visualization at:
# https://sites.google.com/site/tiedonlouhintaa/

library(sorvi)
library(XML)
library(googleVis)

# Retrieve the data / Lataa aineistot

# Read voting results for the first and second election round
# Lue kuntatason aanestystulokset 1. ja 2. vaalikierrokselle
votes1 <- GetElectionResultsPresidentti2012(election.round = 1,
level = "municipalities")
votes2 <- GetElectionResultsPresidentti2012(election.round = 2,
level = "municipalities")

# Get municipality information from Tilastokeskus
# Hae kuntatason perustilastot Tilastokeskukselta
municipality.info <- GetPXTilastokeskus("http://pxweb2.stat.fi/Database/Kuntien%20perustiedot/Kuntien%20perustiedot/Kuntaportaali.px")

# Process and match the data sets / Yhdista datat

# Modifications required to match Tilastokeskus and Election data
municipality.info$Alue <- sapply(strsplit(as.character(municipality.info$Alueluokitus.2012), " - "), function (x) {x[[1]]})
municipality.info[municipality.info$Alue == "Hämeenkyrö-Tavastkyro", "Alue"] <- "Hämeenkyrö"
municipality.info[municipality.info$Alue == "Mantta", "Alue"] <- "Mänttä-Vilppula"
municipality.info$Alue <- factor(municipality.info$Alue)
municipality.info$value <- municipality.info$dat
municipality.info <- cast(municipality.info[, c("Alue", "Alueluokitus.2012", "Tunnusluku", "value")], Alue ~ Tunnusluku) # Convert to wide format

# Combine voting results from both election rounds
votes <- cbind(votes1, votes2[, -c(1,2,3)])
# Remove pre-voting counts and absolute votes to focus on voting percentages
votes <- votes[-c(grep("ennakko", names(votes)))]
votes <- votes[-c(grep("aania",   names(votes)))]

# Merge Election and Municipality statistics by regions
tab <- merge(votes, municipality.info, by.x = "Alue")

# Add time variable, required as the second column by googleVis
tab <- cbind(tab[1], Aika = 2012, tab[-1])
# Remove region id number
tab[["Aluenumero"]] <- NULL

# Visualization
# Plot Motion Chart using googleVis package
mchart.mun <- gvisMotionChart(tab, idvar = "Alue", timevar = "Aika",
options = list(height = 600, width = 700))

# Plot
plot(mchart.mun)

# Save as html (needs javascript to open!)
print(mchart.mun, file="Presidentti2012_MotionChart_20120212.html")

Kategoria(t): datajournalismi, Datavaalit 2012, sorvi, Suomi, tiedonlouhinta, Tilastokeskus, visualisointi, vuorovaikutteisuus | Jätä kommentti

Vaalitulosten vertailua vuorovaikutteisena visualisaationa

Vaalihumu alkaa onneksi jo laantua, mutta innokkaimmille tarjotaan tässä vielä osana Datavaalit2012-projektia mahdollisuus vertailla äänestystuloksia ensimmäisen ja toisen kierroksen välillä. Vertailu onnistuu kuntatasolla sekä pääkaupunkiseudun sisällä äänestysalueiden kesken.

VISUALISOINTI: VAALITULOSTEN VERTAILU KUNNITTAIN. Tässä voi esimerkiksi tarkastella kuinka aktiivisesti Soinia ja Väyrystä ensimmäisellä kierroksella äänestäneet äänestivät toisella kierroksella, ja toisaalta äänestivätkö he Niinistöä vai Haavistoa.

VISUALISOINTI: VAALITULOSTEN VERTAILU PÄÄKAUPUNKISEUDULLA. Tässä voi tarkastella äänestyskäyttäytymistä yksityiskohtaisesti pääkaupunkiseudun sisällä äänestysalueittain. PÄIVITYS 8.2. kaupungit korjattu, kiitos Martille kommentista.

Tässä esimerkkinä ruutukaappaus interaktiivisesta visualisoinnista.

Esimerkkivertailu. Väyrysen ensimmäisen kierroksen kannatuksen ja toisen kierroksen äänestysprosentin välillä näyttää olevan yhteys.

Aiemmat Louhoksessa julkaisut visualisaatiot ovat kaikki olleet staattisia, sillä R:ssä on toistaiseksi melko huonosti tarjolla työkaluja interaktiivisten visualisointien tekoon. Tähän tuli kuitenkin hiljattain muutos googleVis R-paketin myötä. Paketti tarjoaa helppokäyttöisen rajapinnan Google Chart Tools:iin, joilla kuka tahansa voi tuottaa esimerkiksi Hans Rosling -tyyppisen Motion Chartin hetkessä.

Vaalien ensimmäisen kierroksen tuloksista julkaistiinkin jo hieno Motion Chart -visualisointi, jossa oli lisäksi yhdistetty muuta Tilastokeskukselta löytyvää kuntadataa. Näytämme nyt kuinka sama tehdään R:llä yhdistäen ensimmäisen ja toisen kierroksen vaalidatat, koodi löytyy alta.

HS Next tarjoaa ensimmäisen ja toisen kierroksen äänestystulokset, ja lisäksi Tilastokeskukselta löytyi lista kunnista vaalipiireittäin, mikä helpottaa datan työstämistä yhteensopivaan muotoon. Tulokset löytyvät aluksi linkitettyinä Dropboxin kautta, kunnes keksin kuinka ne saa sisällytettyä WordPressiin. PÄIVITYS: Tämä ei taidakaan onnistua eli noilla Dropbox-linkeillä mennään.

# This script is posted to the Louhos-blog
# http://louhos.wordpress.com
# Copyright (C) 2008-2012 Juuso Parkkinen <juuso.parkkinen@gmail.com>. All rights reserved.

# This program is open source software; you can redistribute it and/or modify
# it under the terms of the FreeBSD License (keep this notice):
# http://en.wikipedia.org/wiki/BSD_licenses

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#################
## VOTING DATA ##
#################

## Read 1st round votes from HS Next
votes1.url <- "http://www2.hs.fi/extrat/hsnext/presidentti1-tulos.csv"
votes1 <- read.csv(votes1.url, sep=";")

# Fix column names ("osuus" and "aania" are mixed with each other)
names(votes1) <- gsub("osuus", "temp", names(votes1))
names(votes1) <- gsub("ääniä", "osuus", names(votes1))
names(votes1) <- gsub("temp", "ääniä", names(votes1))
votes1$Ääniä.yhteensä <- as.numeric(as.vector(gsub("None", "0", votes1$Ääniä.yhteensä)))

# Read 2nd round votes from HS Next
votes2.url <- "http://www2.hs.fi/extrat/hsnext/presidentti2.csv"
votes2 <- read.csv(votes2.url, sep=";", fileEncoding="ISO-8859-15")

# Here the names are ok, but ',' has been used as the decimal separator
bad.cols <- c(3,4,7,9,11,13,15)
votes2[,bad.cols] <- apply(votes2[,bad.cols], 2, function(x) as.numeric(gsub(",", ".", x)))

# Rows in votes1 and votes2 match perfectly with one exception:
# votes1 is missing row 1995: 499021 Köklot
# As we are now not interested in it, we simply remove it from
# votes2 to make merging these two easier
votes2 <- droplevels(votes2[-1995,])

# Refine variable names
names(votes1) <- gsub("\\.", " ", names(votes1))
names(votes2) <- gsub("\\.", " ", names(votes2))
names(votes1)[3:39] <- paste("1.K", names(votes1)[3:39], sep=" ")
names(votes2)[3:15] <- paste("2.K", names(votes2)[3:15], sep=" ")
#####################
## Helsinki Region ##
#####################

# Combine data for Helsinki region (Helsinki, Espoo, Vantaa, include Kauniainen to Espoo)
helsinki.inds <- 4:160
espoo.inds <- c(169:236, 355)
vantaa.inds <- 245:309
pks.rows <- c(helsinki.inds, espoo.inds, vantaa.inds)
pks1 <- droplevels(votes1[pks.rows,])
pks2 <- droplevels(votes2[pks.rows,])
# Check that the areas are the same
all(pks1$Alue==pks2$Alue)

# Merge based on Alue
pks.votes <- merge(pks1[2:length(pks1)], pks2[2:length(pks2)], by="Alue")

# Keep only the total percentage to keep the number of variables sensible
pks.votes <- pks.votes[-c(grep("ennakko", names(pks.votes)))]
pks.votes <- pks.votes[-c(grep("ääniä", names(pks.votes)))]

# Add auxiliary variable Aika as the second column
# NOTE! Time variable needs to be the second columnd for googleVis
pks.votes <- cbind(pks.votes[1], Aika=2012, pks.votes[2:length(pks.votes)])

# Add city for colouring (note that merge has alphabetized the Alue names, updated 8.2.2012)
pks.votes$Kaupunki <- "Helsinki"
pks.votes$Kaupunki[pks.votes$Alue %in% pks1$Alue[match(espoo.inds, pks.rows)]] <- "Espoo"
pks.votes$Kaupunki[pks.votes$Alue %in% pks1$Alue[match(vantaa.inds, pks.rows)]] <- "Vantaa"

# Plot a Motion Chart using googleVis -package
library(googleVis)
mchart.pks <- gvisMotionChart(pks.votes, idvar="Alue", timevar="Aika", options=list(height=600, width=700))
# Plot immediately (opens in browser)
plot(mchart.pks)
# Save as html (needs javascript to open!)
print(mchart.pks, file="vaalit/Presidentti2012_MotionChart_PKS_20120207.html")
####################
## Municipalities ##
####################

# Read info of municipalities and election areas from Tilastoteskus
library(XML)
url <- "http://www.stat.fi/meta/luokitukset/vaalipiiri/001-2012/luokitusavain_kunta.html"
temp <- readHTMLTable(url)

# Extract info that we want
municipalities <- temp[[1]][-1,]
municipalities$Vaalipiiri <- paste(as.vector(municipalities[,1]), as.vector(municipalities[,2]))
municipalities <- municipalities[3:5]
names(municipalities) <- c("Aluenumero", "Alue", "Vaalipiiri")

# Fill missing Vaalipiiri info
current.piiri <- NA
for (i in 1:nrow(municipalities)) {
 # If vaalipiiri given, save it as current
 if (municipalities[i,"Vaalipiiri"]!=" ")
 current.piiri <- as.vector(municipalities[i,"Vaalipiiri"])
 # Else add current vaalipiiri
 else
 municipalities[i,"Vaalipiiri"] <- current.piiri
}

# Have to rename two places to match the HS Next data
levels(municipalities$Alue)[levels(municipalities$Alue)=="Parainen"] <- "Länsi-Turunmaa"
levels(municipalities$Alue)[levels(municipalities$Alue)=="Maarianhamina - Mariehamn"] <- "Maarianhamina"

# municipalities and votes1 match perfectly based on Alunumero,
# but votes2 doesn't, so we can't use the merge() -function
# Instead, we first get the rows of the municipalities based on votes1 and Aluenumero
mun.rows <- match(municipalities$Aluenumero, votes1$Aluenumero)
# Then check that the rows match for votes1 and votes2
all(as.vector(votes1$Alue[mun.rows])== as.vector(votes2$Alue[mun.rows]))

# Now we can manually merge the three datasets
mun.votes <- droplevels(cbind(municipalities[2:3], votes1[mun.rows,3:length(votes1)], votes2[mun.rows,3:length(votes2)]))

# Keep only the total percentage to keep the number of variables sensible
mun.votes <- mun.votes[-c(grep("ennakko", names(mun.votes)))]
mun.votes <- mun.votes[-c(grep("ääniä", names(mun.votes)))]

# Add auxiliary variable Aika as the second column
# NOTE! Time variable needs to be the second columnd for googleVis
mun.votes <- cbind(mun.votes[1], Aika=2012, mun.votes[2:length(mun.votes)])

# Plot a Motion Chart using googleVis -package
mchart.mun <- gvisMotionChart(mun.votes, idvar="Alue", timevar="Aika", options=list(height=600, width=700))
# Plot immediately (opens in browser)
plot(mchart.mun)
# Save as html (needs javascript to open!)
print(mchart.mun, file="vaalit/Presidentti2012_MotionChart_Municipalities_20120207.html")

Kategoria(t): Datavaalit 2012 | Avainsanat: , | 8 kommenttia

Pekka vs. Sauli pääkaupunkiseudulla

Vaalipäivän kunniaksi julkaisemme visualisoinnin ensimmäisen kierroksen äänestysjakaumasta kahden suosituimman ehdokkaan välillä pääkaupunkiseudulla äänestysalueittain. Varsinainen äänestysdata julkaistiin HS Next -blogissa ja äänestysalueet löytyvät Helsingin kaupungin Kiinteistövirastolta KML-muodossa.

Suurin työ tässä oli äänestysaluedatan prosessointi käytettävään muotoon, mukaan lukien koordinaatistomuutos KKJ2:sta WGS84:ään. Tästä kiitos kuuluu Joonan kirjoittamalle GetHKK()-funktiolle, joka löytyy soRvin release-versiosta piakkoin. Tämän jälkeen datan visualisointi onnistui helposti ggplot2-paketin avulla.

Tässä tuloksena visualisaatio Haaviston ja Niinistön kannatuksesta pääkaupunkiseudulla. Molemmilla on muihin ehdokkaisiin nähden erittäin suuri kannatus, mutta lisäksi ehdokkaiden välillä löytyy selkeitä alueellisia eroja. Näitä on mielenkiintoista verrata toisen kierroksen äänestyskäyttäytymiseen mikäli ne saadaan myös julki.

Haaviston ja Niinistön kannatus pääkaupunkiseudulla vaalien 1. kierroksella.

# This script is posted to the Louhos-blog # http://louhos.wordpress.com
# Copyright (C) 2008-2012 Juuso Parkkinen <juuso.parkkinen@gmail.com>. All rights reserved.
# This program is open source software; you can redistribute it and/or modify
# it under the terms of the FreeBSD License (keep this notice):
# http://en.wikipedia.org/wiki/BSD_licenses
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# Install soRvi package # Instructions in http://sorvi.r-forge.r-project.org/asennus.html
# This script was implemented with soRvi version 0.1.56

library(sorvi)

#################
## VOTING DATA ##
#################

## Read voting results from HS Next
votes.url <- "http://www2.hs.fi/extrat/hsnext/presidentti1-tulos.csv"
votes <- read.csv(votes.url, sep=";")

# Fix column names ("osuus" and "aania" are mixed with each other)
names(votes) <- gsub("osuus", "temp", names(votes))
names(votes) <- gsub("ääniä", "osuus", names(votes))
names(votes) <- gsub("temp", "ääniä", names(votes))

## Read voting area data from HKK (Helsingin kaupungin kiinteistovirasto)
library(rgdal)
areas <- GetHKK(which.data="Aanestysaluejako", data.dir="TEMP")

# Create new Aluenumero code from TKTUNNUS for areas data (discard the first 2
# digits)
areas@data$Aluenumero <- sapply(areas@data$TKTUNNUS, function(x) substr(as.character(x), 3, nchar(as.character(x))))

# Check that Aluenumero is found also in the voting data
if(!all(areas@data$Aluenumero %in% votes$Aluenumero))
stop("DAMN!")

# Merge voting data to area data based on Aluenumero
areas@data <- merge(areas@data, votes, by="Aluenumero")

# Set the projection right and reproject to WS84
areas@proj4string <- CRS("+init=epsg:2392")
areas <- spTransform(areas, CRS("+proj=longlat +datum=WGS84"))

# Map the cities from code to name
city.codes  <- list("091"="Helsinki", "049"="Espoo", "235"="Kauniainen",
"092"="Vantaa")
areas[["Kuntanimi"]] <- sapply(as.character(areas[["KUNTA"]]), function(x) city.codes[[x]])
areas@data$Kuntanimi <- factor(areas@data$Kuntanimi)

# Split the spatial data into respective cities
areas.cities <- SplitSpatial(areas, "Kuntanimi")

##############
## MAP PLOT ##
##############

library(ggplot2)
library(gridExtra)

# Get the data frame
areas.df <- fortify(areas, region="Aluenumero")

# Add support for Pekka and Sauli
areas.df$Pekka.Haavisto.osuus <- votes$Pekka.Haavisto.osuus[match(areas.df$id, votes$Aluenumero)]
areas.df$Sauli.Niinistö.osuus <- votes$Sauli.Niinistö.osuus[match(areas.df$id, votes$Aluenumero)]

# Create a blank background for the maps
theme_map <- theme_bw()
theme_map$panel.background <-  theme_blank()
theme_map$panel.grid.major <- theme_blank()
theme_map$panel.grid.minor <- theme_blank()
theme_map$axis.ticks <- theme_blank()
theme_map$axis.text.x <- theme_blank()
theme_map$axis.text.y <- theme_blank()
theme_map$axis.title.x <- theme_blank()
theme_map$axis.title.y <- theme_blank()
theme_set(theme_map)

# Get map of Helsinki for background
Helsinki.center <- c(lon=24.93, lat = 60.20)
HelsinkiMap <- GetStaticmapGoogleMaps(center = Helsinki.center, zoom = 10,
GRAYSCALE=TRUE, maptype="Map", scale=1)
hplot <- ggplot(HelsinkiMap, aes(x=lon, y=lat))
hplot <- hplot + geom_tile(aes(fill=fill)) + scale_fill_identity(legend=FALSE)
hplot <- hplot + xlab(NULL) + ylab(NULL)

# Create first a common colour scale
min.val <- min(areas.df$Pekka.Haavisto.osuus, areas.df$Sauli.Niinistö.osuus)
max.val <- max(areas.df$Pekka.Haavisto.osuus, areas.df$Sauli.Niinistö.osuus)
col.scale <- scale_colour_gradient(low = 'blue', high = 'red',
limits=c(min.val, max.val))
fill.scale <- scale_fill_gradient(low = 'blue', high = 'red',
limits=c(min.val, max.val))

# Make map for Pekka
den_fill_scale <- col.scale
den_fill_scale$train(areas.df$Pekka.Haavisto.osuus, T)
areas.df$Pekka <- den_fill_scale$map(areas.df$Pekka.Haavisto.osuus)
hplot.pekka <- hplot + geom_polygon(data=areas.df, aes(x=long, y=lat, group=id,
fill=Pekka), colour="white",
alpha=0.7, size=0.2)

# Add legend using an auxiliary ggplot object
p <- ggplot(data=areas.df) + geom_polygon(data=areas.df,
aes(x=long, y=lat, group=id,
fill=Pekka.Haavisto.osuus)) +
fill.scale + labs(fill="Osuus äänistä (%)")
leg <- ggplotGrob(p + opts(keep="legend_box"))
legend <- gTree(children=gList(leg), cl="legendGrob")
widthDetails.legendGrob <- function(x) unit(3, "cm")
hplot.pekka <- arrangeGrob(hplot.pekka, legend=legend, main="Pekka Haavisto")

# Make map for Sauli and use the same legend
den_fill_scale <- col.scale
den_fill_scale$train(areas.df$Sauli.Niinistö.osuus, T)
areas.df$Sauli <- den_fill_scale$map(areas.df$Sauli.Niinistö.osuus)
hplot.sauli <- hplot + geom_polygon(data=areas.df, aes(x=long, y=lat, group=id,
fill=Sauli),
colour="white", alpha=0.7, size=0.2)
hplot.sauli <- arrangeGrob(hplot.sauli, legend=legend, main="Sauli Niinistö")

# Save together
both.plot <- arrangeGrob(hplot.pekka, hplot.sauli, nrow=1)
ggsave(both.plot, file="vaalit/Presidentti2012_PKS_Haavisto-Niinisto_20120207.png",
width=20, height=9)

Kategoria(t): Datavaalit 2012, Uncategorized, visualisointi | Avainsanat: , , , | 3 kommenttia