Kitkaton data, Suomen rakennukset ja R

Categories: R

Digi- ja väestövirasto (DVV) on julkaissut uuden version Suomalaisten rakennusten osoitteet, postinumerot ja WGS84-koordinaatit ja tällä kertaa ns. kitkattomana datana (frictionless data).

Frictionless data -projektissa pyritään luomaan (taas kerran) tekstipohjainen paketointiformaatti, joka on yhteensopiva eri alustojen ja ohjelmistojen kesken. Syyskuussa 2020 työkalut löytyvät jo seuraaviin ohjelmointikieliin:

Ideana siis on että paketti sisältää json-muotoiset metadatat pakettiin kuuluvien datojen sisällöstä, sijainnista, lisensseistä sekä teknisistä spesifikaatioista. Eri kielille hehitetyillä työkaluilla nämä tiedot on helppo lukea kullekin kielelle ominaisella tavalla.


Seuraavaksi katsotaan DVV:n uutta dataa tarkemmin R-kielen avulla.

Aluksi ladataan zipattu paketti levylle, puretaan se kansioon sekä listataan paketista löytyvät data.

library(dplyr) # CRAN
library(sp) # CRAN
library(sf) # CRAN
library(fs) # CRAN
library(archive) # remotes::install_github("jimhester/archive")
library(jsonlite) # CRAN
library(tableschema.r) # CRAN
library(datapackage.r) # CRAN

tmpfile <- tempfile()
tmpdir <- tempdir()
# Ladataan paketti
download.file("https://www.avoindata.fi/data/dataset/941b70c8-3bd4-4b4e-a8fb-0ae29d2647a1/resource/18e2b019-e986-4cf5-abfe-e6771f6e04d8/download/finland-2020-08-14-json.7z",
              destfile = tmpfile)
# Puretaan paketti
archive::archive_extract(tmpfile,
                         dir = tmpdir)
# Poistetaan paketti
file_delete(tmpfile)

# Listataan paketin tiedostot
dir_info(tmpdir, recurse = TRUE) %>% 
  select(path,size,modification_time) %>% 
  arrange(size) -> flies
print(flies, n = 30)
## # A tibble: 24 x 3
##    path                                                 size modification_time  
##    <fs::path>                                     <fs::byte> <dttm>             
##  1 /tmp/RtmpJbF11i/csv_dialect.json                      180 2020-08-14 12:51:23
##  2 /tmp/RtmpJbF11i/json_table_schema.json              2.11K 2020-08-14 12:51:22
##  3 /tmp/RtmpJbF11i/datapackage.json                    3.98K 2020-08-14 12:51:23
##  4 /tmp/RtmpJbF11i/data                                   4K 2020-08-14 12:57:29
##  5 /tmp/RtmpJbF11i/data/19_addresses_2020-08-14.…      1.63M 2020-08-14 12:51:37
##  6 /tmp/RtmpJbF11i/data/15_addresses_2020-08-14.…      3.37M 2020-08-14 12:52:51
##  7 /tmp/RtmpJbF11i/data/17_addresses_2020-08-14.…      4.58M 2020-08-14 12:52:09
##  8 /tmp/RtmpJbF11i/data/08_addresses_2020-08-14.…      7.38M 2020-08-14 12:55:10
##  9 /tmp/RtmpJbF11i/data/07_addresses_2020-08-14.…       8.3M 2020-08-14 12:55:27
## 10 /tmp/RtmpJbF11i/data/04_addresses_2020-08-14.…      8.37M 2020-08-14 12:56:34
## 11 /tmp/RtmpJbF11i/data/06_addresses_2020-08-14.…      8.59M 2020-08-14 12:55:43
## 12 /tmp/RtmpJbF11i/data/14_addresses_2020-08-14.…      9.71M 2020-08-14 12:53:08
## 13 /tmp/RtmpJbF11i/data/13_addresses_2020-08-14.…      9.92M 2020-08-14 12:53:26
## 14 /tmp/RtmpJbF11i/data/11_addresses_2020-08-14.…     10.44M 2020-08-14 12:54:08
## 15 /tmp/RtmpJbF11i/data/18_addresses_2020-08-14.…     11.57M 2020-08-14 12:52:00
## 16 /tmp/RtmpJbF11i/data/03_addresses_2020-08-14.…     11.66M 2020-08-14 12:56:54
## 17 /tmp/RtmpJbF11i/data/09_addresses_2020-08-14.…     12.73M 2020-08-14 12:54:55
## 18 /tmp/RtmpJbF11i/data/10_addresses_2020-08-14.…     13.32M 2020-08-14 12:54:32
## 19 /tmp/RtmpJbF11i/data/12_addresses_2020-08-14.…     13.76M 2020-08-14 12:53:51
## 20 /tmp/RtmpJbF11i/data/16_addresses_2020-08-14.…     17.67M 2020-08-14 12:52:43
## 21 /tmp/RtmpJbF11i/data/05_addresses_2020-08-14.…     18.74M 2020-08-14 12:56:18
## 22 /tmp/RtmpJbF11i/data/02_addresses_2020-08-14.…     20.61M 2020-08-14 12:57:29
## 23 /tmp/RtmpJbF11i/data/01_addresses_2020-08-14.…     30.57M 2020-08-14 12:58:16
## 24 /tmp/RtmpJbF11i/data/Finland_addresses_2020-0…    222.92M 2020-08-14 12:58:04

Paketissa siis on 23 tiedostoa ja yksi kansio ./data. Paketissa on kolme .json-tiedostoa ja katsotaan ensin niiden sisältö.

# Printataan .JSON tiedostojen sisältö
flies %>% 
  filter(grepl("json", path)) %>% 
  pull(path) -> jsons
jsons
## /tmp/RtmpJbF11i/csv_dialect.json       /tmp/RtmpJbF11i/json_table_schema.json 
## /tmp/RtmpJbF11i/datapackage.json

csv_dialect.json -tiedostossa kerrotaan datatiedostojen csv:n murre seuraavasti.

plyr::ldply(fromJSON(jsons[1]), data.frame) %>% as_tibble()
## # A tibble: 7 x 2
##   .id              X..i..
##   <chr>            <chr> 
## 1 csvddfVersion    "1.2" 
## 2 delimiter        ","   
## 3 doubleQuote      "TRUE"
## 4 lineTerminator   "\r\n"
## 5 quoteChar        "\""  
## 6 skipInitialSpace "TRUE"
## 7 header           "TRUE"

json_table_schema.json -tiedostossa taas kerrotaan datatiedostojen sarakkeiden nimet, datatyypit ja kuvaukset.

plyr::ldply(fromJSON(jsons[2]), data.frame) %>% as_tibble()
## # A tibble: 9 x 4
##   .id    name        type   description                                         
##   <chr>  <chr>       <chr>  <chr>                                               
## 1 fields building_id string Identifier for Finnish buildings                    
## 2 fields region      string Identification number for Finnish regions. See: htt…
## 3 fields municipali… string Identification number for Finnish municipalities. S…
## 4 fields street      string Street name: an identifying name given to a street  
## 5 fields house_numb… string Unique number to each building in a street or area,…
## 6 fields postal_code string Series of digits included in a postal address for t…
## 7 fields latitude_w… number Coordinate latitude in the WGS 84 standard. The Wor…
## 8 fields longitude_… number Coordinate longitude in the WGS 84 standard. The Wo…
## 9 fields building_u… integ… Intended use of building. The identification codes …

datapackage.json -tiedostossa puolestaan on yleistä metatietoa datasta ja julkaisijasta kuten datan lisenssi.

jsonlite::prettify(readLines(jsons[3]))
## {
##     "name": "finnish-addresses-postalcodes-and-coordinates",
##     "title": "Data of finnish addresses with postal codes and coordinates",
##     "description": "The data is provided for separately for each region (e.g.: xx_addresses_yyyy-mm-dd.csv) and alternatively as a single csv file (e.g.: Finland_addresses_yyyy-mm-dd.csv). See this link for region codes: https://dvv.fi/tilastot-ja-luettelot, file Maakunnat.xlsx",
##     "licenses": [
##         {
##             "url": "https://creativecommons.org/licenses/by/4.0/",
##             "name": "Creative Commons Attribution 4.0 International",
##             "version": "4.0"
##         },
##         {
##             "url": "http://www.jhs-suositukset.fi/suomi/jhs189",
##             "name": "Finnish public sector open data license"
##         }
##     ],
##     "sources": [
##         {
##             "name": "DVV Population Information System",
##             "web": "http://dvv.fi/en/population-information-system"
##         }
##     ],
##     "maintainers": [
##         {
##             "name": "Mika Honkanen",
##             "email": "mika.honkanen@dvv.fi",
##             "web": "https://www.avoindata.fi/en"
##         }
##     ],
##     "publishers": [
##         {
##             "name": "Mika Honkanen",
##             "email": "mika.honkanen@dvv.fi",
##             "web": "https://www.avoindata.fi/en"
##         }
##     ],
##     "resources": [
##         {
##             "name": "addresses",
##             "path": "./data/*.csv",
##             "format": "csv",
##             "mediatype": "text/csv",
##             "schema": {
##                 "fields": [
##                     {
##                         "name": "building_id",
##                         "type": "string",
##                         "description": "Identifier for Finnish buildings"
##                     },
##                     {
##                         "name": "region",
##                         "type": "string",
##                         "description": "Identification number for Finnish regions. See: https://dvv.fi/tilastot-ja-luettelot, file Maakunnat.xlsx"
##                     },
##                     {
##                         "name": "municipality",
##                         "type": "string",
##                         "description": "Identification number for Finnish municipalities. See: http://tilastokeskus.fi/meta/luokitukset/kunta/001-2019/index.html"
##                     },
##                     {
##                         "name": "street",
##                         "type": "string",
##                         "description": "Street name: an identifying name given to a street"
##                     },
##                     {
##                         "name": "house_number",
##                         "type": "string",
##                         "description": "Unique number to each building in a street or area, with the intention of making it easier to locate a particular building"
##                     },
##                     {
##                         "name": "postal_code",
##                         "type": "string",
##                         "description": "Series of digits included in a postal address for the purpose of sorting mail."
##                     },
##                     {
##                         "name": "latitude_wgs84",
##                         "type": "number",
##                         "description": "Coordinate latitude in the WGS 84 standard. The World Geodetic System (WGS) is a standard for use in cartography, geodesy, and navigation including GPS."
##                     },
##                     {
##                         "name": "longitude_wgs84",
##                         "type": "number",
##                         "description": "Coordinate longitude in the WGS 84 standard. The World Geodetic System (WGS) is a standard for use in cartography, geodesy, and navigation including GPS."
##                     },
##                     {
##                         "name": "building_use",
##                         "type": "integer",
##                         "description": "Intended use of building. The identification codes with the corresponding letter codes from stat.fi are: 0 The intended use of building is lacking, 1 Residental building or business premises (A - H), and 2 Production building or other building (J - N). See: http://www.stat.fi/meta/luokitukset/rakennus/001-2018-07-12/index_en.html"
##                     }
##                 ]
##             }
##         }
##     ]
## }
## 

Katsotaan sitten tarkemmin datapackage.json:n resources-kohtaa

fromJSON(jsons[3]) %>% 
  .$resources -> resources
str(resources)
## 'data.frame':    1 obs. of  5 variables:
##  $ name     : chr "addresses"
##  $ path     : chr "./data/*.csv"
##  $ format   : chr "csv"
##  $ mediatype: chr "text/csv"
##  $ schema   :'data.frame':   1 obs. of  1 variable:
##   ..$ fields:List of 1
##   .. ..$ :'data.frame':  9 obs. of  3 variables:
##   .. .. ..$ name       : chr  "building_id" "region" "municipality" "street" ...
##   .. .. ..$ type       : chr  "string" "string" "string" "string" ...
##   .. .. ..$ description: chr  "Identifier for Finnish buildings" "Identification number for Finnish regions. See: https://dvv.fi/tilastot-ja-luettelot, file Maakunnat.xlsx" "Identification number for Finnish municipalities. See: http://tilastokeskus.fi/meta/luokitukset/kunta/001-2019/index.html" "Street name: an identifying name given to a street" ...

Sieltä käy ilmi mm. datatiedostojen sijainti (./data) sekä schema-kohdan alta vielä toistamiseen datojen kenttien tiedot.

resources$schema$fields[[1]] %>% as_tibble()
## # A tibble: 9 x 3
##   name         type    description                                              
##   <chr>        <chr>   <chr>                                                    
## 1 building_id  string  Identifier for Finnish buildings                         
## 2 region       string  Identification number for Finnish regions. See: https://…
## 3 municipality string  Identification number for Finnish municipalities. See: h…
## 4 street       string  Street name: an identifying name given to a street       
## 5 house_number string  Unique number to each building in a street or area, with…
## 6 postal_code  string  Series of digits included in a postal address for the pu…
## 7 latitude_wg… number  Coordinate latitude in the WGS 84 standard. The World Ge…
## 8 longitude_w… number  Coordinate longitude in the WGS 84 standard. The World G…
## 9 building_use integer Intended use of building. The identification codes with …

Nyt kun on tiedossa datojen sijainnit, voimme ladata datat R:ään. Sivun alussa olevasta tiedostolistauksesta saattoi huomata että datat ovat sekä maakunnittaisina tiedostoina maakuntakoodilla merkittynä sekä koko maan tiedostona. Maakuntatatoista suurin on Uudenmaan data /tmp/RtmpJbF11i/data/Finland_addresses_2020-08-14.csv ja tehdään sen pohjalta pieni kartta.

Koska sarake-erottimena on pilkku, R:ssä meille riittää kun luetaan data normaalilla read.csv-funktiolla. Koska datat ovat melko suuria, käytän readr-paketin funktioita tässä esimerkissä

library(readr)
d <- read_csv(flies[nrow(flies),]$path)
d
## # A tibble: 3,677,547 x 9
##    building_id region municipality street house_number postal_code
##    <chr>       <chr>  <chr>        <chr>  <chr>        <chr>      
##  1 100085724R  <NA>   <NA>         <NA>   <NA>         25830      
##  2 100170063B  <NA>   <NA>         <NA>   <NA>         34550      
##  3 100170070K  <NA>   <NA>         <NA>   <NA>         34550      
##  4 100170071L  <NA>   <NA>         <NA>   <NA>         39700      
##  5 100170072M  <NA>   <NA>         <NA>   <NA>         39700      
##  6 100170073N  <NA>   <NA>         <NA>   <NA>         34550      
##  7 100170078U  <NA>   <NA>         <NA>   <NA>         34180      
##  8 100170079V  <NA>   <NA>         <NA>   <NA>         34180      
##  9 100170082Y  <NA>   <NA>         <NA>   <NA>         34300      
## 10 1001700852  <NA>   <NA>         <NA>   <NA>         34300      
## # … with 3,677,537 more rows, and 3 more variables: latitude_wgs84 <dbl>,
## #   longitude_wgs84 <dbl>, building_use <dbl>

Datat näyttää oikein fiksulta, rakennuksia on yhteensä 3 677 547. Piiretään datan rakennuksista vielä loppuun kartta niin että siinä ovat kaikki Helsingin Mannerheimintiellä olevat rakennukset.

manskun_rakennukset <- d %>% 
  filter(municipality == "091",
         street == "Mannerheimintie") 
manskun_rakennukset
## # A tibble: 179 x 9
##    building_id region municipality street house_number postal_code
##    <chr>       <chr>  <chr>        <chr>  <chr>        <chr>      
##  1 100809206V  01     091          Manne… 15b          00260      
##  2 100809208X  01     091          Manne… 15a          00260      
##  3 1013132799  01     091          Manne… 113          00300      
##  4 1017008098  01     091          Manne… 166          00300      
##  5 101797595C  01     091          Manne… 113          00280      
##  6 102320284A  01     091          Manne… 117          00280      
##  7 102384058J  01     091          Manne… 81a          00270      
##  8 102384059K  01     091          Manne… 81a          00270      
##  9 102384063P  01     091          Manne… 81-83        00270      
## 10 102394189B  01     091          Manne… <NA>         00280      
## # … with 169 more rows, and 3 more variables: latitude_wgs84 <dbl>,
## #   longitude_wgs84 <dbl>, building_use <dbl>

Datan sarakkeiden kuvauksessa kerrotaan building_use-sarakkeesta seuraavaa: Intended use of building. The identification codes with the corresponding letter codes from stat.fi are: 0 The intended use of building is lacking, 1 Residental building or business premises (A - H), and 2 Production building or other building (J - N). See: http://www.stat.fi/meta/luokitukset/rakennus/001-2018-07-12/index_en.html. Eli luetaan se mukaan osoitteesta: http://www.stat.fi/meta/luokitukset/rakennus/001-2018-07-12/tekstitiedosto.txt

Mannerheimintiellä rakennuksia on 179 ja kartalla ne sijoittuvat näin käyttötarkoituksen mukaan:

rak_sf <- st_as_sf(manskun_rakennukset,
                            coords = c("longitude_wgs84", 
                                       "latitude_wgs84"),
                            crs = "+proj=longlat +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +no_defs")

kayttotark <- read_delim(file = "http://www.stat.fi/meta/luokitukset/rakennus/001-2018-07-12/tekstitiedosto.txt", delim = "\t", skip = 3) %>% 
  mutate(koodi = as.integer(koodi))
rak_sf2 <- left_join(rak_sf,kayttotark, 
                     by = c("building_use" = "koodi"))

library(leaflet)
labels <- sprintf(
  "%s<br/>Käyttötarkoitus: %s",
  paste(rak_sf2$street, rak_sf2$house_number), rak_sf2$nimike
) %>% lapply(htmltools::HTML)
paletti <- colorFactor(
  palette = "Set1",
  domain = rak_sf2$nimike)
leaflet(rak_sf2) %>%
  addTiles(options = tileOptions(opacity = .7)) %>% 
  addCircleMarkers(color = ~paletti(rak_sf2$nimike),label = labels) %>% 
  addLegend("bottomleft", pal = paletti, 
            values = ~nimike,
    opacity = 1
  )

See also