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=