Skip to content

Commit

Permalink
add support for sf inputs to alarm_add_plan
Browse files Browse the repository at this point in the history
  • Loading branch information
christopherkenny committed Apr 5, 2024
1 parent e2093b5 commit 9aaa367
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 16 deletions.
4 changes: 2 additions & 2 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package: alarmdata
Title: Download, Merge, and Process Redistricting Data
Version: 0.2.1
Version: 0.2.2
Authors@R: c(
person("Cory", "McCartan", , "[email protected]", role = c("aut", "cre"),
comment = c(ORCID = "0000-0002-6251-669X")),
Expand Down Expand Up @@ -52,5 +52,5 @@ BugReports: https://github.com/alarm-redist/alarmdata/issues/
Config/testthat/edition: 3
Encoding: UTF-8
Roxygen: list(markdown = TRUE)
RoxygenNote: 7.2.3
RoxygenNote: 7.3.1
Language: en-US
4 changes: 4 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# alarmdata 0.2.2

* Adds support for using `sf` objects as input to `alarm_add_plans()`

# alarmdata 0.2.1

* Adds support for 2010 50-state simulation data.
Expand Down
43 changes: 32 additions & 11 deletions R/add_plan.R
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,17 @@
#' Facilitates comparing an existing (i.e., non-simulated) redistricting plan to a set of simulated plans.
#'
#' @param plans A `redist_plans` object.
#' @param ref_plan An integer vector containing the reference plan or a block assignment file as a `tibble` or `data.frame`.
#' @param ref_plan An `integer` vector containing the reference plan,
#' a block assignment file as a `tibble` or `data.frame`, or an `sf` object where each
#' row corresponds to a district.
#' @param map A `redist_map` object. Only required if the `redist_plans` object includes summary statistics.
#' @param name A human-readable name for the reference plan. Defaults to the name of `ref_plan`. If `ref_plan` is a
#' `tibble` or `data.frame`, it should be the name of the column of `ref_plan` that identifies districts.
#' @param calc_polsby A logical value indicating whether a Polsby-Popper compactness score should be calculated for the reference plan. Defaults to `FALSE`.
#' @param GEOID character. Ignored unless `ref_plan` is a `tibble` or `data.frame`.
#' Should correspond to the column of `ref_plan` that identifies block `GEOID`s.
#' @param GEOID character. If `ref_plan` is a `tibble` or `data.frame`, then it
#' should correspond to the column of `ref_plan` that identifies block `GEOID`s.
#' If `ref_plan` is an `sf` object, then it should correspond to the column of
#' `ref_plan` that identifies district numbers. Ignored when `ref_plan` is numeric.
#' Default is `'GEOID'`.
#' @param year the decade to request if passing a `tibble` to `ref_plan`, either `2010` or `2020`. Default is `2020`.
#'
Expand Down Expand Up @@ -64,16 +68,33 @@ alarm_add_plan <- function(plans, ref_plan, map = NULL, name = NULL,
if (is.null(map)) {
cli::cli_abort("{.arg map} must be provided to use a {.cls data.frame} for {.arg ref_plan}.")
}
if (year != 2020 && utils::packageVersion('geomander') < '2.3.0') {
cli::cli_abort('geomander must be updated to use {.arg year} != 2020')
}
if (utils::packageVersion('geomander') < '2.3.0') {
ref_plan <- geomander::baf_to_vtd(ref_plan, name, GEOID)
# if a baf
if (!inherits(ref_plan, 'sf')) {
if (year != 2020 && utils::packageVersion('geomander') < '2.3.0') {
cli::cli_abort('geomander must be updated to use {.arg year} != 2020')
}
if (utils::packageVersion('geomander') < '2.3.0') {
ref_plan <- geomander::baf_to_vtd(ref_plan, name, GEOID)
} else {
ref_plan <- geomander::baf_to_vtd(ref_plan, name, GEOID, year = year)
}

ref_plan <- ref_plan[[name]][match(ref_plan[[GEOID]], map[[names(map)[stringr::str_detect(names(map), "GEOID")][1]]])]
} else {
ref_plan <- geomander::baf_to_vtd(ref_plan, name, GEOID, year = year)
# then it has an sf shape
#cli::cli_abort('{.cls sf} input to {.arg ref_plan} detected but not yet supported.')
# first we have to check that it has the right # of rows
ndist_ref <- nrow(ref_plan)
if (ndist_ref != attr(map, "ndists")) {
cli::cli_abort("The number of districts in {.arg ref_plan} must match the number of districts in {.arg map}")
}
ref_plan_m <- geomander::geo_match(from = map, to = ref_plan)
if (GEOID %in% names(ref_plan)) {
ref_plan <- ref_plan[[GEOID]][ref_plan_m]
} else {
ref_plan <- ref_plan_m
}
}

ref_plan <- ref_plan[[name]][match(ref_plan[[GEOID]], map[[names(map)[stringr::str_detect(names(map), "GEOID")][1]]])]
} else {
cli_abort("{.arg ref_plan} must be numeric or inherit {.cls data.frame}.")
}
Expand Down
10 changes: 7 additions & 3 deletions man/alarm_add_plan.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions tests/testthat/test-add_plan.R
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,10 @@ test_that("single state add plan works", {
expect_equal(nrow(x), 5002)
expect_s3_class(x, 'data.frame')
})

test_that("sf input to alarm_add_plan() works", {
x <- alarm_add_plan(ref_plan = alarm_50state_map('DE'), plans = alarm_50state_plans('DE', stats = FALSE),
map = alarm_50state_map('DE'), name = 'example')
expect_equal(nrow(x), 5002)
expect_s3_class(x, 'data.frame')
})

0 comments on commit 9aaa367

Please sign in to comment.