# Tallenna ympäristömuuttuja esim .Rprofile -tiedostoon.
Sys.setenv("MML_API_KEY"="4b5ff7a19789-4a95-85bb-ddbb-936f5fb4")
# lue avain objektiksi sessioon
<- Sys.getenv("MML_API_KEY") mml_api_key
Maanmittauslaitoksen geokoodauspalvelua kuvataan verkkosivuilla seuraavasti:
Geokoodauspalvelu mahdollistaa sijainnin löytämisen hakusanoilla, jotka sisältävät paikannimiä, osoitteita, kiinteistötunnuksia (kiinteistötunnus ja palstan tunnuspisteen sijainti) tai karttalehtiä koko maasta. Palvelu tarjoaa myös käänteistä geokoodausta, eli lähimpien kohteiden hakemista annetuilla koordinaateilla.
Tarkempi dokumentaatio ja käyttöesimerkit löytyvät taas sivulta Tekninen kuvaus Geokoodauspalvelu (REST) v2. Tässä blogissa näytetään miten palvelua voi käyttää R-kielellä.
Maanmittauslaitoksen rajapinnat edellyttävät api-avaimen käyttöä. Api-avaimia ei pidä kirjoittaa suoraan skripteihin. Yksi parempi tapa on tallentaa api-avaimet ympäristömuuttujiksi ja lukea arvo ympäristömuuttujasta Sys.getenv()
-funktiolla.
Suora geokoodaus
Tutustu aluksi suoran geokoodauksen logiikkaan https://github.com/pelias/documentation/blob/master/search.md.
Määritellään funktio mml_api_key
.
<- Sys.getenv("MML_API_KEY")
mml_api_key
#' Geocode a place name or an address
#'
#' @param search_string plane name or an address
#' @param apikey MML api key
#' @param string source of data. One of geographic-names, interpolated-road-addresses, addresses,
#' @return sf data
#' @export
<- function(search_string = "",
geocode source = "interpolated-road-addresses",
output_crs = "EPSG:3067",
lang = "fi",
size = NULL,
options = NULL,
api_key = NULL) {
if (!source %in% c("interpolated-road-addresses",
"geographic-names", "addresses",
"mapsheets-tm35","cadastral-units")){
stop("source must be one of 'interpolated-road-addresses','geographic-names', 'addresses','mapsheets-tm35','cadastral-units'")
}if (!output_crs %in% c("EPSG:3067","EPSG:4326")){
stop("output_crs must be one of 'EPSG:3067','EPSG:4326'")
}if (!lang %in% c("fi","sv","en")){
stop("lang must be one of 'fi','se' or 'en'")
}if (is.null(api_key)){
stop("api_key must be provided")
}
= "https://avoin-paikkatieto.maanmittauslaitos.fi/geocoding/v2/pelias/search"
base_url <- paste0("?text=",
queries URLencode(search_string),
"&sources=",source,
"&crs=",output_crs,
"&lang=",lang,
"&api-key=", api_key)
if (!is.null(size)){
<- paste0(queries, "&size=", size)
queries
}if (!is.null(options)){
<- paste0(queries, "&options=", options)
queries
}
# Set the user agent
<- httr::user_agent("https://github.com/rOpenGov/geofi")
ua # Construct the query URL
<- paste0(base_url, queries)
urls
# Print out the URL
# message("Requesting response from: ", url)
<- function(x, query_ua = ua, crs1=output_crs){
query_geocode #dat <- suppressWarnings(sf::st_read(x, crs = as.integer(sub(".+:", "", crs1))))
# Get the response and check the response.
<- httpcache::GET(x, query_ua)
resp
# Strip the namespace as it will be only trouble
# xml2::xml_ns_strip(content)
if (httr::http_error(resp)) {
<- httr::status_code(resp)
status_code # If status code is 400, there might be more information available
# exception_texts <- ""
# if (status_code == 400) {
# # exception_texts <- xml2::xml_text(xml2::xml_find_all(content, "//ExceptionText"))
# # Remove URI since full URL is going to be displayed
# #exception_texts <- exception_texts[!grepl("^(URI)", exception_texts)]
# #exception_texts <- c(exception_texts, paste("URL: ", url))
# } else if (status_code == 403) {
#
# }
stop(
sprintf(
"OGC API %s request failed\n[%s]",
paste(x),
::http_status(status_code)$message#,
httr# paste0(exception_texts, collapse = "\n ")
),call. = FALSE
)
}<- suppressWarnings(sf::st_read(resp, crs = as.integer(sub(".+:", "", crs1)), quiet = TRUE))
resp_sf if (nrow(resp_sf) == 0){
return()
else {
} $query <- x
resp_sfreturn(resp_sf)
}
}<- lapply(urls, query_geocode) %>%
dat do.call("rbind", .)
return(dat)
}
Testataan funktiota ensin hakemalla paikannimistä kaikki paikannimet, joissa esiintyy sana kainu
.
library(sf)
library(mapview)
library(dplyr)
library(leaflet)
<- geocode(search_string = "kainu",
kainut source = "geographic-names",
output_crs = "EPSG:4326", # koska tehdään leaflet-kartta
api_key = Sys.getenv("MML_API_KEY"))
leaflet(kainut) %>%
addTiles() %>%
addMarkers() %>%
addLabelOnlyMarkers(label = ~label,
labelOptions = labelOptions(noHide = T,
direction = 'top',
textOnly = T,
textsize = "20px"))
Sitten yritetään hakea pistekoordinaatti katuosoitteelle. Kokeillaan tehdä se Pelkosennniemen kunnanvirastolle osoitteessa Sodankyläntie 1 A 98500 Pelkosenniemi
.
<- geocode(search_string = "Sodankyläntie 1 A 98500 Pelkosenniemi",
pelko source = "interpolated-road-addresses",
api_key = Sys.getenv("MML_API_KEY"))
leaflet(pelko %>% st_transform(4326)) %>%
addTiles() %>%
addMarkers() %>%
addLabelOnlyMarkers(label = ~label,
labelOptions = labelOptions(noHide = T,
direction = 'top',
textOnly = T,
textsize = "20px"))
Voit myös hakea useamman osoitteen samalla kertaa, kuten yliopistosairaalat tässä tapauksessa
<- c("haartmaninkatu 4 Helsinki", "Kiinamyllynkatu 4 Turku", "Kajaanintie 50 Oulu", "Puijonlaaksontie 2 Kuopio", "Kuntokatu 2 Tampere")
yo_sairaala_osoitteet
<- geocode(search_string = yo_sairaala_osoitteet,
yo_sairaalat source = "interpolated-road-addresses",
api_key = Sys.getenv("MML_API_KEY"))
ggplot() +
geom_sf(data = geofi::get_municipalities() %>% st_union()) +
geom_sf_label(data = yo_sairaalat, aes(label = label))
Käänteinen geokoodaus
Tutustu aluksi käänteisen geokoodauksen logiikkaan https://github.com/pelias/documentation/blob/master/reverse.md.
/geocoding/v2/pelias/reverse
Paikannimen, osoitteen tai muun paikkatietokohteen haku annetun paikan (esim. sijaintipisteellä määriteltynä) läheisyydestä.
#' @param location string location plane name or an address
#' @param api_key string MML api key
#' @param boundary_circle_radius numeric
#' @param size numeric
#' @param layers string
#' @param sources string
#' @param boundary_country string
#' @param api_key string MML api key
#' @return sf of list
#' @export
#' @examples
#'
#' geocode_reverse(point = geofi::municipality_central_localities[1:3,],
#' source = "geographic-names",
#' apikey = Sys.getenv("MML_API_KEY"))
<- function(point,
geocode_reverse boundary_circle_radius = NULL,
size = NULL,
layers = NULL,
sources = NULL,
boundary_country = NULL,
return = "sf", # json
api_key = Sys.getenv("MML_API_KEY")) {
if (!all(sf::st_is_valid(point))) stop("location is not a valid sf-object")
<- function(x){
create_queries <- sf::st_coordinates(x)
coords <- paste0("?point.lat=",coords[[2]],
query "&point.lon=",coords[[1]],
"&api-key=", api_key)
if (!is.null(boundary_circle_radius)){
<- paste0(query, "&boundary.circle.radius=", boundary_circle_radius)
query
}if (!is.null(size)){
<- paste0(query, "&size=", size)
query
}if (!is.null(layers)){
<- paste0(query, "&layers=", layers)
query
}if (!is.null(sources)){
<- paste0(query, "&sources=", sources)
query
}if (!is.null(boundary_country)){
<- paste0(query, "&boundary.country=", boundary_country)
query
}return(query)
}
<- list()
lst for (i in 1:nrow(point)){
<- create_queries(x = point[i,])
lst[[i]]
}<- do.call("c", lst)
queries
<- httr::user_agent("https://github.com/rOpenGov/geofi")
ua # Construct the query URL
= "https://avoin-paikkatieto.maanmittauslaitos.fi/geocoding/v2/pelias/reverse"
base_url <- paste0(base_url, queries)
urls
# Print out the URL
# message("Requesting response from: ", url)
<- function(x, query_ua = ua){
query_geocode # Get the response and check the response.
<- httpcache::GET(x, query_ua)
resp if (return == "sf"){
<- sf::st_read(resp, quiet = TRUE)
ddat else {
} <- httr::content(resp, as = "parsed")
ddat
}
}if (return == "sf"){
<- lapply(urls, query_geocode) %>%
dat do.call("rbind", .)
else {
} <- lapply(urls, query_geocode)
dat
}return(dat)
}
Tee käänteinen geokoodaus Eduskuntatalolle sf
-objektina 300 metrin säteellä pisteestä ja että palautetaan ensimmäiset 10 osumaa.
<- tibble(lon = 24.933333, lat = 60.1725) %>%
eduskuntatalo ::st_as_sf(coords = c("lon","lat"), crs = 4326)
sf
<- geocode_reverse(point = eduskuntatalo,
res size = 10,
boundary_circle_radius = 300,
return = "sf")
leaflet(res) %>%
addTiles() %>%
addMarkers() %>%
addLabelOnlyMarkers(label = ~label,
labelOptions = labelOptions(noHide = T,
direction = 'top',
textOnly = T,
textsize = "20px"))
Hakusanojen tulkinta
/geocoding/v2/searchterm/decode
Hakusanan tunnistus vertailemalle hakusanaa luettelopalvelussa saatavilla oleviin koodilistojen koodien selitteisiin. Jos sopiva selite löytyy, palautetaan vastaava koodiarvo.
Samankaltaiset hakusanat
/geocoding/v2/searchterm/similar
Samankaltaisten termien haku vertaamalla hakusanaa paikannimiin ja palauttamalla parhaiten saatuun syötteeseen sopivat.
Uudelleenkäyttö
Viittaus
@online{kainu2023,
author = {Kainu, Markus},
title = {Maanmittauslaitoksen geocoding-rajapinnan käyttö R-kielellä},
date = {2023-01-27},
url = {https://markuskainu.fi/posts/2023-01-27-mml-geocoding/},
langid = {fi}
}