Skip to contents

Builds one score per visible column with the score function that column's type declares, and combines them with [combine_scores()].

Usage

score_by_knowledge(
  dat_raw_anon,
  knowledge,
  row_number = "ROW_NUMBER",
  weights = NULL,
  normalize = c("range", "zscore", "rank", "none"),
  method = c("weighted", "mahalanobis"),
  split = ":",
  cov_from = c("raw", "anon", "pooled"),
  ridge = 1e-06,
  source = c("anon", "raw", "pooled"),
  weight = c("idf", "inv_log", "inv", "none"),
  hierarchy = NULL,
  rules = NULL,
  screen = c("warn", "drop", "none"),
  alpha = 0.05
)

Arguments

dat_raw_anon

dataframe of raw_anon form

knowledge

an [attacker_knowledge()] object

row_number

name of the row-number column *before* RAW_/ANON_ prefixing (default "ROW_NUMBER")

weights

numeric vector of per-column weights, one per visible column, in the order of `knowledge$visible` (default: all 1)

normalize

normalisation applied to each column before combining; see [normalize_scores()]. Default `"range"`.

method

`"weighted"` (default) or `"mahalanobis"`; see [score_multi()]

split

separator passed to [score_dist()] for `"dist"` columns (default ":"). Treated as a literal string, never as a regular expression.

cov_from, ridge

passed to [score_mahalanobis()] when `method = "mahalanobis"`

source, weight

passed to [score_idf_match()] for `"idf"` columns

hierarchy, rules

passed to [score_containment()] for `"containment"` columns

screen, alpha

passed to [score_multi()]; they decide what happens to a visible column that, measured alone, carries no signal. This matters more here than anywhere else: the W / M / S levels are meant to be read as an increasing sequence, and a dead column entering at level M or S can make the *higher* level report a lower risk than the lower one.

Value

a "reid_scores" table over the same candidate pairs as `dat_raw_anon`

Details

NORMALISATION. The per-column scores are rescaled to \[0, 1\] by default. Without it, an unweighted sum is dominated by whichever column happens to have the widest numeric range, so *adding* a column the attacker knows can make the attack worse – which would make the whole W/M/S comparison meaningless. A column with no variation at all contributes exactly 0, because it cannot discriminate between candidates.

The combination itself is done by [score_multi()] (Issue #14); this function only decides *which* columns are handed to it. `normalize` and `method` therefore accept everything `score_multi()` does, including the correlation aware `method = "mahalanobis"`. The default is unchanged (`"range"` / `"weighted"`), which is the stopgap Issue #13 needed.

Examples

d <- create_dummy_qi_data(people = 20, seed = 1)
j <- join_raw_anon_data(d, d)
k <- dummy_qi_knowledge("M")
match_greedy(score_by_knowledge(j, k))
#>    ANON_ROW_NUMBER RAW_ROW_NUMBER CONFIDENCE RESULT
#> 1                1              1  0.8099614   TRUE
#> 2                2              2  0.6204426   TRUE
#> 3                3              3  1.2314008   TRUE
#> 4                4              4  1.2916034   TRUE
#> 5                5              5  0.5689543   TRUE
#> 6                6              6  0.8699313   TRUE
#> 7                7              7  0.6954175   TRUE
#> 8                8              8  0.3660894   TRUE
#> 9                9              9  1.8013905   TRUE
#> 10              10             10  0.5145569   TRUE
#> 11              11             11  0.3864884   TRUE
#> 12              12             12  1.0048362   TRUE
#> 13              13             13  0.4184709   TRUE
#> 14              14             14  0.5300424   TRUE
#> 15              15             15  1.2977608   TRUE
#> 16              16             16  0.9785062   TRUE
#> 17              17             17  0.8012976   TRUE
#> 18              18             18  0.5106757   TRUE
#> 19              19             19  0.4085725   TRUE
#> 20              20             20  2.4519630   TRUE