Guest User

Untitled

a guest
Mar 28th, 2018
93
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 15.86 KB | None | 0 0
  1. ### Seasonal Variation in Spatial Distribution of Burglary Incidents in Philadelphia, 2014-2016, at the street segment level ###
  2. ### Yinuo Yin ###
  3. ### February 20, 2018 ###
  4.  
  5. # set working directory
  6. setwd("G:/Yinuo Yin/Study/Upenn/2018 Spring/MUSA 620/Week5 Spatial Queries")
  7.  
  8. # load libraries
  9. library(RPostgreSQL)
  10. library(sf)
  11. library(postGIStools)
  12. library(tidyverse)
  13. library(viridis)
  14. library(classInt)
  15. library(lubridate)
  16.  
  17. # connect to database
  18. drv <- dbDriver("PostgreSQL")
  19. con <- dbConnect(drv, dbname = "spatialdb",
  20. host = "127.0.0.1", port = 7437,
  21. user = "postgres", password = '321qaz')
  22.  
  23. # Step 1: Import data + data cleaning
  24. # add Philly shapefile to the database
  25. phillySF <- st_read('census-tracts-philly.shp', stringsAsFactors = FALSE)
  26.  
  27. # we want lowercase fields
  28. phillySF <- rename(phillySF, gisjoin = GISJOIN)
  29.  
  30. # transform to Mercator CRS
  31. phillySF <- st_transform(phillySF, 3785)
  32.  
  33. # import to the database, overwriting the previous one
  34. st_write_db(con, phillySF, "phillysf", drop = TRUE)
  35. dbGetQuery(con, "SELECT UpdateGeometrySRID('phillysf','wkb_geometry',3785)")
  36.  
  37. # add Philly's road network - same procedure: read, rename, tranform, write
  38. phillyStreets <- st_read('Street_Centerline.shp', stringsAsFactors = FALSE)
  39. phillyStreets <- rename(phillyStreets,seg_id=SEG_ID, stname = STNAME)
  40. phillyStreets <- st_transform(phillyStreets, 3785)
  41. st_write_db(con, phillyStreets, "phillystreets", drop = TRUE)
  42.  
  43. # add Philly's crime data
  44. rawcrime <- read.csv("crime.csv")
  45.  
  46. # remove rows of data with unknown longitude and latitude
  47. cleancrime <- subset(rawcrime, !is.na(Lon))
  48. cleancrime <- subset(cleancrime, !is.na(Lat))
  49.  
  50. # transform data
  51. crimeSF <- st_as_sf(cleancrime, coords = c("Lon", "Lat"), crs = 4326)
  52. crimeSF <- st_transform(crimeSF, 3785)
  53.  
  54. # filter raw crime data
  55. # filter time (2014 - 2016)
  56. time <- ymd_hms(crimeSF$Dispatch_Date_Time)
  57. crime1 <-
  58. crimeSF %>%
  59. mutate(Year = year(time), Month = month(time))
  60. crime1 <- filter(crime1, Year == 2014 | Year == 2015 | Year == 2016)
  61.  
  62. # filter burglary crime incidents
  63. crime2 <- filter(crime1, Text_General_Code == "Burglary Non-Residential" | Text_General_Code == "Burglary Residential")
  64.  
  65. # add a column: season
  66. crime.final <- crime2 %>%
  67. mutate(Month = as.numeric(Month))
  68. crime.final$season <- cut(crime.final$Month, breaks = c(0, 2, 5, 8, 11, 12),
  69. labels = c("Winter", "Spring", "Summer", "Fall", "Win"))
  70. crime.final$season[crime.final$season == "Win"] <- "Winter"
  71. crime.final <- arrange(crime.final, Month)
  72.  
  73. # add filtered crime data to the database
  74. st_write_db(con, crime.final, "burglary14to16", drop = TRUE)
  75.  
  76. # add spatial index
  77. dbGetQuery(con, "CREATE INDEX phillystreets_gix ON phillystreets USING GIST (wkb_geometry)")
  78. dbGetQuery(con, "CREATE INDEX phillysf_gix ON phillysf USING GIST (wkb_geometry)")
  79. dbGetQuery(con, "CREATE INDEX burglary14to16_gix ON burglary14to16 USING GIST (wkb_geometry)")
  80.  
  81. # associate burglary incidents with street segments based on this criteria:
  82. # the incident is within 100 m of the street segment
  83. startTime <- Sys.time()
  84. spatialQuery <- paste0("SELECT DISTINCT ON (b.wkb_geometry) b.*, p.seg_id, ",
  85. "ST_Distance(b.wkb_geometry, p.wkb_geometry) AS distance ",
  86. "FROM burglary14to16 AS b, phillystreets AS p ",
  87. "WHERE ST_Distance(b.wkb_geometry, p.wkb_geometry) < 100 ",
  88. "ORDER BY b.wkb_geometry, ST_Distance(b.wkb_geometry, p.wkb_geometry) ASC")
  89. StreetJoinBurglary <- st_read_db(con, query=spatialQuery, geom_column='wkb_geometry')
  90. endTime <- Sys.time()
  91. endTime - startTime # 9.8 min # 20951
  92.  
  93. # just summer
  94. startTime <- Sys.time()
  95. spatialQuery <- paste0("SELECT DISTINCT ON (b.wkb_geometry) b.*, p.seg_id, ",
  96. "ST_Distance(b.wkb_geometry, p.wkb_geometry) AS distance ",
  97. "FROM burglary14to16 AS b, phillystreets AS p ",
  98. "WHERE b.season = 'Summer' ",
  99. "AND ST_Distance(b.wkb_geometry, p.wkb_geometry) < 100 ",
  100. "ORDER BY b.wkb_geometry, ST_Distance(b.wkb_geometry, p.wkb_geometry) ASC")
  101. StreetJoinBurglary_summer <- st_read_db(con, query=spatialQuery, geom_column='wkb_geometry')
  102. endTime <- Sys.time()
  103. endTime - startTime # 2.66 min # 6262
  104.  
  105. # just winter
  106. startTime <- Sys.time()
  107. spatialQuery <- paste0("SELECT DISTINCT ON (b.wkb_geometry) b.*, p.seg_id, ",
  108. "ST_Distance(b.wkb_geometry, p.wkb_geometry) AS distance ",
  109. "FROM burglary14to16 AS b, phillystreets AS p ",
  110. "WHERE b.season = 'Winter' ",
  111. "AND ST_Distance(b.wkb_geometry, p.wkb_geometry) < 100 ",
  112. "ORDER BY b.wkb_geometry, ST_Distance(b.wkb_geometry, p.wkb_geometry) ASC")
  113. StreetJoinBurglary_winter <- st_read_db(con, query=spatialQuery, geom_column='wkb_geometry')
  114. endTime <- Sys.time()
  115. endTime - startTime # 2.07 min # 5153
  116.  
  117. # write these files to database
  118. StreetJoinBurglary <- rename(StreetJoinBurglary_summer ,oldgeom=wkb_geometry)
  119. st_write_db(con, StreetJoinBurglary, "streetjoinburglary",drop=TRUE)
  120. dbGetQuery(con, "CREATE INDEX streetjoinburglary_gix ON streetjoinburglary USING GIST (wkb_geometry)")
  121.  
  122. StreetJoinBurglary_summer <- rename(StreetJoinBurglary_summer ,oldgeom=wkb_geometry)
  123. st_write_db(con, StreetJoinBurglary_summer, "streetjoinburglary_summer",drop=TRUE)
  124. dbGetQuery(con, "CREATE INDEX streetjoinburglary_summer_gix ON streetjoinburglary_summer USING GIST (wkb_geometry)")
  125.  
  126. StreetJoinBurglary_winter <- rename(StreetJoinBurglary_winter ,oldgeom=wkb_geometry)
  127. st_write_db(con, StreetJoinBurglary_winter, "streetjoinburglary_winter",drop=TRUE)
  128. dbGetQuery(con, "CREATE INDEX streetjoinburglary_winter_gix ON streetjoinburglary_winter USING GIST (wkb_geometry)")
  129.  
  130. # count the number of burglary at each street segment
  131. # summer
  132. spatialQuery <- paste0("SELECT p.seg_id, p.wkb_geometry AS geom, COUNT(b.*) AS crime_count ",
  133. "FROM phillystreets AS p ",
  134. "JOIN streetjoinburglary_summer AS b ",
  135. "ON p.seg_id = b.seg_id ",
  136. "GROUP BY (p.seg_id, p.wkb_geometry) ",
  137. "ORDER BY crime_count DESC")
  138. summercount <- st_read_db(con, query=spatialQuery, geom_column='geom')
  139.  
  140. # winter
  141. spatialQuery <- paste0("SELECT p.seg_id, p.wkb_geometry AS geom, COUNT(b.*) AS crime_count ",
  142. "FROM phillystreets AS p ",
  143. "JOIN streetjoinburglary_winter AS b ",
  144. "ON p.seg_id = b.seg_id ",
  145. "GROUP BY (p.seg_id, p.wkb_geometry) ",
  146. "ORDER BY crime_count DESC")
  147. wintercount <- st_read_db(con, query=spatialQuery, geom_column='geom')
  148.  
  149. # get natural breaks of my data
  150. natural <- classIntervals(summercount$crime_count, n=4, style="jenks")
  151. print(natural, unique=TRUE)
  152.  
  153. natural2 <- classIntervals(wintercount$crime_count, n=4, style="jenks")
  154. print(natural2, unique=TRUE)
  155.  
  156. # join back to street layer
  157. summerjoin <- left_join(phillyStreets, as.data.frame(summercount), by = "seg_id")
  158. winterjoin <- left_join(phillyStreets, as.data.frame(wintercount), by = "seg_id")
  159. summerjoin$crime_count[is.na(summerjoin$crime_count)] <- 0
  160. winterjoin$crime_count[is.na(winterjoin$crime_count)] <- 0
  161.  
  162. summerjoin$crime_level <- factor(
  163. cut(summerjoin$crime_count, c(-1, 0, 2, 4, 10)),
  164. labels = c("0", "1 or 2", "3 or 4", "> 5"))
  165.  
  166. winterjoin$crime_level <- factor(
  167. cut(winterjoin$crime_count, c(-1, 0, 2, 4, 10)),
  168. labels = c("0", "1 or 2", "3 or 4", "> 5"))
  169.  
  170. # > 3 crime in summer & winter
  171. summerfew <-filter(summerjoin, crime_level == "1 or 2")
  172. summerok <- filter(summerjoin, crime_level == "3 or 4")
  173. summermore <- filter(summerjoin, crime_level == "> 5")
  174. winterfew <-filter(winterjoin, crime_level == "1 or 2")
  175. winterok <- filter(summerjoin, crime_level == "3 or 4")
  176. wintermore <- filter(winterjoin, crime_level == "> 5")
  177.  
  178. # now ready to plot maps!
  179. # get color palette: viridis
  180. library(colormap)
  181. scales::show_col(colormap(), labels = T)
  182.  
  183. myTheme <- function() {
  184. theme_void() +
  185. theme(
  186. text = element_text(size = 7),
  187. plot.title = element_text(size = 20, color = "white", hjust = 0.5, vjust = 0, face = "bold"),
  188. plot.subtitle = element_text(size = 16, color = "#cccccc", hjust = 0.5, vjust = 0),
  189. axis.ticks = element_blank(),
  190. panel.grid.major = element_line(colour = "black"),
  191. panel.background = element_rect(fill = "black"),
  192. plot.background = element_rect(fill = "black"),
  193. legend.direction = "horizontal",
  194. legend.position = "bottom",
  195. plot.margin = margin(0.5, 0.5, 0.5, 0.5, 'cm'),
  196. legend.key.height = unit(0.4, "cm"), legend.key.width = unit(0.8, "cm"),
  197. legend.title = element_text(size = 14, color = "white", hjust = 0.5, vjust = 0, face = "bold"),
  198. legend.text = element_text(size = 12, color = "#cccccc", hjust = 0.5, vjust = 0)
  199. )
  200. }
  201.  
  202. # summer
  203. ggplot() +
  204. geom_sf(data = summerjoin, aes(color = crime_level)) +
  205. geom_sf(data = summerfew, fill = NA, color = "#218f8d", size = 1) +
  206. geom_sf(data = summerok, fill = NA, color = "#5cc863", size = 2) +
  207. geom_sf(data = summermore, fill = NA, color = "#fde725", size = 4) +
  208. # scale_color_viridis(discrete = TRUE, direction = 1, option="viridis", name = "# of Burglary Incident") +
  209. scale_colour_manual(values = c("#472775", "#218f8d", "#5cc863", "#fde725"),
  210. name="Number of Burglary Incidents") +
  211. labs(title = 'BURGLARY INCIDENTS, SUMMER 2014 - 2016',
  212. subtitle = "By Street Segment, Philadelphia, PA") +
  213. guides(colour = guide_legend(override.aes = list(colour = "black", fill=c("#472775", "#218f8d", "#5cc863", "#fde725")))) +
  214. myTheme()
  215.  
  216. # winter
  217. ggplot() +
  218. geom_sf(data = winterjoin, aes(color = crime_level)) +
  219. geom_sf(data = winterfew, fill = NA, color = "#218f8d", size = 1) +
  220. geom_sf(data = winterok, fill = NA, color = "#5cc863", size = 2) +
  221. geom_sf(data = wintermore, fill = NA, color = "#fde725", size = 4) +
  222. # scale_color_viridis(discrete = TRUE, direction = 1, option="viridis", name = "# of Burglary Incident") +
  223. scale_colour_manual(values = c("#472775", "#218f8d", "#5cc863", "#fde725"),
  224. name="Number of Burglary Incidents") +
  225. labs(title = 'BURGLARY INCIDENTS, WINTER 2014 - 2016',
  226. subtitle = "By Street Segment, Philadelphia, PA") +
  227. guides(colour = guide_legend(override.aes = list(colour = "black", fill=c("#472775", "#218f8d", "#5cc863", "#fde725")))) +
  228. myTheme()
  229.  
  230. # add bar plots for better comparison
  231. # spring and fall
  232. spatialQuery <- paste0("SELECT p.seg_id, p.wkb_geometry AS geom, COUNT(b.*) AS crime_count ",
  233. "FROM phillystreets AS p ",
  234. "JOIN streetjoinburglary AS b ",
  235. "ON p.seg_id = b.seg_id ",
  236. "WHERE season = 'Spring' ",
  237. "GROUP BY (p.seg_id, p.wkb_geometry) ",
  238. "ORDER BY crime_count DESC")
  239. springcount <- st_read_db(con, query=spatialQuery, geom_column='geom')
  240.  
  241. spatialQuery <- paste0("SELECT p.seg_id, p.wkb_geometry AS geom, COUNT(b.*) AS crime_count ",
  242. "FROM phillystreets AS p ",
  243. "JOIN streetjoinburglary AS b ",
  244. "ON p.seg_id = b.seg_id ",
  245. "WHERE season = 'Fall' ",
  246. "GROUP BY (p.seg_id, p.wkb_geometry) ",
  247. "ORDER BY crime_count DESC")
  248. fallcount <- st_read_db(con, query=spatialQuery, geom_column='geom')
  249.  
  250. # join back to street layer
  251. springjoin <- left_join(phillyStreets, as.data.frame(springcount), by = "seg_id")
  252. falljoin <- left_join(phillyStreets, as.data.frame(fallcount), by = "seg_id")
  253. springjoin$crime_count[is.na(springjoin$crime_count)] <- 0
  254. falljoin$crime_count[is.na(falljoin$crime_count)] <- 0
  255.  
  256. springjoin$crime_level <- factor(
  257. cut(springjoin$crime_count, c(-1, 0, 2, 4, 10)),
  258. labels = c("0", "1 or 2", "3 or 4", "> 5"))
  259.  
  260. falljoin$crime_level <- factor(
  261. cut(falljoin$crime_count, c(-1, 0, 2, 4, 10)),
  262. labels = c("0", "1 or 2", "3 or 4", "> 5"))
  263.  
  264. # comparison
  265. # create a dataset
  266. # spring
  267. tot1 <- nrow(springjoin)
  268. few1 <- nrow(filter(springjoin, crime_level == "1 or 2"))
  269. ok1 <- nrow(filter(springjoin, crime_level == "3 or 4"))
  270. many1 <- nrow(filter(springjoin, crime_level == "> 5"))
  271.  
  272. # summer
  273. tot2 <- nrow(summerjoin)
  274. few2 <- nrow(filter(summerjoin, crime_level == "1 or 2"))
  275. ok2 <- nrow(filter(summerjoin, crime_level == "3 or 4"))
  276. many2 <- nrow(filter(summerjoin, crime_level == "> 5"))
  277.  
  278. #fall
  279. tot3 <- nrow(falljoin)
  280. few3 <- nrow(filter(falljoin, crime_level == "1 or 2"))
  281. ok3 <- nrow(filter(falljoin, crime_level == "3 or 4"))
  282. many3 <- nrow(filter(falljoin, crime_level == "> 5"))
  283.  
  284. # winter
  285. tot4 <- nrow(winterjoin)
  286. few4 <- nrow(filter(winterjoin, crime_level == "1 or 2"))
  287. ok4 <- nrow(filter(winterjoin, crime_level == "3 or 4"))
  288. many4 <- nrow(filter(winterjoin, crime_level == "> 5"))
  289.  
  290. # create a data frame
  291. fewc <- data.frame(
  292. Season = factor(c("Spring","Summer", "Fall", "Winter"), levels=c("Spring","Summer", "Fall", "Winter")),
  293. Count = c(few1, few2, few3, few4))
  294.  
  295. okc <- data.frame(
  296. Season = factor(c("Spring","Summer", "Fall", "Winter"), levels=c("Spring","Summer", "Fall", "Winter")),
  297. Count = c(ok1,ok2,ok3,ok4))
  298.  
  299. manyc <- data.frame(
  300. Season = factor(c("Spring","Summer", "Fall", "Winter"), levels=c("Spring","Summer", "Fall", "Winter")),
  301. Count = c(many1,many2,many3,many4))
  302.  
  303. # 1 or 2
  304. a <- ggplot(data=fewc, aes(x=Season, y=Count, fill=Season)) +
  305. geom_bar(stat="identity", position="dodge") +
  306. scale_fill_manual(values=c("#6FDEDC","#1A6F6E","#218F8D","#30CFCC")) +
  307. theme_minimal() +
  308. theme(legend.position="none",
  309. text = element_text(size = 12),
  310. axis.text=element_text(size=12, color = "#BEBEBE", face="bold"),
  311. plot.margin = unit(c(0.1, 0.1, 0.1, 0.1), "in"),
  312. plot.title = element_text(colour="white", size=18, face ="bold"),
  313. axis.title.x=element_blank(),
  314. axis.title.y=element_blank(),
  315. panel.background = element_rect(fill = "black"),
  316. plot.background = element_rect(fill = 'black')) +
  317. ggtitle("# of Street Segments with 1 or 2 Burglary Incidents")
  318.  
  319. # 3 or 4
  320. b<- ggplot(data=okc, aes(x=Season, y=Count, fill=Season)) +
  321. geom_bar(stat="identity", position="dodge") +
  322. scale_fill_manual(values=c("#36A53E","#297A2E","#66CB6D","#A6E1A9")) +
  323. theme_minimal() +
  324. theme(legend.position="none",
  325. text = element_text(size = 12),
  326. axis.text=element_text(size=12, color = "#BEBEBE", face="bold"),
  327. plot.margin = unit(c(0.1, 0.1, 0.1, 0.1), "in"),
  328. plot.title = element_text(colour="white", size=18, face ="bold"),
  329. axis.title.x=element_blank(),
  330. axis.title.y=element_blank(),
  331. panel.background = element_rect(fill = "black"),
  332. plot.background = element_rect(fill = 'black')) +
  333. ggtitle("# of Street Segments with 3 or 4 Burglary Incidents")
  334.  
  335. # >5
  336. c<- ggplot(data=manyc, aes(x=Season, y=Count, fill=Season)) +
  337. geom_bar(stat="identity", position="dodge") +
  338. scale_fill_manual(values=c("#FEEB4F","#F5DC03","#D9C200","#FEF188")) +
  339. theme_minimal() +
  340. theme(legend.position="none",
  341. text = element_text(size = 12),
  342. axis.text=element_text(size=12, color = "#BEBEBE", face="bold"),
  343. plot.margin = unit(c(0.1, 0.1, 0.1, 0.1), "in"),
  344. plot.title = element_text(colour="white", size=18, face ="bold"),
  345. axis.title.x=element_blank(),
  346. axis.title.y=element_blank(),
  347. panel.background = element_rect(fill = "black"),
  348. plot.background = element_rect(fill = 'black')) +
  349. ggtitle("# of Street Segments with Over 5 Burglary Incidents")
  350.  
  351. # combine the three plot
  352. library("cowplot")
  353. plot_grid(a, b, c,
  354. labels = c("A", "B", "C"),
  355. ncol = 3, nrow = 1)
  356.  
  357. # did not use this
  358. Season=c(rep("Spring" , 3) , rep("Summer" , 3) , rep("Fall" , 3) , rep("Winter" , 3) )
  359. Condition=rep(c("1 or 2 Incidents" , "3 or 4 Incidents", "More Than 3 Incidents") , 4)
  360. Value=c(few1, ok1, many1, few2, ok2, many2, few3, ok3, many3, few4, ok4, many4)
  361. data=data.frame(Season,Condition,Value)
  362.  
  363. # disconnect from the database once you're done
  364. dbDisconnect(con)
  365. dbUnloadDriver(drv)
Add Comment
Please, Sign In to add comment