0Pricing
R Academy · Lesson

Spatial Joins and Operations

Apply st_join(), st_intersection(), st_buffer(), and st_distance().

Spatial Joins with st_join

st_join(x, y) performs a spatial left join: for each feature in x, it finds features in y that satisfy a spatial predicate (default: st_intersects) and appends their attributes. Multiple matches produce multiple rows.

library(sf)

nc <- st_transform(
  read_sf(system.file('shape/nc.shp', package = 'sf')), 4326
)

# Create random points within NC bounding box
set.seed(42)
bbox <- st_bbox(nc)
pts <- data.frame(
  lon = runif(20, bbox['xmin'], bbox['xmax']),
  lat = runif(20, bbox['ymin'], bbox['ymax'])
)
pts_sf <- st_as_sf(pts, coords = c('lon', 'lat'), crs = 4326)

# Spatial join: assign county attributes to each point
pts_with_county <- st_join(pts_sf, nc['NAME'])

cat('Points with county:\n')
print(head(pts_with_county[, c('NAME', 'geometry')], 5))

st_within: Point-in-Polygon

st_within(x, y) returns a sparse matrix of logical values indicating whether each feature in x falls completely within a feature in y. It is stricter than st_intersects — boundary touches do not count.

library(sf)

nc <- st_transform(
  read_sf(system.file('shape/nc.shp', package = 'sf')), 4326
)

# Random points
set.seed(7)
bbox <- st_bbox(nc)
pts_sf <- st_as_sf(
  data.frame(
    lon = runif(30, bbox['xmin'], bbox['xmax']),
    lat = runif(30, bbox['ymin'], bbox['ymax'])
  ),
  coords = c('lon', 'lat'), crs = 4326
)

# Which points are within NC at all?
within_nc <- st_within(pts_sf, st_union(nc), sparse = FALSE)[, 1]
cat('Points within NC:', sum(within_nc), '/ 30\n')

# Keep only points inside NC
pts_inside <- pts_sf[within_nc, ]
cat('Kept:', nrow(pts_inside), 'points\n')

All lessons in this course

  1. Simple Features with the sf Package
  2. Coordinate Reference Systems and Projections
  3. Spatial Joins and Operations
  4. Interactive Maps with leaflet
← Back to R Academy