Introduction
Last year, someone broke our car’s window parked inside the parking and took some stuff, I though, it is good idea to look at the rubbing data in Montreal where we have been living.
Montreal is one of the AI hub city, and provides open data open data to accessible for every one. Amazingly Montreal police has also been releasing detailed data, which can be used to explore this multicultural city. The analysis was completed using data from the website and R. The following analyses show the criminal hotspots and concentrations.
Contents
Import data
# Load the data Montreal and prepare
crime_mtl<- read.csv("https://data.montreal.ca/dataset/5829b5b0-ea6f-476f-be94-bc2b8797769a/resource/c6f482bf-bf0f-4960-8b2f-9982c211addd/download/interventionscitoyendo.csv", header = TRUE)
crime_mtl$CATEGORIE[crime_mtl$CATEGORIE=="Infractions entrainant la mort"]<-"resulting_in_death"
crime_mtl$CATEGORIE[crime_mtl$CATEGORIE=="Introduction"]<-"breaking_into_house"
crime_mtl$CATEGORIE[crime_mtl$CATEGORIE=="M\xe9fait"]<-"mischief"
crime_mtl$CATEGORIE[crime_mtl$CATEGORIE=="Vol dans / sur v\xe9hicule \xe0 moteur"]<-"theft_of_vehicle_part"
crime_mtl$CATEGORIE[crime_mtl$CATEGORIE=="Vol de v\xe9hicule \xe0 moteur"]<-"vehicle"
crime_mtl$CATEGORIE[crime_mtl$CATEGORIE=="Vols qualifi\xe9s"]<-"other types of robbery"
knitr::kable(crime_mtl[1:5,])
CATEGORIE | DATE | QUART | PDQ | X | Y | LONGITUDE | LATITUDE |
---|---|---|---|---|---|---|---|
vehicle | 2018-09-13 | jour | 30 | 294904.2 | 5047549 | -73.62678 | 45.56778 |
vehicle | 2018-04-30 | jour | 30 | 294904.2 | 5047549 | -73.62678 | 45.56778 |
vehicle | 2018-09-01 | nuit | 7 | 290274.6 | 5042150 | -73.68593 | 45.51912 |
mischief | 2017-07-21 | jour | 21 | 0.0 | 0 | -76.23729 | 0.00000 |
mischief | 2017-07-29 | jour | 12 | 0.0 | 0 | -76.23729 | 0.00000 |
The data includes:
- breaking_into_house(Fr: Introduction) : breaking and entering a public establishment or a private residence, theft of a firearm from a residence.
- theft_of_vehicle_part(Fr: Vol dans / sur véhicule à moteur) : theft of the contents of a motor vehicle (car, truck, motorcycle, etc.) or of a vehicle part (wheel, bumper, etc.).
- vehicle (Fr:Vol de véhicule à moteur) : car, truck, motorcycle theft, snowmobile tractor with or without trailer, construction or farm vehicle, all-terrain.
- mischie(Fr: Méfait): Graffiti and damage to religious property, vehicle or general damage and all other types of mischief. Vol qualifié : Robbery accompanied by commercial violence, financial institution, person, handbag, armored vehicle, vehicle, firearm, and all other types of robbery.
- resulting_in_death(Fr: Infraction entraînant la mort): First degree murder, second degree murder, manslaughter, infanticide, criminal negligence, and all other types of offenses resulting in death.
Pattern through years
It might also be interesting to see if the percentage changed through year, the following code provides the table of interest.
per_year<-matrix(,nrow=7,ncol=6)
dat_cat<-table(substring((crime_mtl$DATE),1,4), crime_mtl$CATEGORIE)
for (i in 1:6){
per_year[,i]<-t(prop.table(t(dat_cat[,i])))
}
rownames(per_year)<-rownames(dat_cat)
colnames(per_year)<-colnames(dat_cat)
knitr::kable(per_year)
breaking_into_house | mischief | other types of robbery | resulting_in_death | theft_of_vehicle_part | vehicle | |
---|---|---|---|---|---|---|
2015 | 0.1842427 | 0.1812778 | 0.1785289 | 0.1525424 | 0.1802642 | 0.1412043 |
2016 | 0.1842615 | 0.1606465 | 0.1680572 | 0.1299435 | 0.1686045 | 0.1390949 |
2017 | 0.1729767 | 0.1584120 | 0.1575856 | 0.1468927 | 0.1578200 | 0.1512401 |
2018 | 0.1397243 | 0.1395379 | 0.1355355 | 0.1751412 | 0.1431214 | 0.1354193 |
2019 | 0.1314112 | 0.1338757 | 0.1519666 | 0.1355932 | 0.1324195 | 0.1332779 |
2020 | 0.1139198 | 0.1273240 | 0.1191044 | 0.1468927 | 0.1222626 | 0.1504091 |
2021 | 0.0734639 | 0.0989261 | 0.0892219 | 0.1129944 | 0.0955078 | 0.1493544 |
Here we are interested in exploring the pattern of breaking and entering a public establishment or a private residence, so we drop unrelated crime.
crime_mtl_b <- subset(crime_mtl,CATEGORIE == "breaking_into_house")
crime_mtl_b<-crime_mtl_b[crime_mtl_b$LAT>1,]
The scatter plot over year shows there has been a decline which is a very good news.
suppressMessages(library(tidyverse))
suppressMessages(library(xts))
suppressMessages(library(lubridate))
suppressMessages(library(dygraphs))
crime_mtl_bj<-crime_mtl_b[crime_mtl_b$QUART=='jour',]
crime_mtl_bj_count <- crime_mtl_bj %>%
group_by(DATE) %>%
summarise(count = n())
crime_mtl_bn<-crime_mtl_b[crime_mtl_b$QUART=='nuit',]
crime_mtl_bn_count <- crime_mtl_bn %>%
group_by(DATE) %>%
summarise(count = n())
crime_mtl_bs<-crime_mtl_b[crime_mtl_b$QUART=='soir',]
crime_mtl_bs_count <- crime_mtl_bs %>%
group_by(DATE) %>%
summarise(count = n())
crime_mtl_bjn_count<-merge(crime_mtl_bj_count,crime_mtl_bn_count,by.x="DATE", by.y="DATE",suffixes = c(".day",".night"))
crime_mtl_count<-merge(crime_mtl_bjn_count,crime_mtl_bs_count,by.x="DATE", by.y="DATE")
row.names(crime_mtl_count)=crime_mtl_count$DATE
crime_mtl_count<-crime_mtl_count[,-1]
dygraph(as.xts(crime_mtl_count)) %>%
dySeries("count.day", label = "day") %>%
dySeries("count.night", label = "night") %>%
dySeries("count", label = "evening")
Spread of breaking into house
Pattern over day
library(KernSmooth)
LonLat<-crime_mtl_bj[,7:8]
kde <- bkde2D(LonLat,bandwidth=c(0.00225, 0.00225))
CL <- contourLines(kde$x1 , kde$x2 , kde$fhat,nlevels = 8)
## EXTRACT CONTOUR LINE LEVELS
LEVS <- as.factor(sapply(CL, `[[`, "level"))
NLEV <- length(levels(LEVS))
## CONVERT CONTOUR LINES TO POLYGONS
library(sp)
pgons <- lapply(1:length(CL), function(i)
Polygons(list(Polygon(cbind(CL[[i]]$x, CL[[i]]$y))), ID=i))
spgons = SpatialPolygons(pgons)
## Leaflet map with polygons
library(leaflet)
im<-leaflet(spgons) %>% addTiles() %>%
addPolygons(color = heat.colors(NLEV, NULL)[LEVS]) %>%
addRectangles(lng1=min(LonLat[,1]), lat1=min(LonLat[,2]),
lng2=max(LonLat[,1]), lat2=max(LonLat[,2]),
fillColor = "transparent")
im
Pattern over night
LonLat<-crime_mtl_bn[,7:8]
kde <- bkde2D(LonLat,bandwidth=c(0.00225, 0.00225))
CL <- contourLines(kde$x1 , kde$x2 , kde$fhat,nlevels = 8)
LEVS <- as.factor(sapply(CL, `[[`, "level"))
NLEV <- length(levels(LEVS))
pgons <- lapply(1:length(CL), function(i)
Polygons(list(Polygon(cbind(CL[[i]]$x, CL[[i]]$y))), ID=i))
spgons = SpatialPolygons(pgons)
im<-leaflet(spgons) %>% addTiles() %>%
addPolygons(color = heat.colors(NLEV, NULL)[LEVS]) %>%
addRectangles(lng1=min(LonLat[,1]), lat1=min(LonLat[,2]),
lng2=max(LonLat[,1]), lat2=max(LonLat[,2]),
fillColor = "transparent")
im
Pattern over evening
LonLat<-crime_mtl_bs[,7:8]
kde <- bkde2D(LonLat,bandwidth=c(0.00225, 0.00225))
CL <- contourLines(kde$x1 , kde$x2 , kde$fhat,nlevels = 8)
LEVS <- as.factor(sapply(CL, `[[`, "level"))
NLEV <- length(levels(LEVS))
pgons <- lapply(1:length(CL), function(i)
Polygons(list(Polygon(cbind(CL[[i]]$x, CL[[i]]$y))), ID=i))
spgons = SpatialPolygons(pgons)
im<-leaflet(spgons) %>% addTiles() %>%
addPolygons(color = heat.colors(NLEV, NULL)[LEVS]) %>%
addRectangles(lng1=min(LonLat[,1]), lat1=min(LonLat[,2]),
lng2=max(LonLat[,1]), lat2=max(LonLat[,2]),
fillColor = "transparent")
im
License
Copyright (c) 2021 Saeid Amiri