Introduction:

This analysis examines 911 calls for the year 2017 in Salem, Massachusetts. Being a resident of Salem living in close proximety to Salem State Univeristy, I am interested in determining how calls for noise complains are distributed. I also wanted to look at another non-violent infraction, disturbing the peace, to see if there is clustering between these two disturbances. I pose the question: are 911 calls for these infractions clustered, and is the call density centered around Salem State Univerisity?

Methodology:

Read Salem 911 call data:

salem <- read.csv("Redacted Crime Data AB.csv", stringsAsFactors = FALSE)

Load packages:

library(tidyverse)
library(ggplot2)
library(lubridate)
library(scales)
library(sf)
library(tmap)
library(maptools)
library(spatstat)

Fix variable formats - ID from double to character, longitude and latitude as numeric:

salem$primary_unit <- as.character(salem$primary_unit)  
salem$badge_no_primary <- as.character(salem$badge_no_primary)
salem$rownum <- as.character(salem$rownum)
salem$latitude <- as.numeric(salem$latitude)
salem$longitude <- as.numeric(salem$longitude)

Subset two TYPES used for this analysis - noise complaints and keeping the peace:

salemtype <- salem %>%
  filter(grepl("NOISE|PEACE", call_description.1))

Determine the number of calls for each type examined in this analysis: In the year 2017 there were a total of 455 call for noise complaints, and 38 calls for keeping the peace.

table(salemtype$call_description.1)
## 
##  KEEP THE PEACE NOISE COMPLAINT 
##              38             455

Create a point sf based on coordinates and plot the points:

salem_sf <- st_as_sf(salemtype, coords = c("longitude", "latitude"),
                               crs=4326, agr = "constant")
tm_shape(salem_sf) + tm_dots(col="call_description.1", size = .5)

Create an interactive map:

tmap_mode("view")
## tmap mode set to interactive viewing
tm_basemap(leaflet::providers$OpenStreetMap.BlackAndWhite) + tm_shape(salem_sf) +
  tm_dots(col="call_description.1")

The calls for noise complaints and keeping the peace are clustered around the Point neighborhood (from Lafayette to Congress streets, towards Palmer’s Cove), and extending down Lafayette Street towards SSU. The clustering extends outward from there, down Bridge, North and Boston Streets, but not towards Highland Avenue.

Download, unzip, and call MA town boundaries:

download.file(url = "http://download.massgis.digital.mass.gov/shapefiles/state/townssurvey_shp.zip",
              destfile = "townsurvey_shp.zip")
unzip(zipfile = "townsurvey_shp.zip", exdir = ".")
towns <- st_read(dsn = ".", layer = "TOWNSSURVEY_POLYM")
## Reading layer `TOWNSSURVEY_POLYM' from data source `C:\classes\GPH942\Final' using driver `ESRI Shapefile'
## Simple feature collection with 351 features and 16 fields
## geometry type:  MULTIPOLYGON
## dimension:      XY
## bbox:           xmin: 33863.73 ymin: 777606.4 xmax: 330837 ymax: 959743
## epsg (SRID):    NA
## proj4string:    +proj=lcc +lat_1=41.71666666666667 +lat_2=42.68333333333333 +lat_0=41 +lon_0=-71.5 +x_0=200000 +y_0=750000 +datum=NAD83 +units=m +no_defs

Subset Salem and set CRS:

salem <- towns %>% 
  filter(TOWN=="SALEM")
st_transform(salem, crs=4326)
## Simple feature collection with 1 feature and 16 fields
## geometry type:  MULTIPOLYGON
## dimension:      XY
## bbox:           xmin: -70.94994 ymin: 42.48188 xmax: -70.78249 ymax: 42.55207
## epsg (SRID):    4326
## proj4string:    +proj=longlat +datum=WGS84 +no_defs
##    TOWN TOWN_ID POP1980 POP1990 POP2000 POPCH80_90 POPCH90_00 TYPE
## 1 SALEM     258   38382   38091   40402       -291       2311    C
##   FOURCOLOR FIPS_STCO SUM_ACRES SUM_SQUARE POP2010 POPCH00_10 SHAPE_AREA
## 1         2     25009  5331.594      8.332   41340        938   21609409
##   SHAPE_LEN                       geometry
## 1  53262.85 MULTIPOLYGON (((-70.90296 4...
st_crs(salem)
## Coordinate Reference System:
##   No EPSG code
##   proj4string: "+proj=lcc +lat_1=41.71666666666667 +lat_2=42.68333333333333 +lat_0=41 +lon_0=-71.5 +x_0=200000 +y_0=750000 +datum=NAD83 +units=m +no_defs"

Plot the points with Salem town boundaries to check work:

tmap_mode("plot")
## tmap mode set to plotting
tm_shape(salem)+ tm_borders()+tm_shape(salem_sf)+tm_dots()

Convert points to MA state plane in order to map them:

salem_sf <- st_transform(salem_sf, crs = st_crs(salem)) 
st_crs(salem_sf)
## Coordinate Reference System:
##   No EPSG code
##   proj4string: "+proj=lcc +lat_1=41.71666666666667 +lat_2=42.68333333333333 +lat_0=41 +lon_0=-71.5 +x_0=200000 +y_0=750000 +datum=NAD83 +units=m +no_defs"

Create ppp object for spatsta: Convert salem_sf to sp

salem_sp <- as_Spatial(salem_sf)

Subset salem_sp to get the two call types and change the types to be factors:

salem_sf2 <- salem_sf %>%
  select(call_description.1)
salem_sf2$call_description.1 <- as.factor(salem_sf2$call_description.1)

Convert sf object to sp object:

salem_sp2 <- as_Spatial(salem_sf2)

Convert sp object to ppp object:

salem_ppp2 <- as.ppp(salem_sp2)

Subset each call type for further analysis:

noise_ppp <- subset(salem_ppp2, marks=="NOISE COMPLAINT")
peace_ppp <- subset(salem_ppp2, marks=="KEEP THE PEACE")

Quick plots to check work:

plot(noise_ppp, legend=FALSE)

plot(peace_ppp, legend=FALSE)

Results

Create Kernel Density Estimate maps for each call type:

par(mfrow = c(1,2))
kde_noise <- density(noise_ppp)
plot(kde_noise)
contour(kde_noise, add=TRUE)
kde_peace <- density(peace_ppp)
plot(kde_peace)
contour(kde_peace, add=TRUE)

These patterns again show that the highest number of calls is centered around the Point and SSU, with decreasing values as you move outward from that location. The call density patterns for both 911 call types are very similar.

Compute Ripley’s K Function: This function examines whether calls for noise complaints are more or less clustered/dispersed then they would be if randomly distributed.

par(mfrow=c(1,1))
knoise <-Kest(noise_ppp, correction = "border")
knoise.env <- envelope(noise_ppp, Kest, correction = "border")
## Generating 99 simulations of CSR  ...
## 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
## 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76,
## 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98,  99.
## 
## Done.
plot(knoise, main="Noise Complains K-function")

plot(knoise.env)

The dotted red line represents a random distribution. 911 calls for noise complains are represented by the thin black line. Because the line representing out data is above the dotted red line, it can be said that there is distinct clustering.

Ripley’s K function for keeping the peace calls:

kpeace <-Kest(peace_ppp, correction = "border")
kpeace.env <- envelope(peace_ppp, Kest, correction = "border")
## Generating 99 simulations of CSR  ...
## 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
## 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76,
## 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98,  99.
## 
## Done.
plot(kpeace, main="Keeping the Peace K-function")

plot(kpeace.env)

Like with noise complains, there is pronounced clustering with keeping the peace calls.

Compute a cross-K function to examine if there is a relationship between 911 calls for noise complains and keeping the peace: First step is to re-combine point patterns to same the file and create a subset of the two mark types together:

noisepeace_ppp <- subset(salem_ppp2, marks=="NOISE COMPLAINT" |
                         marks=="KEEP THE PEACE")
ck.noisepeace <- Kcross(noisepeace_ppp, i="NOISE COMPLAINT",
                      j="KEEP THE PEACE", correction = "border")
ckenv.noisepeace <- envelope(noisepeace_ppp, Kcross, i="NOISE COMPLAINT",
                           j="KEEP THE PEACE", correction = "border")
## Generating 99 simulations of CSR  ...
## 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
## 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76,
## 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98,  99.
## 
## Done.
plot(ck.noisepeace)

plot(ckenv.noisepeace)

The nearly 45 degree blackline being much higher then the dotted red line indicates that there is a distinct relationship between the marked point patterns. There is unmistakable clustering between these two call types.

Discussion

The goal of this analysis is to examine 911 calls in the city of Salem. Calls for noise complains and disturbing the peace are examined using a Kernal Density Estimate and the Ripley’s K Function. The question was posed, are these two types of 911 calls clustered, with the density centered around the Salem State University campus? Through this analysis it has been determined that these two types of 911 calls are strongly clustered. The call density however, is clustered more specifically around the Point neighborhood, although the total pattern of clustering suggests the SSU population does contribute to these calls.