library(sf)
library(sp)
library(rgdal)
library(spatstat)
library(ggmap)
library(maptools)
library(tidyverse)
library(lubridate)
We first read our data and get rid of empty rows.
tenders <- read_csv("tabula-tender-bids-from-mar-2012-to-jan-2017.csv", col_names = c("centre", "stall", "area", "trade", "bid", "month"))
tenders<- tenders %>%
drop_na(centre) %>%
filter(row_number() != 1135) %>%
mutate(type = if_else(row_number() < 1135, "cooked", "lockup")) %>%
mutate(bidNum = as.numeric(str_replace_all(bid, pattern="\\$|,", replacement = ""))) %>%
mutate(date = dmy(paste0("01-", month))) %>%
mutate(priceM2 = bidNum/area)
tenders
tenders %>%
ggplot(aes(area, priceM2)) + geom_point()

With a plot, we can see that there is little relation between area and price per M^2.
tenders %>%
ggplot(aes(date, priceM2)) + geom_boxplot(aes(group = date)) + ylim(c(0, 600))

We can also see that the price per M^2 has not gone up over the years.
To get a spatial plot, we first open a spatial hawker centre dataset.
centres <- st_read("hawker-centres-kml.kml")
g <- read_csv("centres-geocoded.csv")
Once we have extracted our spatial hawker centre data, we join them to our hawker centre data.
centres.unique <- tenders %>%
group_by(centre) %>%
summarise(count = n()) %>%
mutate(location = paste0(centre,", Singapore"))
centres <- bind_cols(centres.unique, g)
tenders.sp <- left_join(tenders, centres, by=c("centre" = "centre"))
To avoid overplotting, we can use density plots to show the locations of hawker centres.
ggplot(tenders.sp, aes(x=lon, y=lat)) + geom_point() + geom_density2d() + coord_fixed()

ggplot(tenders.sp, aes(x=lon, y=lat)) + geom_point() + geom_hex() + coord_fixed()

We make some plots to see if there is a spatial distribution between number of bids and type of bids.
ggplot(tenders.sp, aes(x=lon, y=lat)) + geom_point() + facet_wrap(~ type) + coord_fixed()

There does not seem to be a spatial distribution between types of bids.
tenders.sp[tenders.sp$trade %in% unique(tenders.sp$trade)[!grepl("\\$.*", unique(tenders.sp$trade))],] %>%
ggplot(aes(x=lon, y=lat)) + geom_point() + facet_wrap(~trade) + coord_fixed()

There also does not seem to be an overwhelming spatial distribution between types of food cooked.
To analyse spatial patterns, we first convert our dataset.
centres.sp <- tenders.sp %>%
filter(lat>0) %>%
group_by(centre, lon, lat) %>%
summarise(price=mean(priceM2, na.rm=T)) %>%
replace_na(list(price = 0))
coordinates(centres.sp) <- c('lon', 'lat')
centres.ppp <- unmark(as.ppp(centres.sp))
sg <- readOGR(".", "sg-all")
sg.window <- as.owin(sg)
centres.ppp <- centres.ppp[sg.window]
We can plot graphs and maps to check out the clusters of hawker centres.
plot(Kest(centres.ppp))

plot(density(centres.ppp, 0.02))

contour(density(centres.ppp, 0.02))

We can do further analysis with hawker centres and the population of Singapore.
pop <- as.im(readGDAL("sg-pop.tif"))
After importing data on the population of Singapore, we are able to make pretty charts and maps.
plot(rhohat(centres.ppp, pop))

The decrease towards the end of the chart is due to areas which might have alternatives to eating at a nearby hawker centre, such as driving or eating at restaurants.
plot(pop)
plot(centres.ppp, add=T)

LS0tDQp0aXRsZTogIlNpbmdhcG9yZSdzIEhhd2tlciBDZW50cmVzIg0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCg0KDQpgYGB7cn0NCmxpYnJhcnkoc2YpDQpsaWJyYXJ5KHNwKQ0KbGlicmFyeShyZ2RhbCkNCmxpYnJhcnkoc3BhdHN0YXQpDQpsaWJyYXJ5KGdnbWFwKQ0KbGlicmFyeShtYXB0b29scykNCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShsdWJyaWRhdGUpDQpgYGANCg0KDQpXZSBmaXJzdCByZWFkIG91ciBkYXRhIGFuZCBnZXQgcmlkIG9mIGVtcHR5IHJvd3MuDQpgYGB7cn0NCnRlbmRlcnMgPC0gcmVhZF9jc3YoInRhYnVsYS10ZW5kZXItYmlkcy1mcm9tLW1hci0yMDEyLXRvLWphbi0yMDE3LmNzdiIsIGNvbF9uYW1lcyA9IGMoImNlbnRyZSIsICJzdGFsbCIsICJhcmVhIiwgInRyYWRlIiwgImJpZCIsICJtb250aCIpKQ0KDQp0ZW5kZXJzPC0gdGVuZGVycyAlPiUNCiAgZHJvcF9uYShjZW50cmUpICU+JQ0KICBmaWx0ZXIocm93X251bWJlcigpICE9IDExMzUpICU+JQ0KICBtdXRhdGUodHlwZSA9IGlmX2Vsc2Uocm93X251bWJlcigpIDwgMTEzNSwgImNvb2tlZCIsICJsb2NrdXAiKSkgJT4lDQogIG11dGF0ZShiaWROdW0gPSBhcy5udW1lcmljKHN0cl9yZXBsYWNlX2FsbChiaWQsIHBhdHRlcm49IlxcJHwsIiwgcmVwbGFjZW1lbnQgPSAiIikpKSAlPiUNCiAgbXV0YXRlKGRhdGUgPSBkbXkocGFzdGUwKCIwMS0iLCBtb250aCkpKSAlPiUNCiAgbXV0YXRlKHByaWNlTTIgPSBiaWROdW0vYXJlYSkNCmBgYA0KDQpgYGB7cn0NCnRlbmRlcnMNCmBgYA0KDQoNCmBgYHtyfQ0KdGVuZGVycyAlPiUNCiAgZ2dwbG90KGFlcyhhcmVhLCBwcmljZU0yKSkgKyBnZW9tX3BvaW50KCkNCmBgYA0KV2l0aCBhIHBsb3QsIHdlIGNhbiBzZWUgdGhhdCB0aGVyZSBpcyBsaXR0bGUgcmVsYXRpb24gYmV0d2VlbiBhcmVhIGFuZCBwcmljZSBwZXIgTV4yLg0KDQoNCmBgYHtyfQ0KdGVuZGVycyAlPiUNCiAgZ2dwbG90KGFlcyhkYXRlLCBwcmljZU0yKSkgKyBnZW9tX2JveHBsb3QoYWVzKGdyb3VwID0gZGF0ZSkpICsgeWxpbShjKDAsIDYwMCkpDQpgYGANCldlIGNhbiBhbHNvIHNlZSB0aGF0IHRoZSBwcmljZSBwZXIgTV4yIGhhcyBub3QgZ29uZSB1cCBvdmVyIHRoZSB5ZWFycy4NCg0KDQpUbyBnZXQgYSBzcGF0aWFsIHBsb3QsIHdlIGZpcnN0IG9wZW4gYSBzcGF0aWFsIGhhd2tlciBjZW50cmUgZGF0YXNldC4NCg0KYGBge3J9DQpjZW50cmVzIDwtIHN0X3JlYWQoImhhd2tlci1jZW50cmVzLWttbC5rbWwiKQ0KZyA8LSByZWFkX2NzdigiY2VudHJlcy1nZW9jb2RlZC5jc3YiKQ0KYGBgDQpPbmNlIHdlIGhhdmUgZXh0cmFjdGVkIG91ciBzcGF0aWFsIGhhd2tlciBjZW50cmUgZGF0YSwgd2Ugam9pbiB0aGVtIHRvIG91ciBoYXdrZXIgY2VudHJlIGRhdGEuDQpgYGB7cn0NCmNlbnRyZXMudW5pcXVlIDwtIHRlbmRlcnMgJT4lDQogIGdyb3VwX2J5KGNlbnRyZSkgJT4lDQogIHN1bW1hcmlzZShjb3VudCA9IG4oKSkgJT4lDQogIG11dGF0ZShsb2NhdGlvbiA9IHBhc3RlMChjZW50cmUsIiwgU2luZ2Fwb3JlIikpDQoNCmNlbnRyZXMgPC0gYmluZF9jb2xzKGNlbnRyZXMudW5pcXVlLCBnKQ0KDQp0ZW5kZXJzLnNwIDwtIGxlZnRfam9pbih0ZW5kZXJzLCBjZW50cmVzLCBieT1jKCJjZW50cmUiID0gImNlbnRyZSIpKQ0KYGBgDQpUbyBhdm9pZCBvdmVycGxvdHRpbmcsIHdlIGNhbiB1c2UgZGVuc2l0eSBwbG90cyB0byBzaG93IHRoZSBsb2NhdGlvbnMgb2YgaGF3a2VyIGNlbnRyZXMuDQpgYGB7cn0NCmdncGxvdCh0ZW5kZXJzLnNwLCBhZXMoeD1sb24sIHk9bGF0KSkgKyBnZW9tX3BvaW50KCkgKyBnZW9tX2RlbnNpdHkyZCgpICsgY29vcmRfZml4ZWQoKQ0KDQpnZ3Bsb3QodGVuZGVycy5zcCwgYWVzKHg9bG9uLCB5PWxhdCkpICsgZ2VvbV9wb2ludCgpICsgZ2VvbV9oZXgoKSArIGNvb3JkX2ZpeGVkKCkNCmBgYA0KV2UgbWFrZSBzb21lIHBsb3RzIHRvIHNlZSBpZiB0aGVyZSBpcyBhIHNwYXRpYWwgZGlzdHJpYnV0aW9uIGJldHdlZW4gbnVtYmVyIG9mIGJpZHMgYW5kIHR5cGUgb2YgYmlkcy4NCg0KYGBge3J9DQpnZ3Bsb3QodGVuZGVycy5zcCwgYWVzKHg9bG9uLCB5PWxhdCkpICsgZ2VvbV9wb2ludCgpICsgZmFjZXRfd3JhcCh+IHR5cGUpICsgY29vcmRfZml4ZWQoKQ0KYGBgDQpUaGVyZSBkb2VzIG5vdCBzZWVtIHRvIGJlIGEgc3BhdGlhbCBkaXN0cmlidXRpb24gYmV0d2VlbiB0eXBlcyBvZiBiaWRzLg0KDQpgYGB7cn0NCnRlbmRlcnMuc3BbdGVuZGVycy5zcCR0cmFkZSAlaW4lIHVuaXF1ZSh0ZW5kZXJzLnNwJHRyYWRlKVshZ3JlcGwoIlxcJC4qIiwgdW5pcXVlKHRlbmRlcnMuc3AkdHJhZGUpKV0sXSAlPiUNCmdncGxvdChhZXMoeD1sb24sIHk9bGF0KSkgKyBnZW9tX3BvaW50KCkgKyBmYWNldF93cmFwKH50cmFkZSkgKyBjb29yZF9maXhlZCgpDQoNCmBgYA0KVGhlcmUgYWxzbyBkb2VzIG5vdCBzZWVtIHRvIGJlIGFuIG92ZXJ3aGVsbWluZyBzcGF0aWFsIGRpc3RyaWJ1dGlvbiBiZXR3ZWVuIHR5cGVzIG9mIGZvb2QgY29va2VkLg0KDQpUbyBhbmFseXNlIHNwYXRpYWwgcGF0dGVybnMsIHdlIGZpcnN0IGNvbnZlcnQgb3VyIGRhdGFzZXQuIA0KYGBge3J9DQpjZW50cmVzLnNwIDwtIHRlbmRlcnMuc3AgJT4lDQogIGZpbHRlcihsYXQ+MCkgJT4lDQogIGdyb3VwX2J5KGNlbnRyZSwgbG9uLCBsYXQpICU+JQ0KICBzdW1tYXJpc2UocHJpY2U9bWVhbihwcmljZU0yLCBuYS5ybT1UKSkgJT4lDQogIHJlcGxhY2VfbmEobGlzdChwcmljZSA9IDApKQ0KDQpjb29yZGluYXRlcyhjZW50cmVzLnNwKSA8LSBjKCdsb24nLCAnbGF0JykNCmNlbnRyZXMucHBwIDwtIHVubWFyayhhcy5wcHAoY2VudHJlcy5zcCkpDQoNCnNnIDwtIHJlYWRPR1IoIi4iLCAic2ctYWxsIikNCnNnLndpbmRvdyA8LSBhcy5vd2luKHNnKQ0KY2VudHJlcy5wcHAgPC0gY2VudHJlcy5wcHBbc2cud2luZG93XQ0KYGBgDQoNCldlIGNhbiBwbG90IGdyYXBocyBhbmQgbWFwcyB0byBjaGVjayBvdXQgdGhlIGNsdXN0ZXJzIG9mIGhhd2tlciBjZW50cmVzLg0KYGBge3J9DQpwbG90KEtlc3QoY2VudHJlcy5wcHApKQ0KcGxvdChkZW5zaXR5KGNlbnRyZXMucHBwLCAwLjAyKSkNCmNvbnRvdXIoZGVuc2l0eShjZW50cmVzLnBwcCwgMC4wMikpDQpgYGANCldlIGNhbiBkbyBmdXJ0aGVyIGFuYWx5c2lzIHdpdGggaGF3a2VyIGNlbnRyZXMgYW5kIHRoZSBwb3B1bGF0aW9uIG9mIFNpbmdhcG9yZS4gDQpgYGB7cn0NCnBvcCA8LSBhcy5pbShyZWFkR0RBTCgic2ctcG9wLnRpZiIpKQ0KYGBgDQpBZnRlciBpbXBvcnRpbmcgZGF0YSBvbiB0aGUgcG9wdWxhdGlvbiBvZiBTaW5nYXBvcmUsIHdlIGFyZSBhYmxlIHRvIG1ha2UgcHJldHR5IGNoYXJ0cyBhbmQgbWFwcy4NCmBgYHtyfQ0KcGxvdChyaG9oYXQoY2VudHJlcy5wcHAsIHBvcCkpDQpgYGANClRoZSBkZWNyZWFzZSB0b3dhcmRzIHRoZSBlbmQgb2YgdGhlIGNoYXJ0IGlzIGR1ZSB0byBhcmVhcyB3aGljaCBtaWdodCBoYXZlIGFsdGVybmF0aXZlcyB0byBlYXRpbmcgYXQgYSBuZWFyYnkgaGF3a2VyIGNlbnRyZSwgc3VjaCBhcyBkcml2aW5nIG9yIGVhdGluZyBhdCByZXN0YXVyYW50cy4NCmBgYHtyfQ0KcGxvdChwb3ApDQpwbG90KGNlbnRyZXMucHBwLCBhZGQ9VCkNCmBgYA0K