Re-executes a design exactly as recorded in its execution receipt,
passing the stored seed, stages, panels, and reps back to
execute().
Usage
replay_design(
x,
frame,
...,
fingerprint = c("error", "warn", "inform", "ignore"),
links = NULL,
targets = NULL
)Arguments
- x
A
sampling_designcarrying an execution receipt, as returned byread_design()for a file written from atbl_sample. Atbl_sampleis also accepted and is replayed from its own metadata, which is useful for verifying reproducibility without a file round trip.- frame
The sampling frame the receipt refers to: a data frame for a one-frame call, or the ordered list of stage frames for a call that supplied one register per stage. For a sample built by several calls, one element per call that read frames, in the form
frametakes inwrite_design().- ...
Must be empty. Arguments after it are matched by exact name.
- fingerprint
How to respond when
framediffers from the fingerprint stored in the design file:"error"(default),"warn","inform", or"ignore".- links, targets
The link table and the target register, for a shared-weight sample only. Both are required there and refused elsewhere, so a sample is never returned untransformed to a caller expecting a transformation. The result is checked against the integrity the file records.
Value
The replayed tbl_sample, or the rebuilt frame_stack for a
frame collection. When the receipt carries a frame digest, the replay
captures its own digest in the same mode ("summary" or "full") and
compares pool sizes, targets, expected sizes and chances, plus chance
quantiles or every unit's chance. A difference warns with
samplyr_warning_replay_digest. That catches
a frame saved without its fingerprint, and a version of samplyr or its
dependencies that resolves the design differently. The comparison is
skipped under fingerprint = "ignore" and once a frame difference has
been reported.
Details
Given the same frame and compatible recorded implementations, the replayed
sample is identical to the original: the same rows in the same order, the
same weights and design columns, and the same .panel and .replicate
assignments. Only the execution timestamp differs. Replay restores the
execution-time RNG configuration and then the caller's RNG state. It
warns when recorded R or package versions differ.
When the design was saved with a frame fingerprint, frame is compared
against it before replaying. A differing frame still yields a valid
sample, but not the recorded one, so the default is to error. Several
frames are compared one by one, and a mismatch names the register by
position and recorded label. A wrong number of frames is
samplyr_error_replay_frame_count. After replaying, the row count is
checked against the receipt's n_selected.
A chained sample, produced by several execute() calls, is replayed
call by call, each under its own seed, stages and RNG kind. The first
call and each continuation read the frames given here, a new phase reads
the phase replayed before it, and a wave reads its replayed master.
Inherited panels and replicates are carried rather than declared again.
The fingerprints cover every call's frames, and the row count is checked
after each call. An earlier call run without a seed is
samplyr_error_receipt_no_seed. When a new phase was drawn from a sample
modified after its execution, the record starts at that phase, and its
frame must be the modified sample as the tbl_sample it was
(samplyr_error_replay_phase_frame otherwise).
A chained receipt that does not record its earlier calls (a continuation
of a modified sample, or a file written before receipts recorded earlier
calls) is refused with class samplyr_error_receipt_chained. The refusal
carries the final call's seed and stages as fields and gives the
recipe. Rebuild the sample that call ran on by replaying its own receipt,
or keep it when it was modified, since no receipt rebuilds a modified
sample. Then run
execute(earlier, frame, seed = seed, stages = stages) for a continuation,
or execute(design, earlier, seed = seed) for a new phase. That
reproduces the sample exactly under the same RNG kind, which the refusal
names since a direct execute() does not set it.
A shared-weight sample re-executes the source selection against frame,
then re-applies the recorded transformation to links and targets.
Those are not in the file, so replay checks the source and the result
against the hashes the file records. A source that does not reproduce
means frame is wrong, and a result that does not means links or
targets is.
A frame collection replays each component against its register, with
frame a list named by component. Every component is checked before any
runs. The results are stacked through stack_frames() rather than by
restoring attributes, so a register that has lost the membership column,
or whose key is no longer unique, is reported as that. Shared-weight
samples and collections are accepted both from a file and live.
For a registered custom method, the receipt records a fingerprint of the
implementation (the formals and body of the registered sample_fn and
joint_fn). Replay refuses when the currently registered function
differs, since identical registry metadata does not imply the same
selections. The fingerprint normalizes formatting and comments and does
not cover the enclosing environment, so a registered function that reads
from its environment can change behavior without changing its
fingerprint.
A panel assignment record naming an algorithm or schema version this
samplyr does not know is samplyr_error_panel_record_unsupported. One
that lacks what its stated version requires, or is not a set of named
fields, is samplyr_error_panel_record_malformed. Neither is replayed
under the current law or repaired, since the assignment stage decides the
assignment units and filling in a missing one would replay a different
assignment.
vignette("serialization") works through these cases with examples.
See also
write_design() and read_design() for the receipt
round trip, validate_frame() for checking a frame against a
design before executing.
Other serialization:
as.list.sampling_design(),
design_json(),
write_design()
Examples
sample <- sampling_design() |>
stratify_by(region) |>
draw(n = 100) |>
execute(bfa_eas, seed = 11, panels = 4)
path <- tempfile(fileext = ".json")
write_design(sample, path, frame = bfa_eas)
replayed <- replay_design(read_design(path), bfa_eas)
identical(replayed$ea_id, sample$ea_id)
#> [1] TRUE
identical(replayed$.panel, sample$.panel)
#> [1] TRUE
# One register per stage replays from the same ordered list
regions <- dplyr::distinct(bfa_eas, region)
two_stage <- sampling_design() |>
add_stage(label = "Regions") |>
cluster_by(region) |>
draw(n = 3) |>
add_stage(label = "EAs") |>
draw(n = 5)
registers <- execute(two_stage, regions, bfa_eas, seed = 4)
write_design(registers, path, frame = list(regions, bfa_eas))
identical(
replay_design(read_design(path), list(regions, bfa_eas))$ea_id,
registers$ea_id
)
#> [1] TRUE
# A second phase replays both calls from the first phase's frame
phase1 <- sampling_design() |>
stratify_by(region) |>
draw(n = 300) |>
execute(bfa_eas, seed = 7)
phase2 <- sampling_design() |>
stratify_by(urban_rural) |>
draw(n = 60) |>
execute(phase1, seed = 8)
write_design(phase2, path, frame = bfa_eas)
identical(replay_design(read_design(path), bfa_eas)$ea_id, phase2$ea_id)
#> [1] TRUE
unlink(path)