library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr 1.2.0 ✔ readr 2.2.0
## ✔ forcats 1.0.1 ✔ stringr 1.6.0
## ✔ ggplot2 4.0.2 ✔ tibble 3.3.1
## ✔ lubridate 1.9.5 ✔ tidyr 1.3.2
## ✔ purrr 1.2.1
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag() masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(sf)
## Linking to GEOS 3.13.1, GDAL 3.11.4, PROJ 9.7.0; sf_use_s2() is TRUE
library(osmdata)
## Data (c) OpenStreetMap contributors, ODbL 1.0. https://www.openstreetmap.org/copyright
library(ggspatial)
library(sfhotspot)
options(osmdata.use_cache = TRUE)
options(osmdata.base_url = "https://overpass-api.de/api/interpreter")
fixed_plot_aspect <- function() {
coord_sf(datum = NA)
}
wards <- read_sf("https://mpjashby.github.io/crimemappingdata/nottingham_wards.gpkg") |>
st_transform("EPSG:27700") |>
dplyr::filter(ward_name %in% c("Castle",
"Lenton & Wollaton East",
"Meadows"))
burglaries <- readr::read_csv(
"https://mpjashby.github.io/crimemappingdata/nottingham_burglary.csv.gz"
) |>
st_as_sf(coords = c("longitude", "latitude"), crs = "EPSG:4326") |>
st_transform("EPSG:27700") |>
st_intersection(wards)
## Rows: 1795 Columns: 5
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (2): location, lsoa_code
## dbl (2): longitude, latitude
## date (1): month
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Warning: attribute variables are assumed to be spatially constant throughout
## all geometries
nottingham_buildings <- wards |>
st_transform("EPSG:4326") |>
st_bbox() |>
opq() |>
add_osm_feature(key = "building") |>
osmdata_sf()
library(tidyverse)
library(sf)
library(osmdata)
library(ggspatial)
library(sfhotspot)
options(osmdata.use_cache = TRUE)
options(osmdata.base_url = "https://overpass-api.de/api/interpreter")
fixed_plot_aspect <- function() {
coord_sf(datum = NA)
}
wards <- read_sf("https://mpjashby.github.io/crimemappingdata/nottingham_wards.gpkg") |>
st_transform("EPSG:27700")
robbery <- read_csv("https://mpjashby.github.io/crimemappingdata/nottingham_robbery.csv.gz") |>
st_as_sf(coords = c("longitude", "latitude"), crs = "EPSG:4326") |>
st_transform("EPSG:27700")
## Rows: 555 Columns: 5
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (2): location, lsoa_code
## dbl (2): longitude, latitude
## date (1): month
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
robbery_gistar <- robbery |>
hotspot_gistar(cell_size = 100, bandwidth_adjust = 0.25, quiet = TRUE) |>
dplyr::filter(gistar > 0, pvalue < 0.05) |>
st_intersection(wards)
## Warning: attribute variables are assumed to be spatially constant throughout
## all geometries
ggplot() +
annotation_map_tile(type = "cartolight", zoomin = 0, progress = "none") +
geom_sf(aes(fill = kde), data = robbery_gistar, alpha = 0.8, colour = NA) +
geom_sf(data = wards, colour = "grey70", fill = NA) +
scale_fill_gradient(
low = rgb(0.8, 0.8, 1),
high = rgb(0, 0, 1),
breaks = range(pull(robbery_gistar, kde)),
labels = c("lower", "higher")
) +
fixed_plot_aspect() +
labs(
title = "Nottingham Robbery Hotspots",
subtitle = "Density of robbery at statistically significant hotspots",
caption = "Contains public sector information licensed under the Open Government Licence v3.0. Map data from OpenStreetMap.",
fill = "Robbery density"
) +
theme_void() +
theme(
plot.caption = element_text(colour = "grey40", hjust = 0),
plot.subtitle = element_text(margin = margin(t = 6, b = 6)),
plot.title = element_text(colour = "grey50", face = "bold", size = 16)
)
