I have created a function that uses st_join()
from the sf
package to extract the congressional district (a polygon) from a set of latitude and longitude coordinates, using a different shapefile to identify the congressional district depending on a "congress" argument that is specified. (This is necessary because districts are periodically redrawn, so the boundaries change over time.) The next step is to apply the function row by row to a data frame containing multiple rows of coordinates (and associated "congress" values) so that the congress value for a given row determines which shapefile to use, and then assign the extracted district to a new variable.
I'm running into trouble applying this function row-by-row. I first tried using the rowwise()
and mutate()
functions from dplyr
, but got a "must be size 1" error. Based on the comments to this question, I put list()
around the variable assigned inside the mutate()
function, but this has resulted in the new variable being a list instead a single character string.
I would greatly appreciate help figuring out a way to either (i) modify the function so that it can be applied row by row using rowwise()
and mutate()
or (ii) apply my function row-by-row in some other way.
Reproducible code is below; you just need to download two shapefiles from https://cdmaps.polisci.ucla.edu/ ("districts104.zip" and "districts111.zip"), unzip them, and put them in your working directory.
library(tidyverse)
library(sf)
districts_104 <- st_read("districts104.shp")
districts_111 <- st_read("districts111.shp")
congress <- c(104, 111)
latitude <- c(37.32935, 37.32935)
longitude <- c(-122.00954, -122.00954)
df_test <- data.frame(congress, latitude, longitude)
point_geo_test <- st_as_sf(df_test,
coords = c(x = "longitude", y = "latitude"),
crs = st_crs(districts_104)) # prep for st_join()
sf_use_s2(FALSE) # preempt evaluation error that would otherwise pop up when using the st_join function
extract_district <- function(points, cong) {
shapefile <- get(paste0("districts_", cong))
st_join_results <- st_join(points, shapefile, join = st_within)
paste(st_join_results$STATENAME, st_join_results$DISTRICT, sep = "-")
}
point_geo_test <- point_geo_test %>%
rowwise %>%
mutate(district = list(extract_district(points = point_geo_test, cong = congress)))