tidycensus::census_api_key(Sys.getenv(“CENSUS_API_KEY”)) google_api_key <- Sys.getenv(“GOOGLE_API_KEY”) stopifnot(nzchar(google_api_key))
#block groups bg <- suppressMessages( tidycensus::get_acs(geography = “block group”, # lab: BGs state = “NY”, county = c(“Broome”), variables = c(hhincome = ‘B19013_001’), year = 2023, survey = “acs5”, # filled geometry = TRUE, # filled (sf) output = “wide”) )
binghamton <- tigris::places(‘NY’) %>% dplyr::filter(NAME == ‘Binghamton’)
bg_city <- bg[binghamton,]
dplyr::glimpse(bg_city)
#next step = lat, long, radius from each block group getXYRadius <- function(polygon, gcs_id, pcs_id){
if (sf::st_crs(polygon) != sf::st_crs(pcs_id)){ polygon <- polygon %>% sf::st_transform(pcs_id) }
bb <- sf::st_bbox(polygon)
bb_corner <- sf::st_point(c(bb[1], bb[2])) %>% sf::st_sfc(crs = pcs_id)
#Get centroid bb_center <- bb %>% sf::st_as_sfc() %>% sf::st_centroid()
#Distance between center and corner (radius in meters in PCS) r <- sf::st_distance(bb_corner, bb_center)
#Convert centroid to GCS bb_center <- bb_center %>% sf::st_transform(gcs_id)
#lon/lat xy <- bb_center %>% sf::st_coordinates() %>% as.vector()
lon_lat_radius <- data.frame(x = xy[1], y = xy[2], r = r) return(lon_lat_radius) }
gcs_id <- 4326 pcs_id <- 32618
bg_city_xyr <- data.frame(x = numeric(nrow(bg_city)), y = numeric(nrow(bg_city)), r = numeric(nrow(bg_city)))
for (i in 1:nrow(bg_city)){ bg_city_xyr[i,] <- bg_city[i, ] %>% getXYRadius(gcs_id = gcs_id, pcs_id = pcs_id) }
tmap::tmap_mode(‘view’) bg_city_xyr %>% sf::st_as_sf(coords = c(“x”,“y”), crs = sf::st_crs(bg_city)) %>% sf::st_buffer(dist = .$r) %>% tmap::tm_shape() + tmap::tm_polygons(alpha = 0.3, col = ‘red’) + tmap::tm_shape(bg_city) + tmap::tm_borders(col = ‘blue’)
lat <- 42.0987 lon <- -75.9180 radius <- 1609.34 # 1 mile in meters (filled) #from lab link below endpoint <- “https://places.googleapis.com/v1/places:searchNearby”
body <- list( includedTypes = list(“park”), locationRestriction = list( circle = list( center = list(latitude = lat, longitude = lon), radius = radius ) ) )
resp <- httr::POST( endpoint, httr::add_headers( “Content-Type” = “application/json”, “X-Goog-Api-Key” = google_api_key, “X-Goog-FieldMask” = “places.displayName,places.formattedAddress,places.types” ), body = body, encode = “json” ) #check print(resp)
options(tigris_class = “sf”, tigris_use_cache = TRUE)
binghamton <- tigris::places(state = “NY”, year = 2023) |> dplyr::filter(NAME == “Binghamton”) |> sf::st_transform(4326)
bg <- tigris::block_groups(state = “NY”, county = “Broome”, year = 2023) |> sf::st_transform(4326)
bg_city <- bg[binghamton, ] |> sf::st_make_valid()
getXYRadius <- function(polygon, gcs_id, pcs_id){
if (sf::st_crs(polygon) != sf::st_crs(pcs_id)){ polygon <- polygon |> sf::st_transform(pcs_id) }
bb <- sf::st_bbox(polygon) bb_corner <- sf::st_point(c(bb[1], bb[2])) |> sf::st_sfc(crs = pcs_id) bb_center <- bb |> sf::st_as_sfc() |> sf::st_centroid()
r <- sf::st_distance(bb_corner, bb_center) # meters (PCS) bb_center <- bb_center |> sf::st_transform(gcs_id)
xy <- bb_center |> sf::st_coordinates() |> as.vector() data.frame(x = xy[1], y = xy[2], r = r) }
#Apply to every BG intersecting the city…. gcs_id <- 4326 pcs_id
<- 32618
#UTM 18N (upstate NY)
bg_city_xyr <- data.frame(x = numeric(nrow(bg_city)), y = numeric(nrow(bg_city)), r = numeric(nrow(bg_city)))
for (i in 1:nrow(bg_city)){ bg_city_xyr[i, ] <- getXYRadius(bg_city[i, ], gcs_id = gcs_id, pcs_id = pcs_id) }
pts_wgs84 <- sf::st_as_sf(bg_city_xyr, coords = c(“x”,“y”), crs = gcs_id)
bufs_wgs84 <- pts_wgs84 |> sf::st_transform(pcs_id) |> sf::st_buffer(dist = as.numeric(bg_city_xyr$r)) |> sf::st_transform(gcs_id)
tmap::tmap_mode(“view”) tmap::tm_basemap(“Esri.WorldGrayCanvas”) + tmap::tm_shape(binghamton) + tmap::tm_borders(col = “dodgerblue”) + tmap::tm_shape(bufs_wgs84) + tmap::tm_borders(col = “orange”) + tmap::tm_shape(pts_wgs84) + tmap::tm_dots(col = “red”, size = 0.03)
nearbySearch <- function(lat, lon, radius, types_vec, fieldmask_vec, google_api_key){
endpoint <- “https://places.googleapis.com/v1/places:searchNearby”
body <- list( includedTypes = as.list(types_vec), locationRestriction = list( circle = list( center = list(latitude = lat, longitude = lon), radius = radius ) ) # lab sometimes includes rankPreference; not required for the assignment )
resp <- httr::POST( endpoint, httr::add_headers( “Content-Type” = “application/json”, “X-Goog-Api-Key” = google_api_key, “X-Goog-FieldMask” = paste(fieldmask_vec, collapse = “,”) ), body = body, encode = “json” )
txt <- httr::content(resp, as = “text”, encoding = “UTF-8”) js <- jsonlite::fromJSON(txt, flatten = TRUE) if (!is.null(js\(places)) as.data.frame(js\)places) else data.frame() }
required_fields <- c( “places.id”, “places.displayName”, “places.formattedAddress”, “places.location”, “places.types”, “places.priceLevel”, “places.rating”, “places.userRatingCount” )
my_types <- c(“park”,“museum”)
#now POIs #testing lab test_list <- vector(“list”, 2) for(i in
1:2){ test_list[[i]] <- nearbySearch( lat = bg_city_xyr\(y[i],
lon = bg_city_xyr\)x[i], radius =
as.numeric(bg_city_xyr$r[i]), types_vec = my_types, fieldmask_vec =
required_fields, google_api_key = google_api_key ) Sys.sleep(1)
}
data_list <- vector(“list”, nrow(bg_city_xyr)) for(i in seq_len(nrow(bg_city_xyr))){ data_list[[i]] <- nearbySearch( lat = bg_city_xyr\(y[i], lon = bg_city_xyr\)x[i], radius = as.numeric(bg_city_xyr$r[i]), types_vec = my_types, fieldmask_vec = required_fields, google_api_key = google_api_key ) Sys.sleep(1) } data_all <- dplyr::bind_rows(data_list)
saveRDS(data_all, here::here(“google_poi_binghamton.rds”))
#convert to sf with the map example in lab file data_all_sf <- data_all |> dplyr::rename( x = places.location.longitude, y = places.location.latitude ) |> dplyr::filter(!is.na(x) & !is.na(y)) |> sf::st_as_sf(coords = c(“x”,“y”), crs = 4326)
tmap::tmap_mode(“view”) tmap::tm_basemap(“Esri.WorldGrayCanvas”) + tmap::tm_shape(binghamton) + tmap::tm_borders(col = “steelblue”) + tmap::tm_shape(data_all_sf) + tmap::tm_dots( col = “places.rating”, size = “places.userRatingCount”, popup.vars = c( “Name” = “displayName.text”, “Address” = “formattedAddress”, “Rating” = “rating”, “Reviews” = “userRatingCount” ) )
#final questions for mini assignment answer #What city did you choose? ANSWER: Binghamton, NY :) #Which two place types? ANSWER: I chose parks and museums. cat(“How many rows?”, nrow(data_all), “”, sep = ““) #Briefly describe the clusters/gaps I see (spatial patterns) #ANSWER: I see a blue boundary that represents Binghamton, NY city with orange circles which represent the buffers from my block group (BG) centroids and finally I see black dots that represent centroids!!! This was a cool lab to do. Thanks!