What is the spatial extent of commonly used large-scale geographies and how do they compare in size and area? Below is a map comparing the Sacramento Metropolitan Area (Grey), Sacramento City (Red), and Sacramento County (Blue). You can hide and add layers to see how the geographies compare.

How do smaller scale geographies typically used to measure neighborhood boundaries compare? Below is a map comparing Davis zip codes (Grey), tracts (blue), block groups (green), and blocks (red). Can you find the tract you currently live in? What about the block?

One thing you’ll have to be careful about if you’re interested in comparing tracts over time - boundaries change. The final map compares Davis tracts in 2000 (red) and 2010 (black). You’ll notice that some tracts in 2000 get split up. Why? Because there were enough significant population changes within the tract from 2000 to 2010 to warrant a split. If you are curious, for example, why the tract in East Davis got split up into 3 tracts, check out this side-by-side Social Explorer map showing changes in population size in the 3 tracts from 2000 to 2010. I also embedded that map below. Can you tell what happened?

The code producing each map is shown after the map.

Sacramento metro, county and city

#Load in required packages
library(tigris)
library(tidyverse)
library(rmapshaper)

#extract metro, counties and cities          
cb <- core_based_statistical_areas(cb = TRUE)
pl <- places(state = "CA", cb = TRUE)
cnty <- counties(state ="CA", cb = TRUE)

#subset to Sacramento metro, county, and city
sac.metro <- filter(cb, NAME =="Sacramento-Roseville-Folsom, CA")
sac.city <- filter(pl, NAME == "Sacramento")
sac.county <- filter(cnty, NAME == "Sacramento")
library(leaflet)

sac.map <- leaflet(sac.metro) %>%
  # Base groups
  addTiles(group = "OSM (default)") %>%
  # Overlay groups
  addPolygons(color="grey", group = "Metro", weight = 1, smoothFactor = 0.5, 
              opacity = 1.0, fillOpacity = 0.5) %>%
  addPolygons(data = sac.city, color = "red", group = "City", weight = 1, 
              smoothFactor = 0.5, opacity = 1.0, fillOpacity = 0.5) %>%
  addPolygons(data = sac.county, color = "blue", group = "County", weight = 1, 
              smoothFactor = 0.5, opacity = 1.0, fillOpacity = 0.5) %>%
  # Layers control
  addLayersControl(
    overlayGroups = c("Metro", "City", "County"),
    options = layersControlOptions(collapsed = FALSE)
  )
sac.map

Davis ZCTAs, tracts, block groups, and blocks

#Load required packages
library(tidycensus)
library(tigris)
library(tidyverse)
library(rmapshaper)

#Get cities, tracts, blocks, and ZCTAs
pl <- places(state = "CA", year = 2011, cb = TRUE)
ca.tracts <- tracts(state ="CA", year = 2010, cb = TRUE)
yolo.block.groups <-block_groups(state="CA", county = "Yolo", year = 2010, cb = TRUE)
yolo.blocks <-blocks(state="CA", year = 2010, county = "Yolo")
zips <- zctas(cb=TRUE, year = 2010, state = "CA")

#Davis city
davis.city <- filter(pl, NAME == "Davis")

#Clip tracts, blocks and ZCTAs to Davis city boundary
davis.tracts <- ms_clip(ca.tracts, davis.city, remove_slivers = TRUE) 
davis.block.groups <- ms_clip(yolo.block.groups, davis.city, remove_slivers = TRUE) 
davis.blocks <- ms_clip(yolo.blocks, davis.city, remove_slivers = TRUE) 
davis.zip <- ms_clip(zips, davis.city, remove_slivers = TRUE) 
library(leaflet)

davis.map <- leaflet(davis.zip) %>%
  # Base groups
  addTiles(urlTemplate = "http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png") %>%
  # Overlay groups
  addPolygons(color="black", group = "Zipcode", weight = 1, smoothFactor = 0.5, 
              opacity = 1.0, fillOpacity = 0.5) %>%
  addPolygons(data = davis.tracts, color = "blue", group = "Tract", weight = 1, 
              smoothFactor = 0.5, opacity = 1.0, fillOpacity = 0.5) %>%
  addPolygons(data = davis.block.groups, color = "green", group = "Block group", 
              weight = 1, smoothFactor = 0.5, opacity = 1.0, fillOpacity = 0.5) %>%
  addPolygons(data = davis.blocks, color = "red", group = "Block", weight = 1, 
              smoothFactor = 0.5, opacity = 1.0, fillOpacity = 0.5) %>%
  # Layers control
  addLayersControl(
    overlayGroups = c("Zipcode", "Tract", "Block group", "Block"),
    options = layersControlOptions(collapsed = FALSE)
  )
davis.map

Davis tracts in 2000 and 2010

Why were there changes? The following map from Social Explorer shows total population sizes in Davis tracts in 2010 boundaries in 2000 and 2010. Toggle between 2000 to 2010 by selecting Map 1 and Map 2.

#Load in required packages
library(tidycensus)
census_api_key("b81d373d6e785ecbc489de1fc862aef424d0a63a")
library(tigris)
options(tigris_class = "sf")
library(tidyverse)
library(rmapshaper)

#Bring in cities, tracts in 2000, and tracts in 2010
pl <- places(state = "CA", cb = TRUE, year = 2011)
ca.tracts.2010 <- tracts(state ="CA", cb = TRUE, year = 2010)
ca.tracts.2000 <- tracts(state ="CA", cb = TRUE, year = 2000)
# Need to reproject 2000 tracts to 2010 tract CRS
ca.tracts.2000<-st_transform(ca.tracts.2000, crs=st_crs(ca.tracts))

#Get City of Davis
davis.city <- filter(pl, NAME == "Davis")

#Clip tracts to Davis boundaries
davis.tracts.2010 <- ms_clip(ca.tracts.2010, davis.city, remove_slivers = TRUE) 
davis.tracts.2000 <- ms_clip(ca.tracts.2000, davis.city, remove_slivers = TRUE) 
library(leaflet)

davis.map2 <- leaflet(davis.tracts.2010) %>%
  # Base groups
  addTiles(urlTemplate = "http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png") %>%
  # Overlay groups
  addPolygons(color="black", group = "2010", weight = 1, smoothFactor = 0.5,
    opacity = 1.0, fillOpacity = 0.5) %>%
  addPolygons(data = davis.tracts.2000, color = "red", group = "2000", weight = 1, 
              smoothFactor = 0.5, opacity = 1.0, fillOpacity = 0.5) %>%
  # Layers control
  addLayersControl(
    overlayGroups = c("2010", "2000"),
    options = layersControlOptions(collapsed = FALSE)
  )
davis.map2

Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License.

Website created and maintained by Noli Brazil