Skip to content

Commit

Permalink
Gini Pull Request (#4)
Browse files Browse the repository at this point in the history
* With Functioning Code

* Finished Testing

* Finalizing

* Finalizing Last Pieces

* Modified _pkgdown

* _pkgdown changes

* Adding Ratio Study and me as a contributor

* Edits after running checks on the Vignette

* Removed Spaces at End of Ratio Study

* Added GitIgnore Info

* Added a xlsx file instead

* Switched to xlsx format to get around git controls

* Switched to CSV to get around read.xlsx

* Hopefully Final Commit

* Reverted to CSV

* Removed assessr from location

* Refactor Gini metric additions (#5)

* Create separate MKI and KI functions

This will be easier to maintain and parse in code. They share the same
documentation so there is minimal duplication. Also rename the standard
met function to `mki_met`, since it only covers that metric.

* Update pkg version and authors

Bump major version since we're adding major functionality without
breaking changes

* Fix spacing + language in formulas

* Update MKI/KI unit tests

* Update vignette language and structure

* Update README language

* Update pkgdown manifest

---------

Co-authored-by: Damon Major <damajor@ccao-datals.ccao.local>
Co-authored-by: Dan Snow <31494343+dfsnow@users.noreply.github.com>
  • Loading branch information
3 people authored Aug 9, 2023
1 parent 163ca38 commit ac9df08
Show file tree
Hide file tree
Showing 14 changed files with 529 additions and 77 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
.RData
.Rprofile
*.Rdata
*.rds
*.utf8.md
*.knit.md
*.xml
Expand Down
8 changes: 5 additions & 3 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
Package: assessr
Type: Package
Title: Measure Property Assessment Performance
Version: 0.5.2
Version: 0.6.0
Authors@R: c(
person(given = "Dan", family = "Snow", email="daniel.snow@cookcountyil.gov", role=c("aut", "cre")),
person(given = "William", family = "Ridgeway", email="william.ridgeway@cookcountyil.gov", role=c("ctb")),
person(given = "Rob", family = "Ross", role=c("ctb")),
person(given = "Nathan", family = "Dignazio", role=c("ctb"))
person(given = "Nathan", family = "Dignazio", role=c("ctb")),
person(given = "Damon", family = "Major", role=c("ctb"))
)
Date: 2023-06-26
Date: 2023-08-07
Description: An R package to measure the performance of property assessments
using IAAO standard statistics. Also includes a host of utility functions
to make common assessment and evaluation tasks easier and more consistent.
Expand All @@ -31,6 +32,7 @@ Suggests:
lintr,
pkgdown,
rmarkdown,
rprojroot,
scales,
testthat,
tibble,
Expand Down
3 changes: 3 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ export(cod_ci)
export(cod_met)
export(detect_chasing)
export(is_outlier)
export(ki)
export(mki)
export(mki_met)
export(prb)
export(prb_ci)
export(prb_met)
Expand Down
156 changes: 129 additions & 27 deletions R/formulas.R
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,14 @@
#' @order 1
#'
#' @examples
#'
#' # Calculate COD
#' cod(ratios_sample$ratio)
#' @family formulas
#' @export
cod <- function(ratio, na.rm = FALSE) {
# nolint end

# Input checking and error handling
check_inputs(ratio)

# Remove NAs if na.rm = TRUE
if (na.rm) ratio <- stats::na.omit(ratio)

# Calculate median ratio
Expand Down Expand Up @@ -86,19 +82,14 @@ cod <- function(ratio, na.rm = FALSE) {
#' @order 1
#'
#' @examples
#'
#' # Calculate PRD
#' prd(ratios_sample$assessed, ratios_sample$sale_price)
#' @family formulas
#' @export
prd <- function(assessed, sale_price, na.rm = FALSE) {
# nolint end

# Input checking and error handling
check_inputs(assessed, sale_price)

# Remove NAs from input vectors. Otherwise, return NA if the input vectors
# contain any NA values
idx <- index_na(assessed, sale_price)
if (na.rm) {
assessed <- assessed[!idx]
Expand All @@ -122,19 +113,10 @@ prd <- function(assessed, sale_price, na.rm = FALSE) {

# Calculate PRB and return model object
calc_prb <- function(assessed, sale_price) {
# Calculate ratio of assessed values to sale price
ratio <- assessed / sale_price

# Calculate median ratio
med_ratio <- stats::median(ratio)

# Generate left-hand side of PRB regression
lhs <- (ratio - med_ratio) / med_ratio # nolint

# Generate right-hand side of PRB regression
rhs <- log(((assessed / med_ratio) + sale_price) * 0.5) / log(2) # nolint

# Calculate PRB and create model object
lhs <- (ratio - med_ratio) / med_ratio
rhs <- log(((assessed / med_ratio) + sale_price) * 0.5) / log(2)
prb_model <- stats::lm(formula = lhs ~ rhs)

return(prb_model)
Expand All @@ -158,24 +140,20 @@ calc_prb <- function(assessed, sale_price) {
#' NOTE: PRB is significantly less sensitive to outliers than PRD or COD.
#'
#' @inheritParams prd
#' @describeIn prb Returns a numeric vector containing the PRD of the
#' @describeIn prb Returns a numeric vector containing the PRB of the
#' input vectors.
#' @order 1
#'
#' @examples
#'
#' # Calculate PRD
#' # Calculate PRB
#' prb(ratios_sample$assessed, ratios_sample$sale_price)
#' @family formulas
#' @export
prb <- function(assessed, sale_price, na.rm = FALSE) {
# nolint end

# Input checking and error handling
check_inputs(assessed, sale_price)

# Remove NAs from input vectors. Otherwise, return NA if the input vectors
# contain any NA values
idx <- index_na(assessed, sale_price)
if (na.rm) {
assessed <- assessed[!idx]
Expand All @@ -195,14 +173,132 @@ prb <- function(assessed, sale_price, na.rm = FALSE) {



##### MKI_KI #####

# Calculate the Gini cofficients needed for KI and MKI
calc_gini <- function(assessed, sale_price) {
df <- data.frame(av = assessed, sp = sale_price)
df <- df[order(df$sp), ]
assessed_price <- df$av
sale_price <- df$sp
n <- length(assessed_price)

av_sum <- sum(assessed_price * seq_len(n))
g_assessed <- 2 * av_sum / sum(assessed_price) - (n + 1L)
gini_assessed <- g_assessed / n

sale_sum <- sum(sale_price * seq_len(n))
g_sale <- 2 * sale_sum / sum(sale_price) - (n + 1L)
gini_sale <- g_sale / n

result <- list(gini_assessed = gini_assessed, gini_sale = gini_sale)

return(result)
}


# nolint start
#' Calculate Kakwani and Modified Kakwani Index
#'
#' @description The Kakwani Index (KI) and the Modified Kakwani Index (MKI)
#' are Gini-based methods to measure vertical equity.
#'
#' These methods first order properties by sale price (ascending), then
#' calculate the Gini coefficient for sale values and assessed values (while
#' remaining ordered by sale price). The Kakwani Index then
#' calculates the difference \code{(Gini of assessed - Gini of sale)}, and the
#' Modified Kakwani Index calculates the ratio
#' \code{(Gini of Assessed / Gini of Sale)}.
#'
#' For the Kakwani Index:
#'
#' - KI < 0 is regressive
#' - KI = 0 is vertical equity
#' - KI > 0 is progressive
#'
#' For the Modified Kakwani Index:
#'
#' - MKI < 1 is regressive
#' - MKI = 1 is vertical equity
#' - MKI > 1 is progressive
#'
#' @references
#' Quintos, C. (2020). A Gini measure for vertical equity in property
#' assessments. Journal of Property Tax Assessment & Administration, 17(2).
#' Retrieved from \href{https://researchexchange.iaao.org/jptaa/vol17/iss2/2}{https://researchexchange.iaao.org/jptaa/vol17/iss2/2}.
#'
#' Quintos, C. (2021). A Gini decomposition of the sources of inequality in
#' property assessments. Journal of Property Tax Assessment & Administration,
#' 18(2). Retrieved from
#' \href{https://researchexchange.iaao.org/jptaa/vol18/iss2/6}{https://researchexchange.iaao.org/jptaa/vol18/iss2/6}
#'
#' @inheritParams prd
#' @describeIn mki_ki Returns a numeric vector containing the KI of the
#' input vectors.
#' @order 2
#'
#' @examples
#'
#' # Calculate KI
#' ki(ratios_sample$assessed, ratios_sample$sale_price)
#' @family formulas
#' @export
#' @md
ki <- function(assessed, sale_price, na.rm = FALSE) {
# nolint end

check_inputs(assessed, sale_price)

idx <- index_na(assessed, sale_price)
if (na.rm) {
assessed <- assessed[!idx]
sale_price <- sale_price[!idx]
} else if (any(idx) && !na.rm) {
return(NA_real_)
}

g <- calc_gini(assessed, sale_price)
ki <- g$gini_assessed - g$gini_sale

return(ki)
}

#' @inheritParams prd
#' @describeIn mki_ki Returns a numeric vector containing the MKI of the
#' input vectors.
#' @order 1
#'
#' @examples
#' # Calculate MKI
#' mki(ratios_sample$assessed, ratios_sample$sale_price)
#' @export
mki <- function(assessed, sale_price, na.rm = FALSE) {
check_inputs(assessed, sale_price)

idx <- index_na(assessed, sale_price)
if (na.rm) {
assessed <- assessed[!idx]
sale_price <- sale_price[!idx]
} else if (any(idx) && !na.rm) {
return(NA_real_)
}

g <- calc_gini(assessed, sale_price)
mki <- g$gini_assessed / g$gini_sale

return(mki)
}



##### STANDARDS #####

# Mini functions to test if IAAO standards are met

#' @describeIn cod Returns TRUE when input COD meets IAAO standards
#' (between 5 and 15).
#' @param x Numeric vector of sales ratio statistic(s) to check
#' against IAAO standards.
#' against IAAO/Quintos standards.
#' @export
cod_met <- function(x) x >= 5.00 & x <= 15

Expand All @@ -217,3 +313,9 @@ prd_met <- function(x) x >= 0.98 & x <= 1.03
#' @inheritParams cod_met
#' @export
prb_met <- function(x) x >= -0.05 & x <= 0.05

#' @describeIn mki_ki Returns TRUE when input meets Quintos paper standards
#' (between 0.95 and 1.05).
#' @inheritParams cod_met
#' @export
mki_met <- function(x) x >= 0.95 & x <= 1.05
4 changes: 2 additions & 2 deletions README.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ knitr::opts_chunk$set(
[![pre-commit](https://github.com/ccao-data/assessr/actions/workflows/pre-commit.yaml/badge.svg)](https://github.com/ccao-data/assessr/actions/workflows/pre-commit.yaml)
[![codecov](https://codecov.io/gh/ccao-data/assessr/branch/master/graph/badge.svg)](https://codecov.io/gh/ccao-data/assessr)

AssessR is a software package for R developed by the Cook County Assessor’s (CCAO) Data Science Department. This package is used in the CCAO’s custom-built Computer Assisted Mass Appraisal system. The codebase for the CCAO’s CAMA system uses a wide range of functions regularly, and packaging these functions streamlines and standardizes their use. The CCAO is publishing this package to make it available to assessors, reporters, and citizens everywhere.
AssessR is a software package for R developed by the Cook County Assessor’s (CCAO) Data Department. This package is used in the CCAO’s custom-built [Automated Valuation Model (AVM)](https://github.com/ccao-data/model-res-avm). The codebase for the CCAO’s AVM uses a wide range of functions regularly, and packaging these functions streamlines and standardizes their use.

For assessors, we believe that this package will reduce the complexity of calculating ratio statistics and detecting sales chasing. We also believe that reporters, taxpayers, and members of academia will find this package helpful in monitoring the performance of local assessors and conducting research.
For assessors, we believe that this package will reduce the complexity of calculating ratio statistics and detecting sales chasing. We also hope that reporters, taxpayers, and members of academia will find this package helpful in monitoring the performance of local assessors and conducting research.

For detailed documentation on included functions and data, [**visit the full reference list**](https://ccao-data.github.io/assessr/reference/index.html).

Expand Down
17 changes: 8 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,17 @@
[![codecov](https://codecov.io/gh/ccao-data/assessr/branch/master/graph/badge.svg)](https://codecov.io/gh/ccao-data/assessr)

AssessR is a software package for R developed by the Cook County
Assessor’s (CCAO) Data Science Department. This package is used in the
CCAO’s custom-built Computer Assisted Mass Appraisal system. The
codebase for the CCAO’s CAMA system uses a wide range of functions
regularly, and packaging these functions streamlines and standardizes
their use. The CCAO is publishing this package to make it available to
assessors, reporters, and citizens everywhere.
Assessor’s (CCAO) Data Department. This package is used in the CCAO’s
custom-built [Automated Valuation Model
(AVM)](https://github.com/ccao-data/model-res-avm). The codebase for the
CCAO’s AVM uses a wide range of functions regularly, and packaging these
functions streamlines and standardizes their use.

For assessors, we believe that this package will reduce the complexity
of calculating ratio statistics and detecting sales chasing. We also
believe that reporters, taxpayers, and members of academia will find
this package helpful in monitoring the performance of local assessors
and conducting research.
hope that reporters, taxpayers, and members of academia will find this
package helpful in monitoring the performance of local assessors and
conducting research.

For detailed documentation on included functions and data, [**visit the
full reference
Expand Down
22 changes: 22 additions & 0 deletions _pkgdown.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
destination: public
url: https://ccao-data.github.io/assessr/

authors:
sidebar:
roles: [aut, ctb]
Dan Snow:
href: https://github.com/dfsnow
William Ridgeway:
href: https://github.com/wrridgeway
Rob Ross:
href: https://github.com/rross0
Damon Major:
href: https://github.com/Damonamajor

reference:

- title: Functions
Expand Down Expand Up @@ -32,6 +45,15 @@ reference:
- prb
- prb_ci
- prb_met
- subtitle: (Modified) Kakwani Index (MKI)
desc: >
The Kakwani Index (KI) and the Modified Kakwani Index (MKI) are Gini-based measures
to test for vertical equity. The work by comparing the cumulative distribution of
assessed values to the distribution of sale prices.
- contents:
- ki
- mki
- mki_met
- subtitle: Other functions
desc: Functions for other assessment-related tasks
- contents:
Expand Down
4 changes: 2 additions & 2 deletions man/cod.Rd

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

Loading

0 comments on commit ac9df08

Please sign in to comment.