Lab 8. Points to Predictions
Overview
Research Question
Environment Setup
#setwd("~/Desktop/Lab8-CodeData")
library(sf)
library(tmap)
library(leaflet)
library(raster) # Needed for grid and kernel density surface
library(adehabitatHR) # Needed for kernel density surface
Load and Join Data
Load non-spatial Data (csv)
Census.Data <-read.csv("practicaldata.csv")
head(Census.Data)
## OA White_British Low_Occupancy Unemployed Qualification
## 1 E00004120 42.35669 6.2937063 1.893939 73.62637
## 2 E00004121 47.20000 5.9322034 2.688172 69.90291
## 3 E00004122 40.67797 2.9126214 1.212121 67.58242
## 4 E00004123 49.66216 0.9259259 2.803738 60.77586
## 5 E00004124 51.13636 2.0000000 3.816794 65.98639
## 6 E00004125 41.41791 3.9325843 3.846154 74.20635
Load spatial Data (shapefile)
Output.Areas <- st_read("Camden_oa11.shp")
## Reading layer `Camden_oa11' from data source `/Users/HIPark/Documents/micrometcalf/Intro2GIS/book/Camden_oa11.shp' using driver `ESRI Shapefile'
## Simple feature collection with 749 features and 1 field
## geometry type: POLYGON
## dimension: XY
## bbox: xmin: 523954.5 ymin: 180959.8 xmax: 531554.9 ymax: 187603.6
## CRS: 27700
head(Output.Areas)
## Simple feature collection with 6 features and 1 field
## geometry type: POLYGON
## dimension: XY
## bbox: xmin: 524326 ymin: 181181.1 xmax: 530660.2 ymax: 185111.2
## CRS: 27700
## OA11CD geometry
## 1 E00004527 POLYGON ((530648.4 181230.2...
## 2 E00004525 POLYGON ((530511.3 181531.2...
## 3 E00004522 POLYGON ((530207 181434, 53...
## 4 E00004287 POLYGON ((524355.4 185053.6...
## 5 E00004206 POLYGON ((528718.5 184565, ...
## 6 E00004200 POLYGON ((529332.4 181816.6...
Join our census data to the shapefile
OA.Census <- merge(Output.Areas, Census.Data, by.x="OA11CD", by.y="OA")
head(OA.Census)
## Simple feature collection with 6 features and 5 fields
## geometry type: POLYGON
## dimension: XY
## bbox: xmin: 526848.4 ymin: 184128 xmax: 527537.6 ymax: 185073.1
## CRS: 27700
## OA11CD White_British Low_Occupancy Unemployed Qualification
## 1 E00004120 42.35669 6.2937063 1.893939 73.62637
## 2 E00004121 47.20000 5.9322034 2.688172 69.90291
## 3 E00004122 40.67797 2.9126214 1.212121 67.58242
## 4 E00004123 49.66216 0.9259259 2.803738 60.77586
## 5 E00004124 51.13636 2.0000000 3.816794 65.98639
## 6 E00004125 41.41791 3.9325843 3.846154 74.20635
## geometry
## 1 POLYGON ((526998.5 184751.6...
## 2 POLYGON ((527159.1 184538.6...
## 3 POLYGON ((527260.6 184350.2...
## 4 POLYGON ((527230.5 184343.3...
## 5 POLYGON ((527439.8 185011.2...
## 6 POLYGON ((527427.2 185022.2...
Load the house prices csv file
houses <- read.csv("CamdenHouseSales15.csv")
head(houses)
## UID Price Date Street District Region
## 1 597034 22500000 6/12/15 0:00 AVENUE ROAD CAMDEN GREATER LONDON
## 2 594622 15200000 11/4/15 0:00 GREENAWAY GARDENS CAMDEN GREATER LONDON
## 3 594696 13500000 3/10/15 0:00 TEMPLEWOOD AVENUE CAMDEN GREATER LONDON
## 4 594592 10500000 9/14/15 0:00 CHURCH ROW CAMDEN GREATER LONDON
## 5 515677 8950000 10/30/15 0:00 THE GROVE CAMDEN GREATER LONDON
## 6 592992 8750000 9/1/15 0:00 ST GEORGES TERRACE CAMDEN GREATER LONDON
## Postcode oseast1m osnrth1m
## 1 NW86HS 527076 183790
## 2 NW37DJ 525813 185524
## 3 NW37XA 525779 186084
## 4 NW36UU 526159 185603
## 5 N66JU 528177 187307
## 6 NW18XH 527818 184013
Inspect and Prepare Data
We only need a few columns for this practical
houses <- houses[,c(1,2,8,9)]
head(houses)
## UID Price oseast1m osnrth1m
## 1 597034 22500000 527076 183790
## 2 594622 15200000 525813 185524
## 3 594696 13500000 525779 186084
## 4 594592 10500000 526159 185603
## 5 515677 8950000 528177 187307
## 6 592992 8750000 527818 184013
create a House.Points SpatialPointsDataFrame using coordinates in columns 3 and 4
House.Points <- st_as_sf(houses, coords = c("oseast1m","osnrth1m"), crs = 27700)
Plot to ensure the points were encoded correctly
plot(House.Points)
Check coordinate reference system, transform if needed.
st_crs(OA.Census)
## Coordinate Reference System:
## User input: 27700
## wkt:
## PROJCS["OSGB 1936 / British National Grid",
## GEOGCS["OSGB 1936",
## DATUM["OSGB_1936",
## SPHEROID["Airy 1830",6377563.396,299.3249646,
## AUTHORITY["EPSG","7001"]],
## TOWGS84[446.448,-125.157,542.06,0.15,0.247,0.842,-20.489],
## AUTHORITY["EPSG","6277"]],
## PRIMEM["Greenwich",0,
## AUTHORITY["EPSG","8901"]],
## UNIT["degree",0.0174532925199433,
## AUTHORITY["EPSG","9122"]],
## AUTHORITY["EPSG","4277"]],
## PROJECTION["Transverse_Mercator"],
## PARAMETER["latitude_of_origin",49],
## PARAMETER["central_meridian",-2],
## PARAMETER["scale_factor",0.9996012717],
## PARAMETER["false_easting",400000],
## PARAMETER["false_northing",-100000],
## UNIT["metre",1,
## AUTHORITY["EPSG","9001"]],
## AXIS["Easting",EAST],
## AXIS["Northing",NORTH],
## AUTHORITY["EPSG","27700"]]
st_crs(House.Points)
## Coordinate Reference System:
## User input: EPSG:27700
## wkt:
## PROJCS["OSGB 1936 / British National Grid",
## GEOGCS["OSGB 1936",
## DATUM["OSGB_1936",
## SPHEROID["Airy 1830",6377563.396,299.3249646,
## AUTHORITY["EPSG","7001"]],
## TOWGS84[446.448,-125.157,542.06,0.15,0.247,0.842,-20.489],
## AUTHORITY["EPSG","6277"]],
## PRIMEM["Greenwich",0,
## AUTHORITY["EPSG","8901"]],
## UNIT["degree",0.0174532925199433,
## AUTHORITY["EPSG","9122"]],
## AUTHORITY["EPSG","4277"]],
## PROJECTION["Transverse_Mercator"],
## PARAMETER["latitude_of_origin",49],
## PARAMETER["central_meridian",-2],
## PARAMETER["scale_factor",0.9996012717],
## PARAMETER["false_easting",400000],
## PARAMETER["false_northing",-100000],
## UNIT["metre",1,
## AUTHORITY["EPSG","9001"]],
## AXIS["Easting",EAST],
## AXIS["Northing",NORTH],
## AUTHORITY["EPSG","27700"]]
Point Data Method: Basic Visualizations
This plots a blank base map, we have set the transparency of the borders to 0.4
tm_shape(OA.Census) + tm_borders(alpha=.4)
Creates a color-coded dot map
tm_shape(OA.Census) + tm_borders(alpha=.4) +
tm_shape(House.Points) + tm_dots(col = "Price", palette = "Reds", style = "quantile")
Rescale the points
tm_shape(OA.Census) + tm_borders(alpha=.4) +
tm_shape(House.Points) + tm_dots(col = "Price", scale = 1.5, palette = "Reds", style = "quantile", title = "Price Paid (£)")
Turn on interactive Leaflet map view
tmap_mode("view")
## tmap mode set to interactive viewing
View interactive Map; in Export, Save as Web Page
tmap_mode("plot")
## tmap mode set to plotting
Point Data Method: Graduate Symbol Visualizations
Creates a graduated symbol map
tm_shape(OA.Census) + tm_fill("Unemployed", alpha=0.8, palette = "Greys", style = "quantile", title = "% Unemployed") +
tm_borders(alpha=.4) +
tm_shape(House.Points) + tm_bubbles(size = "Price", col = "Price", palette = "PuRd", style = "quantile", legend.size.show = FALSE, title.col = "Price Paid (£)", border.col = "black", border.lwd = 0.1, border.alpha = 0.1) +
tm_layout(legend.text.size = 0.8, legend.title.size = 1.1, frame = FALSE)
Point Data Method: Buffer Generation
Create 200m buffers for each house point
house_buffers <- st_buffer(House.Points, 200)
Map in tmap
tm_shape(OA.Census) + tm_borders() +
tm_shape(house_buffers) + tm_borders(col = "blue") +
tm_shape(House.Points) + tm_dots(col = "red")
Point Data Method: Buffer Count per Area
Count buffers within each area; generates a vector of totals
count_buffers <- lengths(st_within(OA.Census, house_buffers))
head(count_buffers)
## [1] 15 2 0 0 18 28
Stick buffer totals back to the census master file
OA.Census <- cbind(OA.Census,count_buffers)
head(OA.Census)
## Simple feature collection with 6 features and 6 fields
## geometry type: POLYGON
## dimension: XY
## bbox: xmin: 526848.4 ymin: 184128 xmax: 527537.6 ymax: 185073.1
## CRS: 27700
## OA11CD White_British Low_Occupancy Unemployed Qualification count_buffers
## 1 E00004120 42.35669 6.2937063 1.893939 73.62637 15
## 2 E00004121 47.20000 5.9322034 2.688172 69.90291 2
## 3 E00004122 40.67797 2.9126214 1.212121 67.58242 0
## 4 E00004123 49.66216 0.9259259 2.803738 60.77586 0
## 5 E00004124 51.13636 2.0000000 3.816794 65.98639 18
## 6 E00004125 41.41791 3.9325843 3.846154 74.20635 28
## geometry
## 1 POLYGON ((526998.5 184751.6...
## 2 POLYGON ((527159.1 184538.6...
## 3 POLYGON ((527260.6 184350.2...
## 4 POLYGON ((527230.5 184343.3...
## 5 POLYGON ((527439.8 185011.2...
## 6 POLYGON ((527427.2 185022.2...
Map density of buffers per census area
tm_shape(OA.Census) + tm_fill(col = "count_buffers", palette = "BuGn", style = "quantile",title = "Housing Density")
Point Data Method: Buffer Union (or Dissolve)
Merge the Buffers
union.buffers <- st_union(house_buffers)
Map Housing Buffers
tm_shape(OA.Census) + tm_borders() +
tm_shape(union.buffers) + tm_fill(col = "blue", alpha = .4) + tm_borders(col = "blue") +
tm_shape(House.Points) + tm_dots(col = "red")
Point Data Method: Group Attribute by Area
Point in polygon. Gives the points the attributes of the polygons that they are in
pip <- st_join(House.Points, OA.Census, join = st_within)
head(pip)
## Simple feature collection with 6 features and 8 fields
## geometry type: POINT
## dimension: XY
## bbox: xmin: 525779 ymin: 183790 xmax: 528177 ymax: 187307
## CRS: EPSG:27700
## UID Price OA11CD White_British Low_Occupancy Unemployed
## 1 597034 22500000 E00004771 46.77419 0.8547009 1.8264840
## 2 594622 15200000 E00004357 44.28571 7.6271186 1.3274336
## 3 594696 13500000 E00004345 48.54369 1.6528926 0.9090909
## 4 594592 10500000 E00004355 57.08812 5.7377049 1.5789474
## 5 515677 8950000 E00004495 72.26562 3.9682540 2.0833333
## 6 592992 8750000 E00004226 60.15625 1.6806723 1.5625000
## Qualification count_buffers geometry
## 1 50.40650 0 POINT (527076 183790)
## 2 71.25000 0 POINT (525813 185524)
## 3 55.10204 0 POINT (525779 186084)
## 4 55.20362 2 POINT (526159 185603)
## 5 65.19824 0 POINT (528177 187307)
## 6 69.71154 0 POINT (527818 184013)
Aggregate average house prices by the OA11CD (OA names) column
OA <- aggregate(pip$Price, by = list(pip$OA11CD), mean)
head(OA)
## Group.1 x
## 1 E00004120 1260000.0
## 2 E00004121 1215000.0
## 3 E00004123 2275000.0
## 4 E00004124 825859.0
## 5 E00004125 956333.3
## 6 E00004126 861428.6
Change the column names of the aggregated data
names(OA) <- c("OA11CD", "Price")
Join the aggregated data back to the OA.Census polygon
OA.Census <- merge(OA.Census, OA, by = "OA11CD", all.x = TRUE)
Map mean housing price per area
tm_shape(OA.Census) + tm_fill(col = "Price", style = "quantile", title = "Mean House Price (£)")
Point Data Method: Group by Grid
Convert sf objects to sp objects for raster and adehabitate packages
OA.Census.sp <- sf:::as_Spatial(OA.Census)
House.Points.sp <- sf:::as_Spatial(House.Points)
Make a Grid. First define boundaries or extent of grid
grid.extent <- extent(bbox(OA.Census.sp))
Next grade a raster object from the extent
grid.raster <- raster(grid.extent)
Specify our dimensions; split extent into 30 x 30 cells
dim(grid.raster) <- c(50,50)
Project the grid using our shapefile CRS
projection(grid.raster) <- CRS(proj4string(OA.Census.sp))
Convert into a spatial data frame
grid.sp <- as(grid.raster, 'SpatialPolygonsDataFrame')
Convert spatial data frame to matrix data structure
grid.matrix <- grid.sp[OA.Census.sp,]
## Warning in RGEOSBinPredFunc(spgeom1, spgeom2, byid, func): spgeom1 and spgeom2
## have different proj4 strings
Aggregate housing prices by grid matrix
OA.grid <- aggregate(x=House.Points.sp["Price"], by=grid.matrix,FUN=mean)
If there is a null value, assign 0
OA.grid$Price[is.na(OA.grid$Price)] <- 0
Inspect data range
summary(OA.grid@data)
## Price
## Min. : 0
## 1st Qu.: 0
## Median : 443502
## Mean : 636711
## 3rd Qu.: 888452
## Max. :13500000
Map
tm_shape(OA.grid) + tm_fill(col = "Price", style = "quantile", n = 7, title = "Mean House Price (£)")
## Point Data Method: Kernel Density Surface Runs the kernel density estimation; look up the function parameters for more options
kde.output <- kernelUD(House.Points.sp, h="href", grid = 1000)
## Warning in kernelUD(House.Points.sp, h = "href", grid = 1000): xy should contain only one column (the id of the animals)
## id ignored
plot(kde.output)
Converts to raster
kde <- raster(kde.output)
Sets projection to British National Grid
projection(kde) <- CRS("+init=EPSG:27700")
Maps the raster in tmap, “ud” is the density variable
tm_shape(kde) + tm_raster("ud")
Creates a bounding box based on the extents of the Output.Areas polygon
bounding_box <- bbox(OA.Census.sp)
Maps the raster within the bounding box
tm_shape(kde, bbox = bounding_box) + tm_raster("ud")
Mask the raster by the output area polygon
masked_kde <- mask(kde, Output.Areas)
Maps the masked raster, also maps white output area boundaries
tm_shape(masked_kde, bbox = bounding_box) + tm_raster("ud", style = "quantile", n = 100, legend.show = FALSE, palette = "YlGnBu") +
tm_shape(Output.Areas) + tm_borders(alpha=.3, col = "white") +
tm_layout(frame = FALSE)
Compute homeranges for 75%, 50%, 25% of points, objects are returned as spatial polygon data frames
range75 <- getverticeshr(kde.output, percent = 75)
range50 <- getverticeshr(kde.output, percent = 50)
range25 <- getverticeshr(kde.output, percent = 25)
The code below creates a map of several layers using tmap
tm_shape(Output.Areas) + tm_fill(col = "#f0f0f0") + tm_borders(alpha=.8, col = "white") +
tm_shape(House.Points) + tm_dots(col = "blue") +
tm_shape(range75) + tm_borders(alpha=.7, col = "#fb6a4a", lwd = 2) + tm_fill(alpha=.1, col = "#fb6a4a") +
tm_shape(range50) + tm_borders(alpha=.7, col = "#de2d26", lwd = 2) + tm_fill(alpha=.1, col = "#de2d26") +
tm_shape(range25) + tm_borders(alpha=.7, col = "#a50f15", lwd = 2) + tm_fill(alpha=.1, col = "#a50f15") +
tm_layout(frame = FALSE)
Write your kernel density surface to raster format
writeRaster(masked_kde, filename = "kernel_density.grd")
## class : RasterLayer
## dimensions : 858, 1000, 858000 (nrow, ncol, ncell)
## resolution : 22.41141, 22.41141 (x, y)
## extent : 516573.8, 538985.2, 174652.8, 193881.8 (xmin, xmax, ymin, ymax)
## crs : +init=EPSG:27700 +proj=tmerc +lat_0=49 +lon_0=-2 +k=0.9996012717 +x_0=400000 +y_0=-100000 +datum=OSGB36 +units=m +no_defs +ellps=airy +towgs84=446.448,-125.157,542.060,0.1502,0.2470,0.8421,-20.4894
## source : /Users/HIPark/Documents/micrometcalf/Intro2GIS/book/kernel_density.grd
## names : ud
## values : 5.060993e-10, 8.224823e-08 (min, max)