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("foreign"))
install.packages("foreign")
## Loading required package: foreign
if (!require("sf"))
install.packages("sf")
## Loading required package: sf
## Linking to GEOS 3.12.1, GDAL 3.8.4, PROJ 9.3.1; sf_use_s2() is TRUE
if (!require("scales"))
install.packages("scales")
## Loading required package: scales
##
## Attaching package: 'scales'
##
## The following object is masked from 'package:purrr':
##
## discard
##
## The following object is masked from 'package:readr':
##
## col_factor
if (!require("mapview"))
install.packages("mapview")
## Loading required package: mapview
if (!require("leaflet"))
install.packages("leaflet")
## Loading required package: leaflet
if (!require("leaflet.extras2"))
install.packages("leaflet.extras2")
## Loading required package: leaflet.extras2
library(tidyverse)
library(foreign)
library(sf)
library(scales)
library(mapview)
library(leaflet)
library(leafpop)
# Read the first data file and use it to create
# an "AllData" dataframe.
AddData <- read.dbf("10162024.dbf")
AllData <- AddData
# Add each subsequent day's file name to this list,
# then run
datafiles <- c("10172024.dbf",
"10182024.dbf",
"10192024.dbf",
"10212024.dbf",
"10222024.dbf",
"10232024.dbf")
# This "for loop" adds each listed datafile
# to the AllData dataframe
for (x in datafiles) {
AddData <- read.dbf(x, as.is = FALSE)
AllData <- rbind(AllData, AddData)
}
# Save AllData file as .csv
write_csv(AllData,"EarlyVoterData2024.csv")
# Get total votes so far
TotalVotes <- nrow(AllData)
PctVotes <- round((TotalVotes / 224746)*100, digits = 0)
### Make a chart showing vote totals by day ###
# Aggregate data by day
# and do some formatting
VotesByDay <- AllData %>%
group_by(VOTEDDATE) %>%
summarize(Votes = n()) %>%
rename(Date = VOTEDDATE) %>%
mutate(Date = (str_remove(Date,"2024-")))
# Make the chart
chart = ggplot(data = VotesByDay,
aes(x = Date,
y = Votes))+
geom_bar(stat="identity", fill = "#41B3A2") +
geom_text(aes(label=comma(Votes)),
vjust=1.6,
color="black",
size=3.5)+
theme(
axis.title.x = element_blank(),
axis.ticks.y = element_blank(),
axis.title.y = element_blank(),
axis.text.y = element_blank(),
panel.background = element_blank())
# Show the chart
chart

### Make a precinct-level map of early voting turnout ***
# Aggregate early voting data by precinct
PrecinctData <- AllData %>%
group_by(PCT_NBR) %>%
summarize(Votes = n()) %>%
rename(Precinct = PCT_NBR)
# Download and unzip a precinct map to pair with the vote data
download.file("https://github.com/drkblake/Data/raw/main/Voting_Precincts_5_31_24.zip","TNVotingPrecincts.zip")
unzip("TNVotingPrecincts.zip")
# Read the unzipped data into an All_Precincts dataframe
All_Precincts <- read_sf("Voting_Precincts_5_31_24.shp")
# Filter for RuCo precincts,
# strip dash from precinct numbers,
# and do some renaming
County_Precincts <- All_Precincts %>%
filter(COUNTY == 149) %>%
rename(Precinct = NEWVOTINGP) %>%
mutate(Precinct = (str_remove(Precinct,"-")))
# Use left_join() function to join the data and map file
# using the "Precinct" variable as the joining key
MapData <- left_join(PrecinctData, County_Precincts, by = "Precinct")
# Use left_join() again, this time to add
# voter registration totals per precinct
# This file was in the .zip file along with
# the daily .dbf files
RegData <- read_csv("RegVotersRuCo.csv") %>%
mutate(Precinct = as.character(Precinct))
## Rows: 33 Columns: 2
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## dbl (2): Precinct, RegVoters
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
MapData <- left_join(MapData, RegData, by = "Precinct")
# Calculate and add Percent column
# Then select columns to keep
# and put them in a MapData dataframe
MapData <- MapData %>%
mutate(Percent = round((Votes/RegVoters)*100), digits = 0) %>%
rename(Voters = RegVoters) %>%
select(Precinct, Votes, Voters, Percent, geometry)
# Make a mappable MapData_sf file out of MapData
MapData_sf <- st_as_sf(MapData)
# Make the map
Map <- mapview(
MapData_sf,
zcol = "Percent",
layer.name = "Pct. early voted",
popup = popupTable(
MapData_sf,
feature.id = FALSE,
row.numbers = FALSE,
zcol = c(
"Precinct",
"Votes",
"Voters",
"Percent"
)
)
)
# Show the map
Map
# Calculate some additional voting stats
MinTurnout <- min(MapData$Percent)
MaxTurnout <- max(MapData$Percent)
MedianTurnout <- median(MapData$Percent)
MeanTurnout <- mean(MapData$Percent)