Plan: 1) Show some basic plots of restaurant data 2) Convert restaurants to PPP 3) Count how many Italian restaurants within given radii 4) Plot count against radii 5) Compare to randomly drawing restaurants Note: there are much better ways to do this using specific functions from the SpatStat package (and others). However, I think it’s helpful to start by doing everything “by hand” before relying on packages.
Load necessary libraries:
library(maptools)
library(rgdal)
library(sp)
library(spatstat)
Loading required package: nlme
Loading required package: rpart
spatstat 1.51-0 (nickname: <U+393C><U+3E31>Poetic Licence<U+393C><U+3E32>)
For an introduction to spatstat, type <U+393C><U+3E31>beginner<U+393C><U+3E32>
Bring in point data and plot
rest_data<-read.table("data/menupages_Wb126.csv", header=T, sep=",",stringsAsFactors =FALSE)
rest_spoints<-SpatialPointsDataFrame(cbind(rest_data$x,rest_data$y), rest_data, coords.nrs=c(4,5),match.ID=TRUE)
#Read shapefiles with readOGR
nyc_tracts<-readOGR("data","manhattan_tracts")
OGR data source with driver: ESRI Shapefile
Source: "data", layer: "manhattan_tracts"
with 221 features
It has 46 fields
plot(nyc_tracts,main="Manhattan Restaurants 2008")
points(rest_spoints)
Subset Plots
plot(nyc_tracts,main="Italian Restaurants")
points(rest_spoints[rest_spoints$cuisName1=="Italian",],col="red")
Now look at statistics on point patterns. In order to take advantage of spatstat distance methods we use a projection (NAD1983 Long Island, feet). This allows simple Euclidean distances.
min_x<-min(rest_spoints$x_feet)
max_x<-max(rest_spoints$x_feet)
min_y<-min(rest_spoints$y_feet)
max_y<-max(rest_spoints$y_feet)
W <- owin(xrange=c(min_x,max_x),yrange=c(min_y,max_y)) #a window defined by limits of data
allrests.ppp<-ppp(rest_spoints$x_feet,rest_spoints$y_feet,window=W)
data contain duplicated points
plot(allrests.ppp)
italian.ppp<-allrests.ppp[rest_spoints$cuisName1=="Italian",]
chinese.ppp<-allrests.ppp[rest_spoints$cuisName1=="Chinese",]
pizza.ppp<-allrests.ppp[rest_spoints$cuisName1=="Pizza",]
#plot(allrests.ppp,main="Chinese Restaurants")
print(paste("There are ",length(chinese.ppp$x)," Chinese restaurants and ",length(pizza.ppp$x)," pizza restaurants."))
[1] "There are 338 Chinese restaurants and 316 pizza restaurants."
plot(chinese.ppp)
plot(italian.ppp)
plot(pizza.ppp)
Look at count of Chinese restaurants within given radii
neighDist<-pairdist(chinese.ppp)
radii_set<-seq(200,3600,200)
chinese_mat<-array(,c(length(radii_set),2))
for (i in 1:length(radii_set)) {
chinese_mat[i,1]<-radii_set[i]
chinese_mat[i,2]<-mean(rowSums((neighDist<radii_set[i]), na.rm=TRUE))-1 #remove own distance
}
plot(chinese_mat,xlab="radius",ylab="Count",main="Count Chinese Restaurants within Radius")
neighDist<-pairdist(pizza.ppp)
pizza_mat<-array(,c(length(radii_set),1))
pizza_mat<-cbind(chinese_mat[,1],pizza_mat)
for (i in 1:length(radii_set)) {
pizza_mat[i,2]<-mean(rowSums((neighDist<radii_set[i]), na.rm=TRUE))-1 #remove own distance
}
plot(chinese_mat,xlab="radius",ylab="Count",main="Chinese (red) and Pizza (green)",
ylim=range(c(chinese_mat[,2],pizza_mat[,2])),col="red")
par(new=T)
plot(pizza_mat,xlab="",ylab="",axes=FALSE,col="green")
Now compare Chinese to simulated measure
numSims<-1000
sim_mat<-array(,c(length(chinese_mat[,1]),numSims))
dim(sim_mat)
[1] 18 1000
for (i in 1:numSims) {
sim.ppp<-allrests.ppp[sample(1:length(allrests.ppp$x),length(chinese.ppp$x),replace=F)]
neighDist_sim<-pairdist(sim.ppp)
for (j in 1:length(radii_set)) {
sim_mat[j,i]<-mean(rowSums(neighDist_sim<radii_set[j], na.rm=TRUE))-1
}
}
conf_mat<-array(,c(length(chinese_mat[,1]),2))
for (j in 1:length(radii_set)) {
conf_mat[j,1]<-quantile(sim_mat[j,],probs=.025,na.rm=TRUE)
conf_mat[j,2]<-quantile(sim_mat[j,],probs=.975,na.rm=TRUE)
}
chinese_mat<-cbind(chinese_mat,conf_mat)
plot(chinese_mat[,1],chinese_mat[,2],ylim=range(c(chinese_mat[,2],chinese_mat[,3],chinese_mat[,4])),
xlab="Radius",ylab="Count",pch=20,col="red")
par(new=T)
plot(chinese_mat[,1],chinese_mat[,3],ylim=range(c(chinese_mat[,2],chinese_mat[,3],chinese_mat[,4])),
axes=FALSE,xlab="",ylab="",main="Count Chinese Restaurants within Radius",pch=25,cex=0.5)
par(new=T)
plot(chinese_mat[,1],chinese_mat[,4],ylim=range(c(chinese_mat[,2],chinese_mat[,3],chinese_mat[,4])),
axes=FALSE,xlab="",ylab="",pch=24,cex=0.5)
Do same for pizza restaurants
sim_mat<-array(,c(length(pizza_mat[,1]),numSims))
dim(sim_mat)
[1] 18 1000
for (i in 1:numSims) {
sim.ppp<-allrests.ppp[sample(1:length(allrests.ppp$x),length(pizza.ppp$x),replace=F)]
neighDist_sim<-pairdist(sim.ppp)
for (j in 1:length(radii_set)) {
sim_mat[j,i]<-mean(rowSums(neighDist_sim<radii_set[j], na.rm=TRUE))-1
}
}
conf_mat<-array(,c(length(pizza_mat[,1]),2))
for (j in 1:length(radii_set)) {
conf_mat[j,1]<-quantile(sim_mat[j,],probs=.025,na.rm=TRUE)
conf_mat[j,2]<-quantile(sim_mat[j,],probs=.975,na.rm=TRUE)
}
pizza_mat<-cbind(pizza_mat,conf_mat)
plot(pizza_mat[,1],pizza_mat[,2],ylim=range(c(pizza_mat[,2],pizza_mat[,3],pizza_mat[,4])),
xlab="Radius",ylab="Count",col="red",cex=1,pch=20)
par(new=T)
plot(pizza_mat[,1],pizza_mat[,3],ylim=range(c(pizza_mat[,2],pizza_mat[,3],pizza_mat[,4])),
axes=FALSE,xlab="",ylab="",main="Count Pizza Restaurants within Radius",pch=25,cex=0.5)
par(new=T)
plot(pizza_mat[,1],pizza_mat[,4],ylim=range(c(pizza_mat[,2],pizza_mat[,3],pizza_mat[,4])),
axes=FALSE,xlab="",ylab="",pch=24,cex=0.5)
LS0tDQp0aXRsZTogJ0wxMSBTcGF0aWFsIE1ldGhvZHM6IFBvaW50IFBhdHRlcm5zJw0Kb3V0cHV0Og0KICBodG1sX25vdGVib29rOiBkZWZhdWx0DQogIHBkZl9kb2N1bWVudDogZGVmYXVsdA0KLS0tDQpQbGFuOg0KMSkgU2hvdyBzb21lIGJhc2ljIHBsb3RzIG9mIHJlc3RhdXJhbnQgZGF0YQ0KMikgQ29udmVydCByZXN0YXVyYW50cyB0byBQUFANCjMpIENvdW50IGhvdyBtYW55IEl0YWxpYW4gcmVzdGF1cmFudHMgd2l0aGluIGdpdmVuIHJhZGlpDQo0KSBQbG90IGNvdW50IGFnYWluc3QgcmFkaWkNCjUpIENvbXBhcmUgdG8gcmFuZG9tbHkgZHJhd2luZyByZXN0YXVyYW50cw0KTm90ZTogdGhlcmUgYXJlIG11Y2ggYmV0dGVyIHdheXMgdG8gZG8gdGhpcyB1c2luZyBzcGVjaWZpYyBmdW5jdGlvbnMgZnJvbSB0aGUgU3BhdFN0YXQgcGFja2FnZSAoYW5kIG90aGVycykuIEhvd2V2ZXIsIEkgdGhpbmsgaXQncyBoZWxwZnVsIHRvIHN0YXJ0IGJ5IGRvaW5nIGV2ZXJ5dGhpbmcgImJ5IGhhbmQiIGJlZm9yZSByZWx5aW5nIG9uIHBhY2thZ2VzLg0KDQpMb2FkIG5lY2Vzc2FyeSBsaWJyYXJpZXM6DQpgYGB7cn0NCmxpYnJhcnkobWFwdG9vbHMpDQpsaWJyYXJ5KHJnZGFsKQ0KbGlicmFyeShzcCkNCmxpYnJhcnkoc3BhdHN0YXQpDQpgYGANCkJyaW5nIGluIHBvaW50IGRhdGEgYW5kIHBsb3QNCmBgYHtyfQ0KcmVzdF9kYXRhPC1yZWFkLnRhYmxlKCJkYXRhL21lbnVwYWdlc19XYjEyNi5jc3YiLCBoZWFkZXI9VCwgc2VwPSIsIixzdHJpbmdzQXNGYWN0b3JzID1GQUxTRSkNCnJlc3Rfc3BvaW50czwtU3BhdGlhbFBvaW50c0RhdGFGcmFtZShjYmluZChyZXN0X2RhdGEkeCxyZXN0X2RhdGEkeSksIHJlc3RfZGF0YSwgY29vcmRzLm5ycz1jKDQsNSksbWF0Y2guSUQ9VFJVRSkNCiNSZWFkIHNoYXBlZmlsZXMgd2l0aCByZWFkT0dSICANCm55Y190cmFjdHM8LXJlYWRPR1IoImRhdGEiLCJtYW5oYXR0YW5fdHJhY3RzIikNCnBsb3QobnljX3RyYWN0cyxtYWluPSJNYW5oYXR0YW4gUmVzdGF1cmFudHMgMjAwOCIpDQpwb2ludHMocmVzdF9zcG9pbnRzKQ0KYGBgDQpTdWJzZXQgUGxvdHMNCmBgYHtyfQ0KcGxvdChueWNfdHJhY3RzLG1haW49Ikl0YWxpYW4gUmVzdGF1cmFudHMiKQ0KcG9pbnRzKHJlc3Rfc3BvaW50c1tyZXN0X3Nwb2ludHMkY3Vpc05hbWUxPT0iSXRhbGlhbiIsXSxjb2w9InJlZCIpDQpgYGANCk5vdyBsb29rIGF0IHN0YXRpc3RpY3Mgb24gcG9pbnQgcGF0dGVybnMuIEluIG9yZGVyIHRvIHRha2UgYWR2YW50YWdlIG9mIHNwYXRzdGF0IGRpc3RhbmNlIG1ldGhvZHMgd2UgdXNlIGEgcHJvamVjdGlvbiAoTkFEMTk4MyBMb25nIElzbGFuZCwgZmVldCkuIFRoaXMgYWxsb3dzIHNpbXBsZSBFdWNsaWRlYW4gZGlzdGFuY2VzLg0KYGBge3J9DQptaW5feDwtbWluKHJlc3Rfc3BvaW50cyR4X2ZlZXQpDQptYXhfeDwtbWF4KHJlc3Rfc3BvaW50cyR4X2ZlZXQpDQptaW5feTwtbWluKHJlc3Rfc3BvaW50cyR5X2ZlZXQpDQptYXhfeTwtbWF4KHJlc3Rfc3BvaW50cyR5X2ZlZXQpDQpXIDwtIG93aW4oeHJhbmdlPWMobWluX3gsbWF4X3gpLHlyYW5nZT1jKG1pbl95LG1heF95KSkgI2Egd2luZG93IGRlZmluZWQgYnkgbGltaXRzIG9mIGRhdGENCmFsbHJlc3RzLnBwcDwtcHBwKHJlc3Rfc3BvaW50cyR4X2ZlZXQscmVzdF9zcG9pbnRzJHlfZmVldCx3aW5kb3c9VykNCnBsb3QoYWxscmVzdHMucHBwKQ0KaXRhbGlhbi5wcHA8LWFsbHJlc3RzLnBwcFtyZXN0X3Nwb2ludHMkY3Vpc05hbWUxPT0iSXRhbGlhbiIsXQ0KY2hpbmVzZS5wcHA8LWFsbHJlc3RzLnBwcFtyZXN0X3Nwb2ludHMkY3Vpc05hbWUxPT0iQ2hpbmVzZSIsXQ0KcGl6emEucHBwPC1hbGxyZXN0cy5wcHBbcmVzdF9zcG9pbnRzJGN1aXNOYW1lMT09IlBpenphIixdDQojcGxvdChhbGxyZXN0cy5wcHAsbWFpbj0iQ2hpbmVzZSBSZXN0YXVyYW50cyIpDQpwcmludChwYXN0ZSgiVGhlcmUgYXJlICIsbGVuZ3RoKGNoaW5lc2UucHBwJHgpLCIgQ2hpbmVzZSByZXN0YXVyYW50cyBhbmQgIixsZW5ndGgocGl6emEucHBwJHgpLCIgcGl6emEgcmVzdGF1cmFudHMuIikpDQpwbG90KGNoaW5lc2UucHBwKQ0KcGxvdChpdGFsaWFuLnBwcCkNCnBsb3QocGl6emEucHBwKQ0KYGBgDQpMb29rIGF0IGNvdW50IG9mIENoaW5lc2UgcmVzdGF1cmFudHMgd2l0aGluIGdpdmVuIHJhZGlpDQpgYGB7cn0NCm5laWdoRGlzdDwtcGFpcmRpc3QoY2hpbmVzZS5wcHApDQpyYWRpaV9zZXQ8LXNlcSgyMDAsMzYwMCwyMDApDQpjaGluZXNlX21hdDwtYXJyYXkoLGMobGVuZ3RoKHJhZGlpX3NldCksMikpDQpmb3IgKGkgaW4gMTpsZW5ndGgocmFkaWlfc2V0KSkgew0KICBjaGluZXNlX21hdFtpLDFdPC1yYWRpaV9zZXRbaV0NCiAgY2hpbmVzZV9tYXRbaSwyXTwtbWVhbihyb3dTdW1zKChuZWlnaERpc3Q8cmFkaWlfc2V0W2ldKSwgbmEucm09VFJVRSkpLTEgI3JlbW92ZSBvd24gZGlzdGFuY2UNCn0NCnBsb3QoY2hpbmVzZV9tYXQseGxhYj0icmFkaXVzIix5bGFiPSJDb3VudCIsbWFpbj0iQ291bnQgQ2hpbmVzZSBSZXN0YXVyYW50cyB3aXRoaW4gUmFkaXVzIikNCmBgYA0KYGBge3J9DQpuZWlnaERpc3Q8LXBhaXJkaXN0KHBpenphLnBwcCkNCnBpenphX21hdDwtYXJyYXkoLGMobGVuZ3RoKHJhZGlpX3NldCksMSkpDQpwaXp6YV9tYXQ8LWNiaW5kKGNoaW5lc2VfbWF0WywxXSxwaXp6YV9tYXQpDQpmb3IgKGkgaW4gMTpsZW5ndGgocmFkaWlfc2V0KSkgew0KICBwaXp6YV9tYXRbaSwyXTwtbWVhbihyb3dTdW1zKChuZWlnaERpc3Q8cmFkaWlfc2V0W2ldKSwgbmEucm09VFJVRSkpLTEgI3JlbW92ZSBvd24gZGlzdGFuY2UNCn0NCnBsb3QoY2hpbmVzZV9tYXQseGxhYj0icmFkaXVzIix5bGFiPSJDb3VudCIsbWFpbj0iQ2hpbmVzZSAocmVkKSBhbmQgUGl6emEgKGdyZWVuKSIsDQogICAgIHlsaW09cmFuZ2UoYyhjaGluZXNlX21hdFssMl0scGl6emFfbWF0WywyXSkpLGNvbD0icmVkIikNCnBhcihuZXc9VCkNCnBsb3QocGl6emFfbWF0LHhsYWI9IiIseWxhYj0iIixheGVzPUZBTFNFLGNvbD0iZ3JlZW4iKQ0KYGBgDQoNCk5vdyBjb21wYXJlIENoaW5lc2UgdG8gc2ltdWxhdGVkIG1lYXN1cmUNCmBgYHtyfQ0KbnVtU2ltczwtMTAwMA0Kc2ltX21hdDwtYXJyYXkoLGMobGVuZ3RoKGNoaW5lc2VfbWF0WywxXSksbnVtU2ltcykpDQpkaW0oc2ltX21hdCkNCmZvciAoaSBpbiAxOm51bVNpbXMpIHsNCiAgc2ltLnBwcDwtYWxscmVzdHMucHBwW3NhbXBsZSgxOmxlbmd0aChhbGxyZXN0cy5wcHAkeCksbGVuZ3RoKGNoaW5lc2UucHBwJHgpLHJlcGxhY2U9RildDQogIG5laWdoRGlzdF9zaW08LXBhaXJkaXN0KHNpbS5wcHApDQogIGZvciAoaiBpbiAxOmxlbmd0aChyYWRpaV9zZXQpKSB7DQogICAgc2ltX21hdFtqLGldPC1tZWFuKHJvd1N1bXMobmVpZ2hEaXN0X3NpbTxyYWRpaV9zZXRbal0sIG5hLnJtPVRSVUUpKS0xDQogIH0NCn0NCmNvbmZfbWF0PC1hcnJheSgsYyhsZW5ndGgoY2hpbmVzZV9tYXRbLDFdKSwyKSkNCmZvciAoaiBpbiAxOmxlbmd0aChyYWRpaV9zZXQpKSB7DQogIGNvbmZfbWF0W2osMV08LXF1YW50aWxlKHNpbV9tYXRbaixdLHByb2JzPS4wMjUsbmEucm09VFJVRSkNCiAgY29uZl9tYXRbaiwyXTwtcXVhbnRpbGUoc2ltX21hdFtqLF0scHJvYnM9Ljk3NSxuYS5ybT1UUlVFKQ0KfQ0KY2hpbmVzZV9tYXQ8LWNiaW5kKGNoaW5lc2VfbWF0LGNvbmZfbWF0KQ0KcGxvdChjaGluZXNlX21hdFssMV0sY2hpbmVzZV9tYXRbLDJdLHlsaW09cmFuZ2UoYyhjaGluZXNlX21hdFssMl0sY2hpbmVzZV9tYXRbLDNdLGNoaW5lc2VfbWF0Wyw0XSkpLA0KICAgICB4bGFiPSJSYWRpdXMiLHlsYWI9IkNvdW50IixwY2g9MjAsY29sPSJyZWQiKQ0KcGFyKG5ldz1UKQ0KcGxvdChjaGluZXNlX21hdFssMV0sY2hpbmVzZV9tYXRbLDNdLHlsaW09cmFuZ2UoYyhjaGluZXNlX21hdFssMl0sY2hpbmVzZV9tYXRbLDNdLGNoaW5lc2VfbWF0Wyw0XSkpLA0KICAgICBheGVzPUZBTFNFLHhsYWI9IiIseWxhYj0iIixtYWluPSJDb3VudCBDaGluZXNlIFJlc3RhdXJhbnRzIHdpdGhpbiBSYWRpdXMiLHBjaD0yNSxjZXg9MC41KQ0KcGFyKG5ldz1UKQ0KcGxvdChjaGluZXNlX21hdFssMV0sY2hpbmVzZV9tYXRbLDRdLHlsaW09cmFuZ2UoYyhjaGluZXNlX21hdFssMl0sY2hpbmVzZV9tYXRbLDNdLGNoaW5lc2VfbWF0Wyw0XSkpLA0KICAgICBheGVzPUZBTFNFLHhsYWI9IiIseWxhYj0iIixwY2g9MjQsY2V4PTAuNSkNCmBgYA0KRG8gc2FtZSBmb3IgcGl6emEgcmVzdGF1cmFudHMNCmBgYHtyfQ0Kc2ltX21hdDwtYXJyYXkoLGMobGVuZ3RoKHBpenphX21hdFssMV0pLG51bVNpbXMpKQ0KZGltKHNpbV9tYXQpDQpmb3IgKGkgaW4gMTpudW1TaW1zKSB7DQogIHNpbS5wcHA8LWFsbHJlc3RzLnBwcFtzYW1wbGUoMTpsZW5ndGgoYWxscmVzdHMucHBwJHgpLGxlbmd0aChwaXp6YS5wcHAkeCkscmVwbGFjZT1GKV0NCiAgbmVpZ2hEaXN0X3NpbTwtcGFpcmRpc3Qoc2ltLnBwcCkNCiAgZm9yIChqIGluIDE6bGVuZ3RoKHJhZGlpX3NldCkpIHsNCiAgICBzaW1fbWF0W2osaV08LW1lYW4ocm93U3VtcyhuZWlnaERpc3Rfc2ltPHJhZGlpX3NldFtqXSwgbmEucm09VFJVRSkpLTENCiAgfQ0KfQ0KY29uZl9tYXQ8LWFycmF5KCxjKGxlbmd0aChwaXp6YV9tYXRbLDFdKSwyKSkNCmZvciAoaiBpbiAxOmxlbmd0aChyYWRpaV9zZXQpKSB7DQogIGNvbmZfbWF0W2osMV08LXF1YW50aWxlKHNpbV9tYXRbaixdLHByb2JzPS4wMjUsbmEucm09VFJVRSkNCiAgY29uZl9tYXRbaiwyXTwtcXVhbnRpbGUoc2ltX21hdFtqLF0scHJvYnM9Ljk3NSxuYS5ybT1UUlVFKQ0KfQ0KcGl6emFfbWF0PC1jYmluZChwaXp6YV9tYXQsY29uZl9tYXQpDQpwbG90KHBpenphX21hdFssMV0scGl6emFfbWF0WywyXSx5bGltPXJhbmdlKGMocGl6emFfbWF0WywyXSxwaXp6YV9tYXRbLDNdLHBpenphX21hdFssNF0pKSwNCiAgICAgeGxhYj0iUmFkaXVzIix5bGFiPSJDb3VudCIsY29sPSJyZWQiLGNleD0xLHBjaD0yMCkNCnBhcihuZXc9VCkNCnBsb3QocGl6emFfbWF0WywxXSxwaXp6YV9tYXRbLDNdLHlsaW09cmFuZ2UoYyhwaXp6YV9tYXRbLDJdLHBpenphX21hdFssM10scGl6emFfbWF0Wyw0XSkpLA0KICAgICBheGVzPUZBTFNFLHhsYWI9IiIseWxhYj0iIixtYWluPSJDb3VudCBQaXp6YSBSZXN0YXVyYW50cyB3aXRoaW4gUmFkaXVzIixwY2g9MjUsY2V4PTAuNSkNCnBhcihuZXc9VCkNCnBsb3QocGl6emFfbWF0WywxXSxwaXp6YV9tYXRbLDRdLHlsaW09cmFuZ2UoYyhwaXp6YV9tYXRbLDJdLHBpenphX21hdFssM10scGl6emFfbWF0Wyw0XSkpLA0KICAgICBheGVzPUZBTFNFLHhsYWI9IiIseWxhYj0iIixwY2g9MjQsY2V4PTAuNSkNCmBgYA0KDQo=