This is an R Markdown document. Markdown is a simple formatting syntax for authoring HTML, PDF, and MS Word documents. For more details on using R Markdown see http://rmarkdown.rstudio.com.
When you click the Knit button a document will be generated that includes both content as well as the output of any embedded R code chunks within the document. You can embed an R code chunk like this:
summary(cars)
## speed dist
## Min. : 4.0 Min. : 2.00
## 1st Qu.:12.0 1st Qu.: 26.00
## Median :15.0 Median : 36.00
## Mean :15.4 Mean : 42.98
## 3rd Qu.:19.0 3rd Qu.: 56.00
## Max. :25.0 Max. :120.00
You can also embed plots, for example:
title: “Problem Set 4-4: Area-Based Crime Mapping” output: html_document —
This module demonstrates area-based crime mapping using choropleth maps. We compare counts and rates across geographic areas and explore both static and interactive mapping.
packages <- c("sf", "tidyverse", "ggspatial", "sfhotspot", "leaflet", "htmltools")
for (p in packages) {
if (!require(p, character.only = TRUE)) {
install.packages(p)
library(p, character.only = TRUE)
}
}
cdmx_car_jacking <- sf::read_sf(
"https://mpjashby.github.io/crimemappingdata/cdmx_car_jacking.gpkg"
)
cdmx_borough <- sf::read_sf(
"https://mpjashby.github.io/crimemappingdata/cdmx_alcaldias.gpkg"
)
bb <- sf::st_bbox(cdmx_borough)
cdmx_pts_crop <- sf::st_crop(cdmx_car_jacking, bb)
## Warning: attribute variables are assumed to be spatially constant throughout
## all geometries
ggplot() +
geom_sf(data = cdmx_borough, fill = NA, linewidth = 0.3) +
geom_sf(data = cdmx_pts_crop, size = 0.3, alpha = 0.6) +
labs(title = "CDMX Car-Jacking Points") +
theme_void()
car_jacking_counts <- sfhotspot::hotspot_count(
data = cdmx_car_jacking,
grid = cdmx_borough
)
## Warning in sfhotspot::hotspot_count(data = cdmx_car_jacking, grid = cdmx_borough): `data` has points with the co-ordinates "0, 0".
## ℹ This usually indicates a problem with the data.
## ℹ Check co-ordinates are correct (e.g. by mapping them).
## Warning: 152 point is outside the area covered by the supplied polygons.
counts_table <- sf::st_drop_geometry(car_jacking_counts)
counts_table |>
arrange(desc(n)) |>
slice(1:10)
## # A tibble: 10 × 3
## municip nomgeo n
## <int> <chr> <int>
## 1 5 Gustavo A. Madero 545
## 2 7 Iztapalapa 492
## 3 12 Tlalpan 277
## 4 2 Azcapotzalco 210
## 5 10 Álvaro Obregón 174
## 6 3 Coyoacán 152
## 7 16 Miguel Hidalgo 152
## 8 14 Benito Juárez 140
## 9 17 Venustiano Carranza 113
## 10 13 Xochimilco 98
ggplot(car_jacking_counts) +
geom_sf(aes(fill = n), alpha = 0.7, color = NA) +
scale_fill_distiller(palette = "Oranges", direction = 1) +
labs(
title = "Car-Jacking Incidents by Alcaldía (CDMX, 2019)",
fill = "Number of Offences"
) +
theme_void()
murders <- readr::read_csv(
"https://mpjashby.github.io/crimemappingdata/uttar_pradesh_murders.csv",
show_col_types = FALSE
)
districts <- sf::read_sf(
"https://mpjashby.github.io/crimemappingdata/uttar_pradesh_districts.gpkg"
)
district_murders <- districts |>
dplyr::left_join(
murders,
by = dplyr::join_by(district_name == district)
)
glimpse(district_murders)
## Rows: 75
## Columns: 4
## $ state <chr> "Uttar Pradesh", "Uttar Pradesh", "Uttar Pradesh", "Utta…
## $ district_name <chr> "Agra", "Bareilly", "Etah", "Shahjahanpur", "Pilibhit", …
## $ geom <POLYGON [°]> POLYGON ((77.6444 27.23444,..., POLYGON ((78.974…
## $ murder <dbl> 178, 132, 65, 88, 54, 132, 72, 68, 36, 55, 25, 32, 68, 1…
colours_red <- leaflet::colorNumeric(
palette = "Reds",
domain = district_murders$murder
)
leaflet(district_murders) |>
addProviderTiles("CartoDB.Voyager") |>
addPolygons(
fillColor = ~ colours_red(murder),
fillOpacity = 0.75,
label = ~ district_name,
weight = 1,
color = "black"
) |>
addLegend(
pal = colours_red,
values = ~ murder,
title = "Number of Murders"
)
district_pop <- readr::read_csv(
"https://mpjashby.github.io/crimemappingdata/uttar_pradesh_population.csv",
show_col_types = FALSE
)
district_murders_rate <- districts |>
left_join(murders, by = join_by(district_name == district)) |>
left_join(district_pop, by = join_by(district_name == district)) |>
mutate(
murder_rate = murder / (population / 100000)
)
glimpse(district_murders_rate)
## Rows: 75
## Columns: 11
## $ state <chr> "Uttar Pradesh", "Uttar Pradesh", "Uttar Pradesh", "Utta…
## $ district_name <chr> "Agra", "Bareilly", "Etah", "Shahjahanpur", "Pilibhit", …
## $ geom <POLYGON [°]> POLYGON ((77.6444 27.23444,..., POLYGON ((78.974…
## $ murder <dbl> 178, 132, 65, 88, 54, 132, 72, 68, 36, 55, 25, 32, 68, 1…
## $ code <chr> "AG", "BR", "ET", "SJ", "PI", "AH", "PR", "JH", "JL", "J…
## $ headquarters <chr> "Agra", "Bareilly", "Etah", "Shahjahanpur", "Pilibhit", …
## $ division <chr> "Agra", "Bareilly", "Aligarh", "Bareilly", "Bareilly", "…
## $ population <dbl> 4418797, 4448359, 1774480, 3006538, 2031007, 5954391, 32…
## $ area <dbl> 4041, 2688, 2431, 4388, 3686, 5482, 3717, 5024, 4565, 40…
## $ density_km2 <dbl> 1093, 1655, 730, 685, 551, 1086, 863, 398, 370, 1113, 56…
## $ murder_rate <dbl> 4.0282457, 2.9673864, 3.6630449, 2.9269545, 2.6587796, 2…
colours_rate <- leaflet::colorNumeric(
palette = "Reds",
domain = district_murders_rate$murder_rate
)
leaflet(district_murders_rate) |>
addProviderTiles(
"Esri.WorldImagery",
options = providerTileOptions(opacity = 0.3)
) |>
addPolygons(
fillColor = ~ colours_rate(murder_rate),
fillOpacity = 0.75,
label = ~ district_name,
weight = 1,
color = "black"
) |>
addLegend(
pal = colours_rate,
values = ~ murder_rate,
title = htmltools::HTML("Murders per<br>100,000 Residents")
)