The map below shows voters (number of accepted ballots) by precinct in Washington in the 2024 general election. Hovering over the precinct shows the county and precinct name. Click on a precinct to see chart showing accepted ballots broken down by imputed race. The full dataset, “Voters by Race, Precinct, Year, and Election”, contains years 2020-2024, and is available for download in the Datasets tab, under Section 2.1.
Please allow up to 60 seconds for the interface to load
shp <- read_sf('P:/Projects/UWED/Master Team Folder/Data/Inputs/SoS/Precinct_Shapefiles/2024/Statewide_Precincts_2024General.shp')
cvap <- fread('P:/Projects/UWED/Master Team Folder/Data/Outputs/CVAP_by_Precinct_Race_2010-2024_2025-07-16.csv')
registrants <- fread('P:/Projects/UWED/Master Team Folder/Data/Outputs/Registrant_Population_by_Precinct_Race_Year2025-07-25.csv')
voters <- fread('P:/Projects/UWED/Master Team Folder/Data/Outputs/Voter_Population_by_Precinct_Race_Year2025-07-25.csv')
shp_no_geo <- st_drop_geometry(shp)
registrants <- registrants %>%
mutate(PrecName = tolower(PrecName)) %>%
rename(precinctname = PrecName,
countycode = County)
voters <- voters %>%
mutate(PrecName = tolower(PrecName)) %>%
rename(precinctname = PrecName,
countycode = County)
make_voter_pl <- function(i, overwrite = FALSE, verbose = FALSE){
message(i)
x <- shp_no_geo[i,]
# year-create image dirs
# id, etc.
stcode <- x$St_Code
# county, precinct
mycounty <- x$CountyName
ctycode <- x$County
myprecinct <- x$PrecinctNa
myprecinctnum <- x$PrecinctNu
mytitle <- str_c(mycounty, str_to_title(myprecinct), myprecinctnum, sep = ", " )
vot_sub <- voters %>%
filter(St_Code == stcode,
Election_date == "2024-11-05")
all <- vot_sub %>%
pivot_longer(cols = c('Total_Pop', "Black_Pop", "White_Pop", "Hispanic_Pop", "Asian_Pop", "OtherRace_Pop")) %>%
rename(Race = name,
Population = value) %>%
filter(Race != "Total_Pop") %>%
mutate(
Race = str_remove_all(string = Race, pattern = "_Pop") %>%
factor(levels = c("White", "Black", "Asian", "Hispanic", "OtherRace"),
labels = c("White", "Black", "Asian", "Hispanic", "Other"))
)
g1 <- ggplot(data = all, aes(x = Race, y = Population)) +
geom_col(aes(), show.legend = F) +
theme_minimal() +
geom_text(aes(label=ceiling(Population)), vjust = -1, color = "gray20") +
ggtitle(paste0("Voting Population by Imputed Race in ", mycounty, " County, \n", str_to_title(myprecinct), " Precinct, ", " 2024 General Election")) +
theme(axis.text.x = element_text(angle = 45, hjust=1)) +
ylim(c(0, max(all$Population)+ 0.05*max(all$Population)))
return(g1)
}
# a function to create a pie chart
make_cvap_pl <- function(i, overwrite = FALSE, verbose = FALSE){
message(i)
x <- shp_no_geo[i,]
# year-create image dirs
# id, etc.
stcode <- x$St_Code
# county, precinct
mycounty <- x$CountyName
ctycode <- x$County
myprecinct <- x$PrecinctNa
myprecinctnum <- x$PrecinctNu
mytitle <- str_c(mycounty, str_to_title(myprecinct), myprecinctnum, sep = ", " )
cvap_sub <- cvap %>%
filter(St_Code == stcode,
Year == 2024)
all <- cvap_sub %>%
mutate(Other = AIAN_White_CVAP + Asian_White_CVAP + Black_White_CVAP + TwoOrMore_CVAP + AIAN_Black_CVAP) %>%
select(-Total_CVAP,-NotHispanic_CVAP, -AIAN_White_CVAP, -Asian_White_CVAP, -Black_White_CVAP, -TwoOrMore_CVAP, -AIAN_Black_CVAP) %>%
rename(AIAN = AIANAlone_CVAP,
Asian = AsianAlone_CVAP,
Black = BlackAlone_CVAP,
NHOPI = NHOPIAlone_CVAP,
White = WhiteAlone_CVAP,
Hispanic = Hispanic_CVAP) %>%
pivot_longer(cols = c("White", "Black", "Hispanic", "AIAN", "Asian", "NHOPI", "Other")) %>%
rename(Race = name,
Population = value) %>%
mutate(
Race =
factor(Race, levels = c("White", "Black", "Hispanic","AIAN", "Asian","NHOPI", "Other"),
labels = c("White", "Black", "Hispanic","AIAN", "Asian","NHOPI", "Other"))
)
g1 <- ggplot(data = all, aes(x = Race, y = Population)) +
geom_col( show.legend = F) +
theme_minimal() +
geom_text(aes(label=ceiling(Population)), vjust = -1, color = "gray20") +
ggtitle(paste0("Citizen Voting Age Population by Race in ", mycounty, " County, \n", str_to_title(myprecinct), " Precinct, ", " 2024")) +
theme(axis.text.x = element_text(angle = 45, hjust=1)) +
ylim(c(0, max(all$Population)+ 0.05*max(all$Population))) +
labs(caption = "*AIAN: American Indian/Alaska Native\nNHOPI: Native Hawaiin/Pacific Islander ")
return(g1)
}
make_reg_pl <- function(i, overwrite = FALSE, verbose = FALSE){
message(i)
x <- shp_no_geo[i,]
# year-create image dirs
# id, etc.
stcode <- x$St_Code
# county, precinct
mycounty <- x$CountyName
ctycode <- x$County
myprecinct <- x$PrecinctNa
myprecinctnum <- x$PrecinctNu
mytitle <- str_c(mycounty, str_to_title(myprecinct), myprecinctnum, sep = ", " )
reg_sub <- registrants %>%
filter(St_Code == stcode,
Year == "2024")
all <- reg_sub %>%
pivot_longer(cols = c('Total_Pop', "Black_Pop", "White_Pop", "Hispanic_Pop", "Asian_Pop", "OtherRace_Pop")) %>%
rename(Race = name,
Population = value) %>%
filter(Race != "Total_Pop") %>%
mutate(
Race = str_remove_all(string = Race, pattern = "_Pop") %>%
factor(levels = c("White", "Black", "Asian", "Hispanic", "OtherRace"),
labels = c("White", "Black", "Asian", "Hispanic", "Other"))
)
g1 <- ggplot(data = all, aes(x = Race, y = Population)) +
geom_col(aes(), show.legend = F) +
theme_minimal() +
geom_text(aes(label=ceiling(Population)), vjust = -1, color = "gray20") +
ggtitle(paste0("Voter Registrant Population by Imputed Race in ", mycounty, " County, \n", str_to_title(myprecinct), " Precinct, ", " 2024 General Election")) +
theme(axis.text.x = element_text(angle = 45, hjust=1)) +
ylim(c(0, max(all$Population)+ 0.05*max(all$Population)))
return(g1)
}
#cvap_pls <- lapply(c(1:nrow(shp_no_geo)), make_cvap_pl)
vote_pls <- lapply(c(1:nrow(shp_no_geo)), make_voter_pl)
#reg_pls <- lapply(c(1:nrow(shp_no_geo)), make_reg_pl)
# labels for hover
labels <- shp_no_geo %>%
mutate(labs = paste0("County: ", CountyName, "<br />Precinct: ", str_to_title(PrecinctNa)))%>%
pull(labs) %>%
lapply(htmltools::HTML)
shp_simple <- shp
#shp_simple <- ms_simplify(shp, keep_shapes = TRUE)
# cvap <- leaflet(data = shp_simple, width = "100%") %>%
# addProviderTiles(providers$CartoDB.Positron) %>%
# addPolygons(weight = 2, label = ~labels, group = "shp_simple", color = 'gray',
# fillColor = 'gray', opacity = 0.5,
# highlight = highlightOptions(
# weight = 3,
# fillOpacity = 0.6,
# color = "gray",
# opacity = 1.0,
# bringToFront = TRUE,
# sendToBack = TRUE) ) %>%
# leafpop::addPopupGraphs(graph = cvap_pls, group = "shp_simple", height = 450, width = 300)
# registrants <- leaflet(data = shp_simple, width = "100%") %>%
# addProviderTiles(providers$CartoDB.Positron) %>%
# addPolygons(weight = 2, label = ~labels, group = "shp_simple", color = 'gray',
# fillColor = 'gray', opacity = 0.5,
# highlight = highlightOptions(
# weight = 3,
# fillOpacity = 0.6,
# color = "gray",
# opacity = 1.0,
# bringToFront = TRUE,
# sendToBack = TRUE) ) %>%
# leafpop::addPopupGraphs(graph = reg_pls, group = "shp_simple", height = 450, width = 300)
voters <- leaflet(data = shp_simple, width = "100%") %>%
addProviderTiles(providers$CartoDB.Positron) %>%
addPolygons(weight = 2, label = ~labels, group = "shp_simple", color = 'gray',
fillColor = 'gray', opacity = 0.5,
highlight = highlightOptions(
weight = 3,
fillOpacity = 0.6,
color = "gray",
opacity = 1.0,
bringToFront = TRUE,
sendToBack = TRUE) ) %>%
leafpop::addPopupGraphs(graph = vote_pls, group = "shp_simple", height = 450, width = 300)
#cvap
#registrants
voters