https://github.com/mpadge/london-housing
Demonstration of osmplotr to plot housing price statistics in London
https://github.com/mpadge/london-housing
Last synced: about 2 months ago
JSON representation
Demonstration of osmplotr to plot housing price statistics in London
- Host: GitHub
- URL: https://github.com/mpadge/london-housing
- Owner: mpadge
- License: gpl-3.0
- Created: 2016-03-16T13:23:45.000Z (about 9 years ago)
- Default Branch: master
- Last Pushed: 2016-05-12T09:30:18.000Z (about 9 years ago)
- Last Synced: 2025-02-14T13:24:32.434Z (3 months ago)
- Language: Shell
- Size: 21.1 MB
- Stars: 0
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.Rmd
- License: LICENSE
Awesome Lists containing this project
README
Visualisation of London housing data using `osmplotr`
========
## 1. Reading Data
Data on housing prices and transactions were taken from
[http://data.london.gov.uk/dataset/average-house-prices-borough](http://data.london.gov.uk/dataset/average-house-prices-borough),
with spatial boundaries of the 'Lower Super Output Areas' (LSOA; the finest
spatial scale) from
[http://data.london.gov.uk/dataset/statistical-gis-boundary-files-london](http://data.london.gov.uk/dataset/statistical-gis-boundary-files-london)Because the links to these data files are likely to change, the script requires
data to be downloaded first. Start by reading the housing price data (the
'DEFINEDNAME' stuff is just junk dumped from `read_excel`)
```{r, warning=FALSE, message=FALSE}
lf <- list.files ("./dat")
fi <- grep ("house-prices", lf)
fname <- paste0 ("./dat/", lf [fi])
housing <- readxl::read_excel (fname, sheet="LSOA11")
# Table has "." for missing values
housing [housing == "."] <- NA
names (housing)
```Convert data columns to numeric:
```{r}
for (i in 3:ncol (housing)) housing [,i] <- as.numeric (housing [,i])
```Then the LSOA boundaries, in the file 'LSOA_2011_London_gen_MHW.shp' contained
in the zip archive 'statistical-gis-boundaries-london.zip'. These data are in
Ordnance Survey National Grid format which must be input in the `proj4string`.
```{r}
fi <- grep ('LSOA\\w+.shp$', lf)
fname <- paste0 ('./dat/', lf [fi])
boundaries <- maptools::readShapePoly (fname,
proj4string=sp::CRS ('+init=epsg:27700'))
sp::bbox (boundaries)
```
Transform the CRS to WGS84:
```{r}
boundaries <- sp::spTransform (boundaries,
CRS=sp::CRS("+proj=longlat +datum=WGS84"))
bbox <- sp::bbox (boundaries)
bbox
```
```{r}
head (slot (boundaries, "data"))
```### 1.1 Downloading OSM data
```{r, eval=FALSE}
devtools::install_github ('mpadge/osmplotr')
``````{r, echo=FALSE, message=FALSE}
wd <- getwd ()
setwd ('/data/Dropbox/mark/analyses')
devtools::load_all ("osmplotr", export_all=FALSE)
setwd (wd)
```Download an area of central London surrounding Hyde Park
```{r, eval=FALSE}
bbox <- osmplotr::get_bbox (c (-0.2, 51.48, -0.1, 51.52))
dat_HP <- osmplotr::extract_osm_objects (key="highway", bbox=bbox, verbose=TRUE)
save (dat_H, file="./dat/dat_H.rda", compress="xz")
pt <- proc.time ()
dat_B <- osmplotr::extract_osm_objects (key="building", bbox=bbox,
verbose=TRUE)
dt <- proc.time () - pt
save (dat_B, file="./dat/dat_B.rda", compress="xz")
``````{r}
load ("./dat/dat_H.rda")
load ("./dat/dat_B.rda")
``````{r}
length (dat_H)
length (dat_B)
```---------------
## 2. Mapping data with `osmplotr`
### 2.1 2015 House Prices
Map the 2014 house prices
```{r}
prices <- housing [, grep ("^Median.+2014$", names (housing))]
```
Then get the corresponding LSOA codes for each point
```{r}
snames <- as.character (housing [,grep("Lower.Super", names(housing))])
indx <- order (snames)
prices <- prices [indx]
snames <- snames [indx]
```The `add_osm_surface` function from `osmplotr` interpolates a continuous surface
between a set of discrete values. The values for each LSOA can be attributed to
its central point, so first extract those:
```{r}
bpts <- t (sapply (slot (boundaries, "polygons"), function (x) slot (x, "labpt")))
bnames <- as.character (slot (boundaries, "data")$LSOA11CD)
indx <- order (bnames)
bpts <- bpts [indx,]
bnames <- bnames [indx]
```
Then check that the LSOA code names in housing match those of the boundary
polygons
```{r}
all (bnames == snames)
```
Then join data together
```{r}
dat <- data.frame (cbind (bpts, prices))
names (dat) <- c ("x", "y", "z")
dat <- dat [!is.na (dat$z),]
head (dat)
```There are a small number of extremely expensive properties, so all values
greater than £1,000,000 points are set to that value
```{r}
zlim <- 1000000
dat$z [dat$z > zlim] <- zlim
```Cut the price data down to values within the bbox only
```{r}
bbox <- slot (dat_B, "bbox")
indx <- which (dat$x > bbox [1,1] & dat$x < bbox [1,2] &
dat$y > bbox [2,1] & dat$y < bbox [2,2])
dat <- dat [indx,]
```Then simply plot the surface with a scale bar in hundreds of thousands of pounds
```{r, eval=FALSE}
map <- plot_osm_basemap (bbox=bbox, bg="gray20")
cols <- rev (heat.colors (50))
map <- add_osm_surface (map, dat_B, dat=dat, col=cols)
map <- add_osm_surface (map, dat_H, dat=dat, col=adjust_colours (cols, -0.2))
map <- add_colourbar (map, cols=cols, zlims=range (dat$z) / 1e5)
```Finally, add a text label to the map and print it
```{r, eval=FALSE}
ypos <- bbox [2,1] + 0.92 * diff (bbox [2,])
dat <- data.frame (x=mean (bbox[1,]), y=ypos,
lab="London house prices")
aes <- ggplot2::aes (x, y, label=lab)
map <- map + ggplot2::geom_text (dat=dat, mapping=aes, size=10, colour="black",
family="Lato Light", fontface=2,
nudge_y=0.0005, nudge_x=0.0005)
map <- map + ggplot2::geom_text (dat=dat, mapping=aes, size=10, colour="white",
family="Lato Light", nudge_y=0.001, fontface=2)
print (map)
```
```{r, echo=FALSE, eval=FALSE}
sht <- diff (bbox [2,]) / diff (bbox [1,])
#ggplot2::ggsave (map, file="figure/map.png", width=30, height=30 * sht,
# unit="cm")
png (width=1000, height=1000 * sht, filename="figure/map.png")
print (map)
graphics.off ()
```