calaud
Calibration audit of a predictive-policing ranking
calaud( area, risk = NULL, outcome = NULL, group = NULL, population = NULL, nperm = 999, seed = NULL)Does the order in which an algorithm ranks areas by predicted risk match
the order of what was later recorded there, and does the disagreement
follow the areas’ demographic make-up? calaud() ranks the areas both
ways, measures the agreement by Spearman’s correlation, and gives each
group the mean gap between its areas’ two ranks, with a permutation
test. It generalises the district-level analysis of the SciencesPo
predictive-policing study of Chicago (Lacherade et al. 2021) to any
place: the five columns of the audit are area, risk, outcome,
group and population.
Parameters
Section titled “Parameters”areaThe area of each record: labels; or a data frame with columns
area,risk,outcome,groupand optionallypopulation, the other arguments then left out. Aclprelist fromclprep()is taken too: its elements fill the arguments by name.riskThe risk the algorithm predicts for each record: finite numbers.
outcomeThe recorded outcome of each record (a 0 or 1, or a count): finite numbers.
groupThe group of each record (or area): labels.
populationNULL, or the population of each area: positive, one per record (the same within an area) or one per area named by area.npermThe number of permutations: a whole number from 0 (none).
seedNULLto draw the seed of the bootstrap (or the permutations) from R’s generator, so thatset.seed()fixes it, or one whole number from 0.
Returns
Section titled “Returns”A list: areas, a data frame with one row per area (sorted by
label): area, n (records), risk, rate, group, riskrk,
raterk and gap; groups, one row per group: group, n (areas),
gap (mean) and p (NaN without areas or permutations); spear, a
named vector: rho, s (Spearman’s statistic, the sum of squared
rank differences), pex, t and pt; ties (TRUE when either
ranking has ties); between, ss and p; and nperm.
Records are rolled up to areas first: an area’s risk is the mean over
its records, its rate the mean outcome (or, with population, the
summed outcome per head), and its group the most frequent label among
its records (the first in order on ties). One record per area is the
per-area audit itself. Rank 1 is the highest; tied values share the mean
of their ranks. An area’s gap is its outcome rank minus its risk rank:
positive when the algorithm ranks it as riskier than its recorded
outcome warrants, negative when less risky.
Spearman’s rho is Pearson’s correlation of the two rankings (Spearman
1904). pex is its two-sided p-value by algorithm AS 89 (Best and
Roberts 1975): exact for nine areas or fewer, from the Edgeworth series
up to 1289, and NA when either ranking has ties; pt is the
large-sample one from the t distribution, as stats::cor.test() gives
them. A group’s mean gap is tested against shuffling the groups across
the areas, nperm times; between tests all groups at once by the
between-group sum of squares of the gaps (the gaps sum to 0).
The audit compares the algorithm with the records, not with crime: a
recorded outcome follows where the police looked as well as what
happened, so a group’s areas can look over-predicted because their
incidents were recorded less, or under-predicted because they were
recorded more (see fairsim()). A gap says the two orders disagree for
that group’s areas; it does not say which order is right or why.
References
Section titled “References”Spearman, C. (1904). The proof and measurement of association between two things. American Journal of Psychology, 15(1), 72-101. doi:10.2307/1412159
Best, D. J. and Roberts, D. E. (1975). Algorithm AS 89: the upper tail probabilities of Spearman’s rho. Journal of the Royal Statistical Society, Series C, 24(3), 377-379. doi:10.2307/2347111
Lacherade, P., Szabo, B., Krikava, J. and Aeby, M. (2021). Predictive policing in the City of Chicago. Group project, Decoding Biases in AI, Sciences Po. https://github.com/marquito95/Predictive-policing-Chicago
Examples
Section titled “Examples”set.seed(3)d <- fairsim(4000, nareas = 24, bias = 0.5, seed = 1)# the recorded outcome is `det`: the incidents that were detectedr <- calaud(d$area, d$risk, d$det, d$group, nperm = 499, seed = 1)r$groupsr$spearAlso in the R reference, with the method and its source.