Crosses the levels of the named factors, counts how many rows fall in each cell, and labels every cell of the crossing as missing, under-represented, balanced, or over-represented. This is what surfaces a nesting or aliasing problem before anything is modelled.
Value
A tibble::tibble with one row per cell of the full crossing:
the factor columns (as character), then n (rows observed),
expected, delta (n - expected) and status, one of "missing"
(n == 0), "under", "ok" or "over".
Details
A design described as "all saddles crossed with all pads" can turn out to
be nothing of the sort: one pad may only ever have been used with one
saddle, in which case the two factors are aliased and their effects are
not separately estimable — a fact no model summary will state out loud.
Counting the cells of the full crossing shows it immediately: a factor
nested inside another leaves whole blocks of the crossing at n == 0.
Levels come from levels() for a factor column and from the sorted
unique non-NA values otherwise. Sorting uses method = "radix", which
forces C-locale collation, so the row order of the result does not depend
on the machine's locale. The crossing is generated by
tidyr::expand_grid(), so the first factor varies slowest and the row
order is the natural nesting order.
expected sets the replicate count a balanced cell should hold. Left
NULL, it is the most common non-zero cell count — the design's own idea
of a full cell — with ties broken towards the larger count, so a tie errs
towards reporting cells as under-represented rather than as balanced.
Rows with NA in any crossing factor cannot be placed in a cell. They
are dropped and a warning names how many, because dropping them silently
would understate the gaps.
See also
pr_factor_contract() for the level sets being crossed,
pr_design_table() for building x from a pr_dataset.
Other provenance functions:
pr_factor_contract(),
pr_lock_table(),
pr_validate_summary(),
pr_verify_lock()
Examples
design <- data.frame(
Saddle = c("K", "K", "K", "S", "S", "W"),
Pad = c("F", "K", "K", "F", "F", "W")
)
gaps <- pr_design_gaps(design, c("Saddle", "Pad"))
gaps
#> # A tibble: 9 × 6
#> Saddle Pad n expected delta status
#> <chr> <chr> <int> <int> <int> <chr>
#> 1 K F 1 2 -1 under
#> 2 K K 2 2 0 ok
#> 3 K W 0 2 -2 missing
#> 4 S F 2 2 0 ok
#> 5 S K 0 2 -2 missing
#> 6 S W 0 2 -2 missing
#> 7 W F 0 2 -2 missing
#> 8 W K 0 2 -2 missing
#> 9 W W 1 2 -1 under
# Pad is nested within Saddle, not crossed with it:
sum(gaps$status == "missing")
#> [1] 5
# With an explicit replicate expectation:
pr_design_gaps(design, c("Saddle", "Pad"), expected = 2)
#> # A tibble: 9 × 6
#> Saddle Pad n expected delta status
#> <chr> <chr> <int> <int> <int> <chr>
#> 1 K F 1 2 -1 under
#> 2 K K 2 2 0 ok
#> 3 K W 0 2 -2 missing
#> 4 S F 2 2 0 ok
#> 5 S K 0 2 -2 missing
#> 6 S W 0 2 -2 missing
#> 7 W F 0 2 -2 missing
#> 8 W K 0 2 -2 missing
#> 9 W W 1 2 -1 under