Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update interface to match assesspy 2.0 #13

Open
wants to merge 8 commits into
base: 1.0.0
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion CITATION.cff
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ message: "If you use this software, please cite it as below."
authors:
- family-names: "Cook County Assessor's Office"
title: "AssessR"
version: 0.6.0
version: 1.0.0
date-released: 2019-01-01
url: "https://github.com/ccao-data/assessr"
9 changes: 5 additions & 4 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
Package: assessr
Type: Package
Title: Measure Property Assessment Performance
Version: 0.6.0
Version: 1.0.0
Authors@R: c(
person(given = "Dan", family = "Snow", email="[email protected]", role=c("aut", "cre")),
person(given = "William", family = "Ridgeway", email="[email protected]", role=c("ctb")),
person(given = "Rob", family = "Ross", role=c("ctb")),
person(given = "Nathan", family = "Dignazio", role=c("ctb")),
person(given = "Damon", family = "Major", role=c("ctb"))
person(given = "Damon", family = "Major", role=c("ctb")),
person(given = "Jean", family = "Cochrane", role=c("ctb"))
)
Date: 2023-08-07
Description: An R package to measure the performance of property assessments
Expand All @@ -19,7 +20,7 @@ Encoding: UTF-8
LazyData: true
Imports:
stats
RoxygenNote: 7.2.3
RoxygenNote: 7.3.2
Suggests:
covr,
devtools,
Expand All @@ -37,5 +38,5 @@ Suggests:
testthat,
tibble,
tidyr
Depends:
Depends:
R (>= 3.5.0)
2 changes: 1 addition & 1 deletion NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ export(boot_ci)
export(cod)
export(cod_ci)
export(cod_met)
export(detect_chasing)
export(is_outlier)
export(is_sales_chased)
export(ki)
export(mki)
export(mki_met)
Expand Down
77 changes: 50 additions & 27 deletions R/ci.R
Original file line number Diff line number Diff line change
Expand Up @@ -4,45 +4,57 @@
#' for a given numeric input and a chosen function.
#'
#' @param FUN Function to bootstrap. Must return a single value.
#' @param nboot Default 100. Number of iterations to use to estimate
#' @param estimate A numeric vector of estimated values. Must be the same
#' length as \code{sale_price}.
#' @param sale_price A numeric vector of sale prices. Must be the same
#' length as \code{estimate}.
#' @param nboot Default 1000. Number of iterations to use to estimate
#' the output statistic confidence interval.
#' @param alpha Default 0.05. Numeric value indicating the confidence
#' interval to return. 0.05 will return the 95\% confidence interval.
#' @param na.rm Default FALSE. A boolean value indicating whether or not to
#' remove NA values. If missing values are present but not removed the
#' function will output NA.
#' @param ... Named arguments passed on to \code{FUN}.
#'
#' @return A two-long numeric vector containing the bootstrapped confidence
#' interval of the input vector(s).
#'
#' @examples
#'
#' # Calculate COD confidence interval
#' boot_ci(cod, nboot = 100, ratio = ratios_sample$ratio)
#' boot_ci(cod, ratios_sample$estimate, ratios_sample$sale_price, nboot = 100)
#'
#' # Calculate PRD confidence interval
#' boot_ci(
#' prd,
#' nboot = 100,
#' assessed = ratios_sample$assessed,
#' estimate = ratios_sample$estimate,
#' sale_price = ratios_sample$sale_price,
#' na.rm = FALSE
#' )
#' @export
boot_ci <- function(FUN = NULL, nboot = 100, alpha = 0.05, na.rm = FALSE, ...) { # nolint
boot_ci <- function(
FUN,
estimate,
sale_price,
nboot = 1000,
alpha = 0.05,
na.rm = FALSE) {
# Input checking and error handling
check_inputs(estimate, sale_price)

# Check that the input function returns a numeric vector
est <- FUN(...)
est <- FUN(estimate, sale_price)
stopifnot(
length(est) == 1,
is.numeric(est),
is.logical(na.rm)
is.logical(na.rm),
nboot > 0
)

# Create an index of missing values, where TRUE when missing.
# If na.rm is FALSE and index contains TRUE, return NA
missing_idx <- index_na(...)
missing_idx <- index_na(estimate, sale_price)
if (any(missing_idx) && !na.rm) {
return(NA_real_)
}
Expand All @@ -62,7 +74,10 @@ boot_ci <- function(FUN = NULL, nboot = 100, alpha = 0.05, na.rm = FALSE, ...) {
# For each of the input vectors to FUN, subset by first removing any
# index positions that have a missing value, then take a random sample of
# each vector using the sample index
sampled <- lapply(list(...), function(x) x[!missing_idx][idx])
sampled <- lapply(
list(estimate, sale_price),
function(x) x[!missing_idx][idx]
)

# For each bootstrap sample, apply the function and output an estimate for
# that sample
Expand All @@ -85,16 +100,21 @@ boot_ci <- function(FUN = NULL, nboot = 100, alpha = 0.05, na.rm = FALSE, ...) {
#' @examples
#'
#' # Calculate COD confidence interval
#' cod_ci(ratios_sample$ratio)
#' cod_ci(ratios_sample$estimate, ratios_sample$sale_price)
#' @export
cod_ci <- function(ratio, nboot = 100, alpha = 0.05, na.rm = FALSE) { # nolint

cod_ci <- function(
estimate,
sale_price,
nboot = 1000,
alpha = 0.05,
na.rm = FALSE) {
cod_ci <- boot_ci(
cod,
estimate = estimate,
sale_price = sale_price,
nboot = nboot,
alpha = alpha,
na.rm = na.rm,
ratio = ratio
na.rm = na.rm
)

return(cod_ci)
Expand All @@ -108,17 +128,21 @@ cod_ci <- function(ratio, nboot = 100, alpha = 0.05, na.rm = FALSE) { # nolint
#' @examples
#'
#' # Calculate PRD confidence interval
#' prd_ci(ratios_sample$assessed, ratios_sample$sale_price)
#' prd_ci(ratios_sample$estimate, ratios_sample$sale_price)
#' @export
prd_ci <- function(assessed, sale_price, nboot = 100, alpha = 0.05, na.rm = FALSE) { # nolint

prd_ci <- function(
estimate,
sale_price,
nboot = 1000,
alpha = 0.05,
na.rm = FALSE) {
prd_ci <- boot_ci(
prd,
estimate = estimate,
sale_price = sale_price,
nboot = nboot,
alpha = alpha,
na.rm = na.rm,
assessed = assessed,
sale_price = sale_price
na.rm = na.rm
)

return(prd_ci)
Expand All @@ -132,25 +156,24 @@ prd_ci <- function(assessed, sale_price, nboot = 100, alpha = 0.05, na.rm = FALS
#' @examples
#'
#' # Calculate PRD confidence interval
#' prb_ci(ratios_sample$assessed, ratios_sample$sale_price)
#' prb_ci(ratios_sample$estimate, ratios_sample$sale_price)
#' @export
prb_ci <- function(assessed, sale_price, alpha = 0.05, na.rm = FALSE) { # nolint

prb_ci <- function(estimate, sale_price, alpha = 0.05, na.rm = FALSE) {
# Input checking and error handling
check_inputs(assessed, sale_price)
check_inputs(estimate, sale_price)

# Remove NAs from input vectors. Otherwise, return NA if the input vectors
# contain any NA values
idx <- index_na(assessed, sale_price)
idx <- index_na(estimate, sale_price)
if (na.rm) {
assessed <- assessed[!idx]
estimate <- estimate[!idx]
sale_price <- sale_price[!idx]
} else if (any(idx) && !na.rm) {
return(NA_real_)
}

# Calculate PRB model
prb_model <- calc_prb(assessed, sale_price)
prb_model <- calc_prb(estimate, sale_price)

# Extract PRB CI from model
prb_ci <- stats::confint(prb_model, level = (1 - alpha))[2, ]
Expand Down
23 changes: 20 additions & 3 deletions R/data.R
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,30 @@
#' This sample was take from Evanston and New Trier in 2019. Ratios are
#' calculated using assessor certified (post-appeal) fair market values.
#'
#' @format A data frame with 979 observation and 4 variables:
#' @format A data frame with 979 observation and 3 variables:
#' \describe{
#' \item{assessed}{The fair market assessed value predicted by CCAO assessment
#' \item{estimate}{The fair market assessed value predicted by CCAO assessment
#' models, including any successful appeals}
#' \item{sale_price}{The recorded sale price of this property}
#' \item{ratio}{Sales ratio representing fair market value / sale price}
#' \item{town}{Township name the property is in}
#' }
#'
"ratios_sample"

#' Sample of sales and estimated market values provided by Quintos in the
#' following MKI papers:
#'
#' @references
#' Quintos, C. (2020). A Gini measure for vertical equity in property
#' assessments. <https://researchexchange.iaao.org/jptaa/vol17/iss2/2>
#'
#' Quintos, C. (2021). A Gini decomposition of the sources of inequality in
#' property assessments. <https://researchexchange.iaao.org/jptaa/vol18/iss2/6>
#'
#' @format A data frame with 30 observation and 2 variables:
#' \describe{
#' \item{estimate}{Assessed fair market value}
#' \item{sale_price}{Recorded sale price of this property}
#' }
#'
"quintos_sample"
Loading
Loading