Skip to contents

Re-executes a design exactly as recorded in its execution receipt, passing the stored seed, stages, panels, and reps back to execute(). This avoids reconstructing those arguments by hand from the receipt fields.

Usage

replay_design(
  x,
  frame,
  fingerprint = c("error", "warn", "inform", "ignore"),
  links = NULL,
  targets = NULL
)

Arguments

x

A sampling_design carrying an execution receipt, as returned by read_design() for a file written from a tbl_sample. A tbl_sample is 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.

fingerprint

How to respond when frame differs from the fingerprint stored in the design file: "error" (default), "warn", "inform", or "ignore".

The link table and the target register, for a shared-weight sample only. Both are required there and refused elsewhere, since accepting them where nothing uses them would return an untransformed sample to someone who believes a transformation was re-applied. Supply the tables the transformation was built from; the result is checked against the integrity the file records.

Value

The replayed tbl_sample, or the rebuilt frame_stack for a frame collection.

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 restores the caller's RNG state. It warns when recorded R or package versions differ.

Receipts record a single execute() call. A sample produced by several calls (a stage continuation or a multi-phase pipeline) carries a chained flag in its receipt and cannot be replayed. Save and replay each phase or stage batch separately.

A sample carrying shared weights replays in two steps: the source selection is re-executed against frame, then the recorded transformation is re-applied to the links and targets given here. Those two are not in the file, by design, so they cannot be checked before use; the file instead records what the source and the result hashed to, and replay is checked against both. A source that does not reproduce means frame is wrong, and a result that does not means links or targets is. Both a file and a live shared sample are accepted.

A frame collection replays component by component and is stacked again afterwards, so frame is a list named by component. Both a collection read back from a file and a live frame_stack are accepted. Every component is checked before any of them runs, since replaying re-executes each selection. The collection is rebuilt through stack_frames() rather than by restoring its attributes, so a register that has stopped carrying the membership column, or whose key is no longer unique, is reported as that.

For a design using 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 from the recorded one, since identical registry metadata does not imply the same selections. The fingerprint normalizes formatting and comments and does not cover the function's enclosing environment: a registered function that reads from its environment can change behavior without changing its fingerprint.

A panelized receipt carries a panel assignment record, and it is read before any panel argument is decoded from it. A record naming an assignment algorithm or a schema version this samplyr does not know is samplyr_error_panel_record_unsupported rather than a replay under the current law. A record that does not carry what the version it states requires, or that is not a set of named fields at all, is samplyr_error_panel_record_malformed rather than a repaired one: the assignment stage decides what the assignment units are, so filling in a missing one would replay a different assignment of the same sample.

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 reported by position and recorded label, so a mismatch names the register that moved. After replaying, the row count is checked against the receipt's n_selected as a final consistency check.

A sample drawn from one register per stage is replayed by passing those registers back as a list, in the same order. The receipt records how many frames the call was given, so supplying the wrong number is samplyr_error_replay_frame_count rather than a sample drawn from the wrong pools.

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

unlink(path)