79 lines
2.7 KiB
R
79 lines
2.7 KiB
R
# update_owners.R
|
|
# Weekly update script. Reads fresh SCPA property data, joins to stable
|
|
# geometry lookup by account_number, saves data/owners.rds.
|
|
# Only the SCPA xlsx needs to be replaced to refresh ownership data.
|
|
# Input: data-raw/property/SCPA Public.xlsx (replace weekly)
|
|
# data-raw/addresses/geometry_lookup.rds (static)
|
|
# Output: data/owners.rds
|
|
|
|
library(readxl)
|
|
library(janitor)
|
|
library(dplyr)
|
|
library(stringr)
|
|
library(sf)
|
|
|
|
# Load configuration
|
|
source("./R/config.R")
|
|
|
|
options(timeout = app_config$update_config$timeout_seconds)
|
|
|
|
subdivisions <- app_config$update_config$subdivisions
|
|
|
|
# load geometry lookup (static) ----
|
|
geometry_lookup <- readRDS("./data-raw/addresses/geometry_lookup.rds")
|
|
|
|
# load and clean scpa data ----
|
|
owners_raw <-
|
|
readxl::read_xlsx(
|
|
path = "./data-raw/property/SCPA Public.xlsx",
|
|
n_max = Inf,
|
|
.name_repair = ~janitor::make_clean_names(.x)
|
|
) |>
|
|
filter(subdivision %in% subdivisions) |>
|
|
rename(
|
|
situs_address = situs_address_property_address,
|
|
homestead = homestead_exemption_yes_or_no
|
|
) |>
|
|
filter(!is.na(situs_address)) |>
|
|
filter(!grepl("^0", situs_address)) |>
|
|
mutate(
|
|
# extract clean street address (before multiple spaces / unit suffix)
|
|
label = str_trim(str_extract(situs_address, "^\\d+\\s+\\S+\\s+\\S+")),
|
|
location = paste0(label, ", Venice FL")
|
|
) |>
|
|
select(account_number, owner_1, owner_2, subdivision, homestead, label, location,
|
|
mailing_address_1, mailing_address_2, mailing_city, mailing_state, mailing_zip_code)
|
|
|
|
# join to geometry ----
|
|
owners <- owners_raw |>
|
|
inner_join(geometry_lookup, by = "account_number") |>
|
|
st_as_sf(sf_column_name = "geom")
|
|
|
|
# report any unmatched records ----
|
|
n_unmatched <- nrow(owners_raw) - nrow(owners)
|
|
if (n_unmatched > 0) {
|
|
cat("WARNING:", n_unmatched, "records had no matching geometry and were dropped.\n")
|
|
missing <- anti_join(owners_raw, st_drop_geometry(geometry_lookup), by = "account_number")
|
|
print(missing)
|
|
}
|
|
|
|
# report most recent sale date in st. andrews ----
|
|
latest_sale <-
|
|
readxl::read_xlsx(
|
|
path = "./data-raw/property/SCPA Public.xlsx",
|
|
n_max = Inf,
|
|
.name_repair = ~janitor::make_clean_names(.x)
|
|
) |>
|
|
filter(subdivision %in% subdivisions) |>
|
|
select(account_number, owner_1, contains("sale")) |>
|
|
filter(!is.na(account_number)) |>
|
|
mutate(last_sale_date = as.Date(last_sale_date, format = "%m/%d/%Y")) |>
|
|
arrange(desc(last_sale_date)) |>
|
|
head(1)
|
|
|
|
cat("Owners written:", nrow(owners), "\n")
|
|
attr(owners, "last_sale_date") <- latest_sale$last_sale_date
|
|
saveRDS(owners, app_config$data_paths$owners)
|
|
cat("Saved to", app_config$data_paths$owners, "\n")
|
|
cat("Most recent sale date:", format(latest_sale$last_sale_date, "%B %d, %Y"), "\n")
|