if (!require("tidyverse")) {install.packages("tidyverse")}
Loading required package: tidyverse
── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr 1.1.4 ✔ readr 2.1.5
✔ forcats 1.0.0 ✔ stringr 1.5.1
✔ ggplot2 3.5.1 ✔ tibble 3.2.1
✔ lubridate 1.9.3 ✔ tidyr 1.3.1
✔ purrr 1.0.2
── 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
if (!require("readxl")) {install.packages("readxl")}
Loading required package: readxl
if (!require("elevatr")) {install.packages("elevatr")}
Loading required package: elevatr
elevatr v0.99.0 NOTE: Version 0.99.0 of 'elevatr' uses 'sf' and 'terra'. Use
of the 'sp', 'raster', and underlying 'rgdal' packages by 'elevatr' is being
deprecated; however, get_elev_raster continues to return a RasterLayer. This
will be dropped in future versions, so please plan accordingly.
if (!require("sf")) {install.packages("sf")}
Loading required package: sf
Linking to GEOS 3.8.0, GDAL 3.0.4, PROJ 6.3.1; sf_use_s2() is TRUE
if (!require("ggplot2")) {install.packages("ggplot2")}if (!require("raster")) {install.packages("raster")}
Loading required package: raster
Loading required package: sp
Attaching package: 'raster'
The following object is masked from 'package:dplyr':
select
if (!require("terra")) {install.packages("terra")}
Loading required package: terra
terra 1.7.83
Attaching package: 'terra'
The following object is masked from 'package:tidyr':
extract
if (!require("ggspatial")) {install.packages("ggspatial")}
Loading required package: ggspatial
if (!require("ggnewscale")) {install.packages("ggnewscale")}
Loading required package: ggnewscale
if (!require("tidyterra")) {install.packages("tidyterra")}
Loading required package: tidyterra
Attaching package: 'tidyterra'
The following object is masked from 'package:raster':
select
The following object is masked from 'package:stats':
filter
if (!require("topoDistance")) {install.packages("topoDistance")}
Loading required package: topoDistance
if (!require("progress")) {install.packages("progress")}
Loading required package: progress
if (!require("gdistance")) {install.packages("gdistance")}
Loading required package: gdistance
Loading required package: igraph
Attaching package: 'igraph'
The following object is masked from 'package:tidyterra':
groups
The following objects are masked from 'package:terra':
blocks, compare, union
The following object is masked from 'package:raster':
union
The following objects are masked from 'package:lubridate':
%--%, union
The following objects are masked from 'package:dplyr':
as_data_frame, groups, union
The following objects are masked from 'package:purrr':
compose, simplify
The following object is masked from 'package:tidyr':
crossing
The following object is masked from 'package:tibble':
as_data_frame
The following objects are masked from 'package:stats':
decompose, spectrum
The following object is masked from 'package:base':
union
Loading required package: Matrix
Attaching package: 'Matrix'
The following objects are masked from 'package:tidyr':
expand, pack, unpack
Attaching package: 'gdistance'
The following object is masked from 'package:igraph':
normalize
if (!require("sp")) {install.packages("sp")}if (!require("leastcostpath")) {install.packages("leastcostpath")}
Loading required package: leastcostpath
if (!require("rgdal")) {install.packages("rgdal", dependencies =TRUE)}
Loading required package: rgdal
Warning in library(package, lib.loc = lib.loc, character.only = TRUE,
logical.return = TRUE, : there is no package called 'rgdal'
Installing package into '/cloud/lib/x86_64-pc-linux-gnu-library/4.4'
(as 'lib' is unspecified)
Warning: package 'rgdal' is not available for this version of R
A version of this package for your version of R might be available elsewhere,
see the ideas at
https://cran.r-project.org/doc/manuals/r-patched/R-admin.html#Installing-packages
if (!require("ggmap")) {install.packages("ggmap", dependencies =TRUE)}
Loading required package: ggmap
ℹ Google's Terms of Service: <https://mapsplatform.google.com>
Stadia Maps' Terms of Service: <https://stadiamaps.com/terms-of-service/>
OpenStreetMap's Tile Usage Policy: <https://operations.osmfoundation.org/policies/tiles/>
ℹ Please cite ggmap if you use it! Use `citation("ggmap")` for details.
Attaching package: 'ggmap'
The following object is masked from 'package:terra':
inset
if (!require("tmaptools")) {install.packages("tmaptools", dependencies =TRUE)}
Loading required package: tmaptools
# Load the librarieslibrary(tidycensus)library(tidyverse)library(readxl)library(elevatr) library(sf) library(ggplot2)library(raster)library(terra)library(ggspatial)library(ggnewscale)library(tidyterra)library(topoDistance)library(progress)library(gdistance)library(sp)library(leastcostpath)library(ggmap)library(tmaptools)
Section #2: Import Voter Registration Data
# file path to data frame.file_path <-"save/voter_registration.rds"# if the data frame exists, load it.if (file.exists(file_path)) { voter_registration <-readRDS(file_path)message("Dataframe loaded from file.")} else {# Assuming you have a Excel file with voter registration data voter_registration <-read_excel("/cloud/project/current voterregstatsbycongressionaldistricts.xlsx") i <-c(1, 3:9) voter_registration[ , i] <-apply(voter_registration[ , i], 2, function(x) as.numeric(as.character(x)))# Calculate proportion of Republican voters voter_registration <- voter_registration %>%mutate(RepublicanProportion = Republican / Total)# Calculate proportion of Democratic voters voter_registration <- voter_registration %>%mutate(DemocraticProportion = Democratic / Total)# Calculate proportion of Libertarian voters voter_registration <- voter_registration %>%mutate(LibertarianProportion = Libertarian / Total)# Calculate proportion of Green voters voter_registration <- voter_registration %>%mutate(GreenProportion = Green / Total)# Calculate proportion of No Affiliation voters voter_registration <- voter_registration %>%mutate(NoAffiliationProportion =`No Affiliation`/ Total)# Calculate proportion of Other voters voter_registration <- voter_registration %>%mutate(OtherProportion = Other / Total)saveRDS(voter_registration, file_path) message("Dataframe generated and saved to file.")}
Dataframe loaded from file.
Section #3: Import ACS variable table for later use.
# Define the file pathfile_path <-"save/acs_vars.rda"# Check if the file existsif (file.exists(file_path)) {# Load the data frame from the file acs_variables <-readRDS(file_path)message("Dataframe loaded from file.")} else {# Generate the data frame acs_variables <-load_variables(dataset ="acs1", year =2021)# Save the data frame to the filesaveRDS(acs_variables, file_path)message("Dataframe generated and saved to file.")}
Dataframe loaded from file.
Section #4: Import PA state geometry.
# Define the file pathfile_path <-"save/pa_geom.rda"# Check if the file existsif (file.exists(file_path)) {# Load the data from the file pa_shape <-readRDS(file_path)message("Data loaded from file.")} else {# Your code to generate the data pa_shape <-get_acs(geography ="state",variables =c("B25077_001"), # Random Variable to ignore.state ="PA",geometry =TRUE) %>%subset(select =-c(variable, estimate, moe))# Save the data to the filesaveRDS(pa_shape, file_path)message("Data generated and saved to file.")}
Data loaded from file.
Section #5: Import Population Density Data for PA
# Define the file pathfile_path <-"save/pop_raster.rds"# Check if the file existsif (file.exists(file_path)) {# Load the data from the file pop_raster <-readRDS(file_path)message("Data loaded from file.")} else {# Generate the data pop_raster <-raster("/cloud/project/pden2010_block/pden2010_60m.tif")# Transform the CRS of the multi-polygon to match the raster CRS pa_multipolygon <-st_transform(pa_shape, crs(pop_raster))# Crop the raster by the multi-polygon cropped_raster <-crop(pop_raster, extent(pa_multipolygon))plot(log(cropped_raster+1))# Mask the raster to set values outside the multi-polygon to NA masked_raster <-mask(cropped_raster, pa_multipolygon)plot(log(masked_raster+1))# Log transform of the population. pop_raster <- (log(masked_raster+1))# Save the data to the filesaveRDS(pop_raster, file_path)message("Data generated and saved to file.")}
Data loaded from file.
Section #6: Import Housing Cost Data for PA
# Define the file pathfile_path <-"save/pa_housing_data.rds"# Check if the file existsif (file.exists(file_path)) {# Load the data from the file pa_dists <-readRDS(file_path)message("Data loaded from file.")} else {# Query housing price data for Pennsylvania's congressional districts pa_housing_data <-get_acs(geography ="congressional district",variables =c("B25077_001"), # Median home value, Median monthly housing costsstate ="PA",geometry =TRUE)# Format the data layout.colnames(voter_registration)[1] <-"GEOID" pa_housing_data$GEOID <-as.numeric(pa_housing_data$GEOID)# Merge the ACS data with voter registration data merged_data <- pa_housing_data %>%left_join(voter_registration, by ="GEOID")# Transform the district data pa_dists <-st_transform(merged_data, crs(pop_raster))# Save the data frame to the filesaveRDS(pa_dists, file_path)message("Data generated and saved to file.")}
Data loaded from file.
Section #7: Visualize the proportion of registered republican voters for PA congressional districts
# Create the ggplotggplot(data = pa_dists) +geom_sf(aes(fill = RepublicanProportion), color ="darkred", size =0.5) +scale_fill_gradient2(low ="white", mid ="grey", high ="red", midpoint =0.5) +coord_sf() +# Coordinate system for spatial datatheme_minimal() +labs(title ="Proportion of Republican Voters in Pennsylvania Congressional Districts",fill ="Republican Proportion")
Section #8: Visualize the proportion of registered democrat voters for PA congressional districts
# Create the ggplotggplot(data = pa_dists) +geom_sf(aes(fill = DemocraticProportion), color ="darkblue", size =0.5) +scale_fill_gradient2(low ="white", mid ="grey", high ="blue", midpoint =0.5) +coord_sf() +# Coordinate system for spatial datatheme_minimal() +labs(title ="Proportion of Democratic Voters in Pennsylvania Congressional Districts",fill ="Democratic Proportion")
Section #9: Visualize the estimate median housing costs for PA congressional districts
# Create the ggplotggplot(data = pa_dists) +geom_sf(aes(fill = estimate), color ="darkblue", size =0.5) +scale_fill_gradient2(low ="white", mid ="grey", high ="darkgreen", midpoint =0.5) +coord_sf() +# Coordinate system for spatial datatheme_minimal() +labs(title ="Median Home Value in Pennsylvania Congressional Districts",fill ="Median Home Value")
Section #10: Visualize the population density for PA (Log Scale)
ggplot() +geom_spatraster(data=rast(pop_raster), show.legend =TRUE) +geom_sf(data = pa_dists, alpha=0, color='black', size =0.5) +coord_sf() +# Coordinate system for spatial datatheme_minimal() +labs(title ='')
<SpatRaster> resampled to 500720 cells.
Section #11: Import the DEM for PA
# Define the file pathfile_path <-"save/pa_dem.rds"# Check if the file existsif (file.exists(file_path)) {# Load the data from the file pa_dem <-readRDS(file_path)message("Data loaded from file.")} else {# Get the bounding box of the geometry bounding_box <-st_bbox(pa_shape) pa_sf <-st_as_sfc(pa_shape)# Get the DEM data pa_dem <-get_elev_raster(locations = pa_dists, z =7, src ="aws", prj =crs(pop_raster))# Create Spat Raster pa_dem_spatrast <-rast(pa_dem)# Transform the CRS of the multi-polygon to match the raster CRS pa_multipolygon <-st_transform(pa_shape, crs(pa_dem_spatrast))# Crop the raster by the multi-polygon cropped_dem <-crop(pa_dem_spatrast, extent(pa_multipolygon))plot(log(cropped_dem+1))# Mask the raster to set values outside the multi-polygon to NA pa_dem <-mask(cropped_dem, pa_multipolygon)plot(log(pa_dem+1))# Save the data to the filesaveRDS(pa_dem, file_path)message("Data generated and saved to file.")}
Data loaded from file.
Section #12: Generater the slope from PA DEM
# Define the file pathfile_path <-"save/pa_slope.rds"# Check if the file existsif (file.exists(file_path)) {# Load the data from the file pa_slope <-readRDS(file_path)message("Data loaded from file.")} else {# Generate the data pa_slope <- terra::terrain(pa_dem, v ="slope",unit ="radians", neighbors =8)# Save the data to the filesaveRDS(pa_slope, file_path)message("Data generated and saved to file.")}
Data loaded from file.
Section #13: Generater the aspect from PA DEM
# Define the file pathfile_path <-"save/pa_aspect.rds"# Check if the file existsif (file.exists(file_path)) {# Load the data from the file pa_aspect <-readRDS(file_path)message("Data loaded from file.")} else {# Generate the data pa_aspect <- terra::terrain(pa_dem, v ="aspect",unit ="radians", neighbors =8)# Save the data to the filesaveRDS(pa_aspect, file_path)message("Data generated and saved to file.")}
Data loaded from file.
Section #14: Generater the shade from PA DEM
# Define the file pathfile_path <-"save/pa_shade.rds"# Check if the file existsif (file.exists(file_path)) {# Load the data from the file pa_shade <-readRDS(file_path)message("Data loaded from file.")} else {# Generate the data pa_shade <- terra::shade(slope = pa_slope,aspect = pa_aspect,angle =30, direction =315,normalize =TRUE)# Save the data to the filesaveRDS(pa_shade, file_path)message("Data generated and saved to file.")}
Data loaded from file.
Section #15: Visualize PA Elevation
ggplot() +geom_spatraster(data=pa_shade, show.legend =FALSE) +scale_fill_distiller(palette ="Greys") +new_scale_fill() +geom_spatraster(data=pa_dem, alpha =0.7) +#alpha is the proportion opaque for the layer, so we're saying to make #this 30% transparentscale_fill_hypso_tint_c() +labs(fill ="Elevation (masl)")
<SpatRaster> resampled to 500720 cells.
<SpatRaster> resampled to 500720 cells.
Section _#: Import the coordinates for Hospitals in PA
# Define the file pathfile_path <-"save/hospital_coords.rds"# Check if the file existsif (file.exists(file_path)) {# Load the data from the file hospital_coords <-readRDS(file_path)message("Data loaded from file.")} else {# Read Hospital Data hospital_data <-read_csv("Hospitals.csv") coords <-select(hospital_data, LONGITUDE, LATITUDE) coords <-st_as_sf(x = coords, coords =c("LONGITUDE", "LATITUDE"),crs="EPSG:4258") hospital_coords <-st_transform(coords, '+proj=aea +lat_0=23 +lon_0=-96 +lat_1=29.5 +lat_2=45.5 +x_0=0 +y_0=0 +datum=NAD83 +units=m +no_defs')# Save the data to the filesaveRDS(hospital_coords, file_path)message("Data generated and saved to file.")}
Data loaded from file.
Section _#: Generate Cost Distance for Hospitals in PA
# Define the file pathfile_path <-"save/hospital_cost_dist.rds"# Define a cost function based on slope cost_function <-function(x) { slope <-abs(diff(x)) # Calculate the slope return(slope +1) # Add 1 to avoid zero cost }# Check if the file existsif (file.exists(file_path)) {# Load the data from the file hospitals_cost_distance <-readRDS(file_path)message("Data loaded from file.")} else {# Create the transition layer trans <-transition(as(pa_dem, "Raster"), transitionFunction = cost_function, directions =8) conductance <-geoCorrection(trans)# Calculate the cost distance raster hospitals_cost_distance <-accCost(conductance, fromCoords=as(hospital_coords, "Spatial"))plot(hospitals_cost_distance)# Save the data to the filesaveRDS(hospitals_cost_distance, file_path)message("Data generated and saved to file.")}
Data loaded from file.
Section _#: Import the coordinates for Schools in PA
# replace "api_key" with your API keyregister_google(key ='AIzaSyABGVOEA6qrU5PQNOH33QrjJgHzR04ivB4')# file path for the data framefile_path <-"save/schls_ggmap.Rda"# if the data frame exists, load it.if (file.exists(file_path)) {# Load the data from the file schls_ggmap <-readRDS(file_path)message("Data loaded from file.")} else { # read/extract data for schools. schools <-read_excel("ExtractPublicSchools.xlsx") schools <-subset(schools, GradeCtgy =='SECONDARY') schools <-select(schools, SchoolName, LEALocationCity, LEALocationState) schools$Concat <-with(data = schools, paste(SchoolName, ',', LEALocationCity,',', LEALocationState)) schools <- schools[!apply(schools, 1, function(x) any(x=="")),] # run the geocode function from ggmap package schls_ggmap <-geocode(location = schools$Concat,output ="more", source ="google") schls_ggmap <-cbind(schools, schls_ggmap)# print the results schls_ggmap <- schls_ggmap[complete.cases(schls_ggmap), ]# Save the data to the filesaveRDS(schls_ggmap, file_path)message("Data generated and saved to file.")}
Data loaded from file.
Section _#: Clean and Mutate the School Coords
# Define the file pathfile_path <-"save/school_coords.rds"# Check if the file existsif (file.exists(file_path)) {# Load the data from the file school_coords <-readRDS(file_path)message("Data loaded from file.")} else {# Read Hospital Data coords <-select(schls_ggmap, lon, lat) coords <-st_as_sf(x = coords, coords =c("lon", "lat"),crs="EPSG:4258") school_coords <-st_transform(coords, '+proj=aea +lat_0=23 +lon_0=-96 +lat_1=29.5 +lat_2=45.5 +x_0=0 +y_0=0 +datum=NAD83 +units=m +no_defs')# Save the data to the filesaveRDS(school_coords, file_path)message("Data generated and saved to file.")}
Data loaded from file.
Section _#: Generate Cost Distance for School Availability
# Define the file pathfile_path <-"save/school_cost_dist.rds"# Define a cost function based on slope cost_function <-function(x) { slope <-abs(diff(x)) # Calculate the slope return(slope +1) # Add 1 to avoid zero cost }# Check if the file existsif (file.exists(file_path)) {# Load the data from the file school_cost_dist <-readRDS(file_path)message("Data loaded from file.")} else {# Create the transition layer trans <-transition(as(pa_dem, "Raster"), transitionFunction = cost_function, directions =8) conductance <-geoCorrection(trans)# Calculate the cost distance raster school_cost_dist <-accCost(conductance, fromCoords=as(school_coords, "Spatial"))plot(school_cost_dist)# Save the data to the filesaveRDS(school_cost_dist, file_path)message("Data generated and saved to file.")}
Data loaded from file.
Visualize the Cost Distance Rasters
ggplot() +geom_spatraster(data=rast(school_cost_dist), show.legend =TRUE) +geom_sf(data = pa_dists, alpha=0, color='black', size =0.5) +coord_sf() +# Coordinate system for spatial datatheme_minimal() +labs(title ='')
<SpatRaster> resampled to 500720 cells.
ggplot() +geom_spatraster(data=rast(hospitals_cost_distance), show.legend =TRUE) +geom_sf(data = pa_dists, alpha=0, color='black', size =0.5) +coord_sf() +# Coordinate system for spatial datatheme_minimal() +labs(title ='')