Skip to content
Snippets Groups Projects
Select Git revision
  • ca01c872efdd32c3a3eed05a0776b9e63bdc8e2a
  • master default protected
2 results

ONS-open-geography.Rmd

Blame
  • Forked from SERG / Mapping with R
    16 commits behind the upstream repository.
    title: "Using the ONS Open Geography API"
    subtitle: "example of using the API to get feature layer data - boundaries"
    author: "Tom Rushby (@tom_rushby)"
    date: 'Last run at: `r Sys.time()`'
    output:
      bookdown::pdf_document2:
        toc: yes
        fig_caption: yes
        number_sections: yes
      bookdown::html_document2:
        fig_caption: yes
        code_folding: hide
        number_sections: yes
        toc: yes
        toc_depth: 4
        toc_float: TRUE
      bookdown::word_document2:
        fig_caption: yes
        number_sections: yes
        toc: yes
        toc_depth: 4
        fig_width: 5
    always_allow_html: yes
    
    # you might need to install these first
    library(sf)   
    library(htmltools)
    library(leaflet)
    library(utils)
    library(dplyr)

    Introduction

    This script provides an example of downloading and importing administrative boundaries from the Office for National Statistics Open Geography portal into RStudio and plotting on a map. It is based upon a useful example by Trafford Data Lab.

    Creating a query

    In this example we want to load Local Authority District geography. The Open Geography portal helpfully provides an API explorer to help us structure the query.

    In the code chunk below, we break up the query into parts that we can change depending on the type of geography we want, the areas we want to include, the fields we want the query to return etc.

    # Elements for the query
    geo_endpoint <- "https://ons-inspire.esriuk.com/arcgis/rest/services/"
    # The geo boundary layer will change depending on which 
    geo_boundarylayer <- "Administrative_Boundaries/Local_Authority_Districts_December_2020_UK_BGC/"
    geo_server <- "FeatureServer/0/"
    geo_search <- "LAD20NM IN "
    
    # Construct a vector of local authorities to load
    # the following local authorities are the 'Solent' region
    las_to_load <- c("Southampton","Portsmouth","Winchester",
                     "Eastleigh","Isle of Wight","Fareham",
                     "Gosport","Test Valley","East Hampshire",
                     "Havant","New Forest","Hart","Basingstoke and Deane")
    
    geo_where <- las_to_load # sometimes we don't want all boundaries
    geo_outfields <- "*" # returns all fields
    #geo_outfields <- c("LAD20CD","LAD20NM","LONG","LAT") # use in place of line above to return selected fields only
    geo_outSR <- "4326"
    geo_format <- "json"

    We then paste the elements together to construct the API query URL ...

    # Assemble the full URL for the query from elements above
    geo_query_string <- paste0(geo_endpoint,geo_boundarylayer,geo_server,
                               "query?where=",geo_search,"(",paste(paste0("'",geo_where,"'"), collapse = ","),
                               ")&outFields=",(paste(geo_outfields, collapse = ",")),"&outSR=",geo_outSR,"&f=",geo_format)
    
    
    # Format the URL to remove spaces
    geo_query <- utils::URLencode(geo_query_string)
    message("Loading LA geometry from ONS Open Geography API")
    # API query
    sf_data <- st_read(geo_query)

    Checking coordinate reference system

    Useful lookup spatial reference for CRS https://spatialreference.org/.

    Sometimes transformation is required using the st_transform() function.

    
    st_coord_sys <- st_crs(sf_data) # check coord system
    st_coord_sys # current coord system EPSG: 4326 (is what leaflet wants - good)
    
    # transform the coord system if required
    if(st_coord_sys$epsg != 4326){
      sf_data <- st_transform(sf_data, "+proj=longlat +datum=WGS84")
    }

    Create map

    Now we can create a map, here using the Leaflet package.

    Find a cheatsheet here.

    Optional: first we can create popups by adding a column to sf_data (uses htmltools).

    sf_data$popup_text <-
      paste("Locial authority area code: ","<b>", sf_data$lad20cd, "</b>",
            '<br/>', 'Local authority: ', '<b>', sf_data$lad20nm, '</b>', ' ') %>%
      lapply(htmltools::HTML)

    Finally we can create the map ...

    leaflet(sf_data) %>%
      addTiles() %>%  # Add default OpenStreetMap map tiles
      addPolygons(color = "blue", fillColor = "blue", fillOpacity = 0.2, weight = 1.5, popup = ~(lad20nm), # popups clicked
                  label = ~(popup_text),                                            # define labels
                  labelOptions = labelOptions(                                      # label options
                    style = list("font-weight" = "normal", padding = "2px 2px"),
                    direction = "auto"),
                  highlight = highlightOptions(
                    weight = 5,
                    color = "#666",
                    fillOpacity = 0.7,
                    bringToFront = TRUE))