## ----setup, include = FALSE---------------------------------------------------
knitr::opts_chunk$set(
  collapse = TRUE,
  comment  = "#>"
)
set.seed(1)

## ----data---------------------------------------------------------------------
library(joinery)
library(dplyr)

data(base_example)
data(target_example)

glimpse(base_example)

## ----target-------------------------------------------------------------------
glimpse(target_example)

## ----pair---------------------------------------------------------------------
target_example |>
  filter(id_target == "T0006") |>
  select(id_target, Vorname, Nachname, Strasse, Ort)

base_example |>
  filter(id_base == "B0006") |>
  select(id_base, Vorname, Nachname, Strasse, Ort)

## ----strategy-----------------------------------------------------------------
strat <- search_strategy(
  Nachname   ~ normalize_text() + word_tokens(min_nchar = 3),
  Vorname    ~ normalize_text() + word_tokens(min_nchar = 3),
  Strasse    ~ normalize_street(lang = "de") + word_tokens(min_nchar = 3),
  Hausnummer ~ numeric_tokens,
  Ort        ~ normalize_text(),
  block_by   = "Kreis",
  threshold  = 0.8
)

strat

## ----inspect------------------------------------------------------------------
head(inspect_tokens(base_example, "id_base", strat, Vorname), 8)

## ----audit--------------------------------------------------------------------
audit_strategy(base_example, "id_base", strat)

## ----dedup--------------------------------------------------------------------
dups <- detect_duplicates(base_example, id = "id_base", strategy = strat)

dups |>
  select(duplicate_group, id, score, rank) |>
  head()

## ----dedup-collapse-----------------------------------------------------------
base_clean <- deduplicate_table(base_example, dups, id = "id_base")

nrow(base_example) - nrow(base_clean)

## ----search-------------------------------------------------------------------
matches <- search_candidates(
  base_clean,
  target_example,
  base_id   = "id_base",
  target_id = "id_target",
  strategy  = strat
)

matches |>
  select(match_id, score, source, id, Nachname, rank) |>
  head()

## ----summarise----------------------------------------------------------------
summarise_matches(matches, threshold = 0.8)

## ----explain------------------------------------------------------------------
mid <- matches |> filter(id == "T0006") |> pull(match_id) |> first()

receipt <- explain_match(
  matches, strat,
  base      = base_clean,
  id        = "id_base",
  target    = target_example,
  target_id = "id_target",
  match_id  = mid
)

receipt

## ----explain-plot, fig.alt = "Horizontal bar chart of per-token contributions to the match score, coloured by column"----
token_contribution_plot(receipt)

## ----scoring------------------------------------------------------------------
pred <- matches |>
  group_by(match_id) |>
  summarise(
    base_id = id[source == "base"][1],
    truth   = actual_link[source == "target"][1],
    .groups = "drop"
  ) |>
  mutate(correct = base_id == truth)

recoverable <- sum(target_example$actual_link %in% base_example$id_base)

c(
  pairs     = nrow(pred),
  precision = round(mean(pred$correct, na.rm = TRUE), 3),
  recall    = round(sum(pred$correct, na.rm = TRUE) / recoverable, 3)
)

## ----sweep--------------------------------------------------------------------
sweep <- bind_rows(lapply(c(0.6, 0.7, 0.8, 0.9), function(th) {
  st <- strat
  st@threshold <- th
  m <- search_candidates(base_clean, target_example,
                         base_id = "id_base", target_id = "id_target",
                         strategy = st)
  p <- m |>
    group_by(match_id) |>
    summarise(base_id = id[source == "base"][1],
              truth   = actual_link[source == "target"][1],
              .groups = "drop") |>
    mutate(correct = base_id == truth)
  tibble(
    threshold = th,
    pairs     = nrow(p),
    precision = round(mean(p$correct, na.rm = TRUE), 3),
    recall    = round(sum(p$correct, na.rm = TRUE) / recoverable, 3)
  )
}))

sweep

## ----residuals----------------------------------------------------------------
unmatched_base   <- extract_unmatched(base_clean, "id_base", matches)
unmatched_target <- extract_unmatched(target_example, "id_target", matches)

nrow(unmatched_base)
nrow(unmatched_target)

## ----staged-------------------------------------------------------------------
staged <- multi_stage_search(
  base_clean, target_example,
  base_id   = "id_base",
  target_id = "id_target",
  strategies = list(
    exact = exact_strategy(
      Nachname ~ normalize_text() + word_tokens(min_nchar = 3),
      Vorname  ~ normalize_text() + word_tokens(min_nchar = 3),
      Ort      ~ normalize_text(),
      block_by = "Kreis"
    ),
    fuzzy = strat
  )
)

table(staged$stage)

