25  Advanced Spatial Analysis

Today we will be focusing on the practice of fancy geospatial data analysis and visualization.

25.1 Load libraries

── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr     1.1.2     ✔ readr     2.1.4
✔ forcats   1.0.0     ✔ stringr   1.5.0
✔ ggplot2   3.4.2     ✔ tibble    3.2.1
✔ lubridate 1.9.2     ✔ tidyr     1.3.0
✔ purrr     1.0.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
Linking to GEOS 3.9.3, GDAL 3.5.2, PROJ 8.2.1; sf_use_s2() is TRUE

25.2 Data

The school database from California School Campus Database. I have posted a cleaned up version for the Inland Empire to this class github.

schoolURL <- 'https://raw.githubusercontent.com/RadicalResearchLLC/WarehouseAssemblyBill/main/IEschools.geojson'
schools <- sf::read_sf(dsn = schoolURL) %>% 
  st_transform(crs = 4326)

head(schools)
Simple feature collection with 6 features and 5 fields
Geometry type: MULTIPOLYGON
Dimension:     XY
Bounding box:  xmin: -117.6022 ymin: 33.89027 xmax: -117.4624 ymax: 34.11768
Geodetic CRS:  WGS 84
# A tibble: 6 × 6
  School             District City  GradesServed Level                  geometry
  <chr>              <chr>    <chr> <chr>        <chr>        <MULTIPOLYGON [°]>
1 Cucamonga Middle   Central… Ranc… 6-8          Inte… (((-117.5996 34.11482, -…
2 Allan Orrenmaa El… Alvord … Rive… K-5          Elem… (((-117.4766 33.89399, -…
3 Alvord Continuati… Alvord … Rive… 10-12        High… (((-117.4885 33.89154, -…
4 Arizona Middle     Alvord … Rive… 6-8          Inte… (((-117.4637 33.89473, -…
5 Arlanza Elementary Alvord … Rive… K-5          Elem… (((-117.4684 33.94243, -…
6 Collett Elementary Alvord … Rive… K-5          Elem… (((-117.479 33.90745, -1…

fig-Schools would show the location of school campuses in the Inland Empire if I wasn’t running out of space.

palGrades <- colorFactor(palette = 'Dark2', domain = schools$Level)

leaflet() %>% 
  addTiles() %>% 
  setView(lat = 33.9, lng = -117.4, zoom = 9) %>% 
  addProviderTiles(providers$CartoDB.PositronNoLabels) %>% 
  addPolygons(data = schools,
               color = ~palGrades(Level),
               fillOpacity = 0.8,
               weight = 2,
               group = 'Schools',
               label = ~htmlEscape(School)) %>% 
  addLegend(data = schools,
            pal = palGrades,
            values = ~Level,
            position = 'bottomleft')

Let’s import the planned Warehouse layer for comparison.

I’ve shown the quiet = TRUE argument in st_read to remove the message import from st_read()

plannedWH.url <- 'https://raw.githubusercontent.com/RadicalResearchLLC/PlannedWarehouses/main/plannedWarehouses.geojson'
plannedWarehouses <- st_read(plannedWH.url, quiet = TRUE) %>% 
  st_transform("+proj=longlat +ellps=WGS84 +datum=WGS84")

Add the planned warehouses next to the schools and zoom in a bit to the City of Fontana.

fig-plannedWHs shows the data for schools in the Inland Empire with planned warehouse projects, or it would if I wasn’t running out of space.

palGrades <- colorFactor(palette = 'Dark2', domain = schools$Level)

leaflet() %>% 
  addTiles() %>% 
  setView(lat = 34, lng = -117.5, zoom = 11) %>% 
  addProviderTiles(providers$CartoDB.PositronNoLabels) %>% 
  addPolygons(data = schools,
               color = ~palGrades(Level),
               fillOpacity = 0.8,
               weight = 2,
               group = 'Schools',
               label = ~htmlEscape(School)) %>% 
  addLegend(data = schools,
            pal = palGrades,
            values = ~Level,
            position = 'bottomleft') %>% 
  addPolygons(data = plannedWarehouses,
              color = 'black',
              fillOpacity = 0.3,
              weight = 2,
              group = 'Planned and Approved Warehouses')

Figure 25.1: Inland Empire public schools

25.2.1 Analysis

Create a 1,000 foot buffer around planned warehouses. The goal is to identify schools within a set distance of warehouses.

The st_buffer() function can be used to create shape specific boundaries around polygons.

buffWH1000 <- plannedWarehouses %>% 
  #default units are meters, 304 m = 1000 ft
  st_buffer(dist = 304)

Figure 25.2 shows the schools with their new buffer as a gray overlay.

leaflet() %>% 
  addTiles() %>% 
  addProviderTiles(provider = providers$CartoDB.PositronNoLabels) %>% 
  setView(lat = 34, lng = -117.5, zoom = 12) %>% 
  addPolygons(data = buffWH1000,
              fillOpacity = 0.4,
              color = 'gray',
              weight = 1,
              group = '1000 foot buffer') %>% 
    addPolygons(data = plannedWarehouses,
              color = 'black',
              fillOpacity = 0.3,
              weight = 2,
              group = 'Planned and Approved Warehouses') %>% 
  addPolygons(data = schools,
               color = ~palGrades(Level),
               fillOpacity = 0.8,
               weight = 2,
               group = 'Schools',
               label = ~htmlEscape(School)) %>% 
  addLegend(data = schools,
            pal = palGrades,
            values = ~Level,
            position = 'bottomleft') #%>%