Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
66e1a72
Add 2020 Census name-dictionary build script
1beb May 22, 2026
7e71d10
Remove legacy surname path and bundled surname datasets
1beb May 22, 2026
8f9c8b3
Extract name-dictionary loading; add name_source stacking helper
1beb May 22, 2026
6d959a8
Add name_source-aware dictionary loading and I/O seam
1beb May 22, 2026
20208cb
Add resolve_name_source for census.surname deprecation mapping
1beb May 22, 2026
e5ee936
Thread name_source through predict_race; deprecate census.surname
1beb May 22, 2026
a85c776
Fix #156 (anchor c_ column regex) and #162 (impute.missing=FALSE leav…
1beb May 22, 2026
22773ea
Add v4.0.0 development handoff doc
1beb May 22, 2026
c7e0140
Stop tracking local docs/ folder
1beb May 22, 2026
5990d2d
Add return.unmatched flag (#105); fix unmatched-name "NA" surname col…
1beb May 22, 2026
70b3c61
Add wru_progress option to suppress Census progress bar (#150)
1beb May 22, 2026
18ea682
Inline single-use helpers from #105/#150 into their call sites
1beb May 22, 2026
74ad391
Don't require first/middle name data for surname-only predictions (#160)
1beb May 22, 2026
8c28681
Fix use.counties year/retry arg bug and age/sex census.data caching (…
1beb May 22, 2026
084d139
Add test for wru_progress option (#150)
1beb May 22, 2026
b90d046
Fix #161 cache test to assert the download decision, not downstream p…
1beb May 22, 2026
ab49136
Respect skip_bad_geos in fBISG path (#163)
1beb May 22, 2026
8506b69
Bump version to 4.0.0
1beb May 22, 2026
9ec6708
Drop stray @param party from modfuns docs (R CMD check NOTE)
1beb May 22, 2026
af290df
Merge branch 'main' into v4.0.0
1beb May 23, 2026
883ff6d
Merge ChangeLog into CHANGELOG.md and remove redundant ChangeLog
1beb May 25, 2026
f18a3ba
Rename CHANGELOG.md to NEWS.md
1beb May 25, 2026
1877aaf
Add test artifacts and build outputs to ignore files
1beb May 25, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .Rbuildignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,11 @@ ChangeLog
^cran-comments\.md$
^CRAN-SUBMISSION$
^README\.Rmd$
^README\.html$
^data-raw$
^\.RData$
^wru_.*\.tar\.gz$
^ebisg-firstname-mlp\.pt$
^ebisg-surname-mlp\.pt$
^inst/python/__pycache__$
wru-data-.*\.rds$
19 changes: 19 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,22 @@ src/RcppExports.o
src/aux_funs.o
src/sample_me.o
src/wru.so

# local-only handoff/working docs (not part of the package)
docs/

# R workspace
.RData

# build tarballs
wru_*.tar.gz

# eBISG model weights
ebisg-firstname-mlp.pt
ebisg-surname-mlp.pt

# Python cache
__pycache__/

# test data RDS files
wru-data-*.rds
25 changes: 0 additions & 25 deletions ChangeLog

This file was deleted.

12 changes: 6 additions & 6 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
Package: wru
Title: Who are You? Bayesian Prediction of Racial Category Using Surname,
First Name, Middle Name, and Geolocation
Version: 3.1.1
Date: 2026-04-30
Version: 4.0.0
Date: 2026-05-22
Authors@R: c(
person("Kabir", "Khanna", , "kabirkhanna@gmail.com", role = "aut"),
person("Brandon", "Bertelsen", , "brandon@bertelsen.ca", role = c("aut", "cre")),
Expand Down Expand Up @@ -35,19 +35,19 @@ Depends:
Imports:
cli,
dplyr,
tidyr,
furrr,
future,
piggyback (>= 0.1.4),
PL94171,
purrr,
Rcpp,
rlang
Suggests:
covr,
future,
reticulate,
testthat (>= 3.0.0),
tidycensus
tidycensus,
tidyr
LinkingTo:
Rcpp,
RcppArmadillo
Expand All @@ -57,4 +57,4 @@ LazyData: yes
LazyDataCompression: xz
LazyLoad: yes
Roxygen: list(markdown = TRUE)
RoxygenNote: 7.3.1
RoxygenNote: 7.3.3
1 change: 0 additions & 1 deletion NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ importFrom(furrr,future_map_dfr)
importFrom(piggyback,pb_download)
importFrom(purrr,map_dfr)
importFrom(rlang,"%||%")
importFrom(stats,rmultinom)
importFrom(utils,setTxtProgressBar)
importFrom(utils,txtProgressBar)
useDynLib(wru, .registration=TRUE)
127 changes: 127 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
# wru (development version)

* `model = "fBISG"` now respects `skip_bad_geos = TRUE`: voter rows whose
geography is absent from the census data are dropped (with a message) so the
model can initialize and sample on a consistent set of rows, instead of
erroring with "Some initial race values are NA" (#163).
* Fixed `use.counties = TRUE` raising `` `year` must be one of "2020" or "2010", not "3" ``:
the county-filtered Census download passed arguments positionally with `year`
omitted, so `retry` was read as `year` (#161).
* Provided `census.data` built with `age = TRUE` and/or `sex = TRUE` is now used
instead of being silently re-downloaded; the cache check compared the stored
flags against `FALSE` rather than the requested `age`/`sex` (#161).
* Surname-only predictions (`surname.only = TRUE` or `names.to.use = "surname"`)
no longer require the first- and middle-name dictionaries to be present; those
files are read only when first/middle names are actually used (#160).
* Added a `wru_progress` option to suppress the Census-download progress bar.
Set `options(wru_progress = FALSE)` to silence the `furrr` progress bar (which
bloats batch/non-interactive log files) while keeping the other progress
messages (#150).
* `predict_race()` gains a `return.unmatched` argument (default `FALSE`). When
`TRUE`, it appends boolean `last_matched` / `first_matched` / `middle_matched`
columns reporting whether each name was found in the dictionary. The flags use
a single dictionary match for every `model` (BISG, fBISG, eBISG), so they are
comparable across models and name selections, and are computed before
imputation (#105). Re-implements the feature proposed by @mdblocker in #165,
keeping the original argument and column names.
* Fixed unmatched non-hyphenated names being silently matched to the genuine
surname "Na" after the name-cleaning cascade coerced their match key to the
string `"NA"`. Such names are now correctly treated as unmatched, so
`impute.missing = FALSE` leaves them `NA` and `impute.missing = TRUE` imputes
them rather than assigning the unrelated "Na" probabilities (#162).

# wru 3.1.1

* Updating release for piggyback fix.

# wru 3.1.0

* New feature release adding the eBISG model.

# wru 3.0.4

* Fixes a bug related to a list of variables not being unnested properly (#151, #153).

# wru 3.0.3

* Fixes a bug that pushed NaN into small population tracts (#151).

# wru 3.0.2

* Fixes a bug that led to overestimation of black and hispanic populations (#145).

# wru 3.0.1

* GitHub has changed their policy on binary formats in releases, need to refer to older version.

# wru 3.0.0

* Adding back age and sex functionality. Other improvements.

# wru 2.0.0

* Updated defaults to 2020 data, specified as next major version 2.0.

# wru 1.0.1

* Bug fixes for census URL and census year.

# wru 1.0.0

* Updates to BISG, inclusion of fBISG and other package improvements.

# wru 0.1.12

* Some Census API improvements (thanks to Silvia Kim).

# wru 0.1.11

* Minor fix requested by CRAN.

# wru 0.1.10

* Fixed minor warning message.

# wru 0.1.9

* Fixed `census_helper.R` so that state field can be lower case in user data.

# wru 0.1.8

* Updated to be compatible with U.S. Census API updates.

# wru 0.1.7

* Added testthat functionality.

# wru 0.1.6

* Removed extraneous documentation, renamed 2010 Surname List object, and added place as geography.

# wru 0.1.5

* Updated http to https to access U.S. Census API.

# wru 0.1.4

* Fixed error in merge_surnames.R and updated relevant documentation.

# wru 0.1.3

* Allows Census data download at level user prefers (block, tract, or county).

# wru 0.1.2

* Updated surname handling, enhanced demographics option, and improved error handling and documentation.

# wru 0.1.1

* New function to pre-download Census data and other minor improvements.

# wru 0.0.2

* Minor improvements.

# wru 0.0.1

* First version on CRAN.
4 changes: 2 additions & 2 deletions R/census_geo_api.R
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ census_geo_api <- function(
message(paste("County ", county, " of ", length(county_list), ": ", county_list[county], sep = ""))
region_county <- paste("for=tract:*&in=state:", state.fips, "+county:", county_list[county], sep = "")
get_census_api(data_url = census_data_url, key = key, var.names = unlist(vars), region = region_county, retry)
}, .progress = TRUE)
}, .progress = isTRUE(getOption("wru_progress", default = TRUE)))
} else {
message('There were no intersecting counties in your voter.file data (tract)')
}
Expand Down Expand Up @@ -192,7 +192,7 @@ census_geo_api <- function(

region_block <- paste("for=block:*&in=state:", state.fips, "+county:", county_list[county], "+tract:", tract_list[tract], sep = "")
get_census_api(census_data_url, key = key, var.names = unlist(vars), region = region_block, retry)
}, .progress = TRUE)
}, .progress = isTRUE(getOption("wru_progress", default = TRUE)))
}
)
message("\n") # new line for progress bar
Expand Down
17 changes: 8 additions & 9 deletions R/census_helper_v2.R
Original file line number Diff line number Diff line change
Expand Up @@ -107,9 +107,9 @@ census_helper_new <- function(

if (geo == "tract") {
geo.merge <- c("county", "tract")
if ((toDownload) || (is.null(census.data[[state]])) || (census.data[[state]]$year != year) || (census.data[[state]]$age != FALSE) || (census.data[[state]]$sex != FALSE)) {#} || (census.data[[state]]$age != age) || (census.data[[state]]$sex != sex)) {
if ((toDownload) || (is.null(census.data[[state]])) || (census.data[[state]]$year != year) || (census.data[[state]]$age != age) || (census.data[[state]]$sex != sex)) {
if(use.counties) {
census <- census_geo_api(key, state, geo = "tract", age, sex, retry,
census <- census_geo_api(key, state, geo = "tract", age, sex, year, retry,
# Only those counties within the target state
counties = unique(voter.file$county[voter.file$state == state]))
} else {
Expand All @@ -120,9 +120,9 @@ census_helper_new <- function(
}
} else if (geo == "block_group") {
geo.merge <- c("county", "tract", "block_group")
if ((toDownload) || (is.null(census.data[[state]])) || (census.data[[state]]$year != year) || (census.data[[state]]$age != FALSE) || (census.data[[state]]$sex != FALSE)) {#} || (census.data[[state]]$age != age) || (census.data[[state]]$sex != sex)) {
if ((toDownload) || (is.null(census.data[[state]])) || (census.data[[state]]$year != year) || (census.data[[state]]$age != age) || (census.data[[state]]$sex != sex)) {
if(use.counties) {
census <- census_geo_api(key, state, geo = "block_group", age, sex, retry,
census <- census_geo_api(key, state, geo = "block_group", age, sex, year, retry,
# Only those counties within the target state
counties = unique(voter.file$county[voter.file$state == state]))
} else {
Expand All @@ -139,9 +139,9 @@ census_helper_new <- function(
geo.merge <- c("county", "tract", "block")
}

if ((toDownload) || (is.null(census.data[[state]])) || (census.data[[state]]$year != year) || (census.data[[state]]$age != FALSE) || (census.data[[state]]$sex != FALSE)) {#} || (census.data[[state]]$age != age) || (census.data[[state]]$sex != sex)) {
if ((toDownload) || (is.null(census.data[[state]])) || (census.data[[state]]$year != year) || (census.data[[state]]$age != age) || (census.data[[state]]$sex != sex)) {
if(use.counties) {
census <- census_geo_api(key, state, geo = "block", age, sex, retry,
census <- census_geo_api(key, state, geo = "block", age, sex, year, retry,
# Only those counties within the target state
counties = unique(voter.file$county[voter.file$state == state]))
} else {
Expand All @@ -157,9 +157,8 @@ census_helper_new <- function(
state_must_be_downloaded <- toDownload ||
is.null(census.data[[state]]) ||
census.data[[state]]$year != year ||
# TODO: Why do we always redownload if sex or age == TRUE?
census.data[[state]]$age != FALSE ||
census.data[[state]]$sex != FALSE
census.data[[state]]$age != age ||
census.data[[state]]$sex != sex

if (state_must_be_downloaded) {
census <- census_geo_api(key, state, geo = geo, age, sex, year, retry)
Expand Down
13 changes: 9 additions & 4 deletions R/get_census_data.R
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,16 @@
#' \code{"county"}, \code{"tract"}, \code{"block"}, and \code{"place"} are supported.
#' @param retry The number of retries at the census website if network interruption occurs.
#' @param county.list A named list of character vectors of counties present in your \var{voter.file}, per state.
#' @return Output will be an object of class \code{list} indexed by state.
#' Output will contain a subset of the following elements:
#' \code{state}, \code{age}, \code{sex},
#' @return Output will be an object of class \code{list} indexed by state.
#' Output will contain a subset of the following elements:
#' \code{state}, \code{age}, \code{sex},
#' \code{county}, \code{tract}, \code{block_group}, \code{block}, and \code{place}.
#'
#'
#' @details A progress bar is shown while Census data is downloaded. To suppress
#' it (e.g., in batch or non-interactive runs where it bloats log files) without
#' silencing the other progress messages, set \code{options(wru_progress = FALSE)}.
#' This also applies to downloads triggered internally by [predict_race()].
#'
#' @export
#'
#' @examples
Expand Down
Loading
Loading