Draws teams that were never in the data and, for each simulated team and
each card, a called sighting category given the card's true one. It
is the generative counterpart of sdt_fit_triage_error(): where that fits
the rows of the confusion matrix, this replays them.
Usage
sdt_simulate_triage(
model,
n_groups = 20L,
cards = NULL,
seed = NULL,
new_teams = TRUE,
nsim = 1L,
team_effects = TRUE
)Arguments
- model
An
sdt_triage_error_modelfromsdt_fit_triage_error().- n_groups
Number of simulated teams per replicate.
- cards
Cards to deal to each team.
NULLuses every card in the fitted frame; anything passed must be a subset of them.- seed
Optional integer seed, applied with
withr::local_seed().- new_teams
If
TRUE(default), redraw the team and session effects, so every simulated team is new. IfFALSE, reuse the fitted conditional modes of the firstn_groupsfitted teams, which is a posterior-predictive check rather than a generator.- nsim
Number of replicates. Replicates are stacked and carry a
.replicatecolumn;sim_groupis unique across the whole result.- team_effects
If
FALSE, simulate from the null fits – the same cells with(1 | group)removed. This is the counterfactual that shows what the team term is doing, and it is a different model rather than the same one with the draw switched off.
Value
An S3 object of class sdt_simulated_triage, a
tibble with .replicate, sim_group, card,
triage, called_triage, and the hit, over and under logicals.
Carries the model, the call, a draws attribute holding the random
effects used, and a gaps attribute counting the cells left NA.
Details
Each simulated team gets its own random effect per cell, drawn from
N(0, sd_group), plus a session effect from N(0, sd_block). For a card
of true category k the call is then a two-step draw: correct with
probability plogis(card effect + team effect + session effect) from the
hit cell, and otherwise one of the two wrong categories from the split
cell. That is the confusion-matrix row, redrawn for a new team.
What comes back as NA
A cell that was never fitted is never guessed. If a category's hit cell
is missing, every card of that category returns NA; if only its split
cell is missing, the correct calls stand and the errors return NA. A card
with no coefficient in a cell – a card the split part never saw, because
no team miscalled it – returns NA for the same reason. Every one of
these is counted in the result's gaps attribute and warned about once.
What is not reproduced
The two parts are drawn independently, so a simulated team's accuracy and
its error direction are uncorrelated. That is the one parameter the
decomposition gives up, and joint = TRUE in sdt_fit_triage_error()
measures it. Card-to-card dependence within a team – a team that has just
over-triaged three greens in a row – is absent as well: cards are drawn
independently given the team.
Examples
set.seed(1)
cards <- sprintf("c%02d", seq_len(12))
truth <- rep(c("red", "yellow", "green"), each = 4)
d <- expand.grid(card = cards, group_id = sprintf("g%02d", seq_len(20)),
stringsAsFactors = FALSE)
d$session_id <- ifelse(d$group_id < "g11", "s1", "s2")
d$triage <- truth[match(d$card, cards)]
b <- stats::rnorm(20, sd = 1)
p <- stats::plogis(1 + b[match(d$group_id, unique(d$group_id))])
hit <- stats::runif(nrow(d)) < p
wrong <- vapply(seq_len(nrow(d)), function(i) {
sample(setdiff(sdt_triage_levels(), d$triage[[i]]), 1)
}, character(1))
d$called_triage <- ifelse(hit, d$triage, wrong)
if (requireNamespace("lme4", quietly = TRUE)) {
fit <- sdt_fit_triage_error(d, verbose = FALSE)
sdt_simulate_triage(fit, n_groups = 5, seed = 1)
}
#> Warning: ! 1 cell fitted a zero team variance: "green.split".
#> ✖ Simulated teams will be identical there.
#> ℹ That is a finding about the cell, not a failure of the fit.
#> <sdt_simulated_triage> 5 new teams x 12 cards in 1 replicate
#> hit 0.717 over 0.083 under 0.200
#> # A tibble: 60 × 8
#> .replicate sim_group card triage called_triage hit over under
#> * <int> <chr> <chr> <chr> <chr> <lgl> <lgl> <lgl>
#> 1 1 g0001 c01 red red TRUE FALSE FALSE
#> 2 1 g0001 c02 red red TRUE FALSE FALSE
#> 3 1 g0001 c03 red yellow FALSE FALSE TRUE
#> 4 1 g0001 c04 red red TRUE FALSE FALSE
#> 5 1 g0001 c05 yellow red FALSE TRUE FALSE
#> 6 1 g0001 c06 yellow green FALSE FALSE TRUE
#> 7 1 g0001 c07 yellow green FALSE FALSE TRUE
#> 8 1 g0001 c08 yellow green FALSE FALSE TRUE
#> 9 1 g0001 c09 green green TRUE FALSE FALSE
#> 10 1 g0001 c10 green green TRUE FALSE FALSE
#> # ℹ 50 more rows