write_design() saves a sampling design (or the design carried by an
executed sample) to a human-readable, samplyr-native JSON file.
read_design() reads it back into a sampling_design that executes
identically to the original.
The file format is versioned JSON and diffable in version control. It stores the complete design specification (stages, stratification, clustering, draw settings, including per-stratum vectors and data frames), never the frame data itself.
Arguments
- x
A
sampling_design, or atbl_sample(the stored design is saved along with an execution receipt).- path
File path to write to. Conventionally with a
.jsonextension.- frame
Optional sampling frame (data frame). When supplied, a fingerprint of the frame (name, dimensions, column types, content hash) is stored so the frame can be verified later. The frame data is never written. The content hash covers column names, column values, and row order; it does not depend on the class of the data frame (tibble or data frame) or on the order of its columns.
- pretty
Whether to pretty-print the JSON. Defaults to
TRUEfor files andFALSEfordesign_json().- file
A path to a local file, or a JSON string produced by
design_json(). URLs are refused:read_design()never fetches remote files. Download the file first and read the local copy.
Value
write_design() returns x invisibly. read_design() returns
a sampling_design; any frame information and execution receipt in
the file are attached as the "frame_info" and "execution"
attributes.
Details
Lifecycle
The serialization interface and its samplyr-native file format are experimental. They support samplyr persistence and replay; they are not a finalized cross-tool survey-sampling interchange standard. The structure may change while that separate specification is developed.
Frame information
Designs are frame-independent, and so are design files. Two derived blocks describe the frame without embedding it:
Requirements (always written): the columns each stage needs (stratification, clustering,
mos,prn,aux, and control variables), so any candidate frame can be checked before execution withvalidate_frame().Fingerprint (written when
frameis supplied): portable dimensions and column types inframe, plus the R source label, native classes, and content hash intools.samplyr. Together these can verify that a frame is the exact one the design was built against without putting R details in the common metadata.
Execution receipts
When x is a tbl_sample, the file additionally records an execution
receipt: every argument of the execute() call that affects the
result (seed, executed stages, panels, reps, and the per
replicate seeds), the execution-time RNG configuration and package
versions, plus the number of selected units and the execution timestamp.
Together with the frame fingerprint this makes a single-call sample
reproducible when the same frame, compatible package implementations, and
any recorded custom methods are available. Running
replay_design(read_design(path), frame) then obtains the same
tbl_sample – the same rows in the same order, including .panel and
.replicate assignments – with only the execution timestamp differing.
The sampled rows themselves are not stored; use a data format (CSV,
parquet) for those.
Receipts describe one execute() call. A sample built by several
calls (a stage continuation or a multi-phase pipeline) is flagged as
chained in the receipt and write_design() warns: replaying the
final call alone cannot reproduce it, so save and replay each phase
or stage batch separately. A sample whose rows or design columns were
modified after execution is likewise flagged (modified); its
receipt describes the original execution, not the modified object.
Control expressions
draw(control = ...) expressions are stored as declarative JSON terms,
not R code. Each term records an ordering type ("ascending",
"descending", or "serpentine") and its variables. Only bare column
names, dplyr::desc(), and serp() can be represented;
write_design() errors on anything else.
Declarative and implementation metadata
The design, frame, and execution blocks use declarative JSON rather
than R expressions. Selection methods carry samplyr's internal semantic
descriptor. The tools.samplyr block records exact method names, R classes,
the R-derived frame hash, and execution environment needed to rebuild and
replay the native object. These descriptors are not a finalized external
method vocabulary.
See also
replay_design() for reproducing a sample from its receipt,
design_json() for in-memory JSON, validate_frame() for
checking a frame against a design, get_design() for extracting the
design from a sample.
Examples
design <- sampling_design(title = "Household Survey") |>
stratify_by(region, alloc = "proportional") |>
draw(n = 200, method = "systematic", control = c(province, ea_id))
path <- tempfile(fileext = ".json")
write_design(design, path, frame = bfa_eas)
restored <- read_design(path)
restored
#> ── Sampling Design: Household Survey ───────────────────────────────────────────
#>
#> ℹ 1 stage
#>
#> ── Stage 1 ─────────────────────────────────────────────────────────────────────
#> • Strata: region (proportional)
#> • Draw: n = 200 (total), method = systematic, control = c(province, ea_id)
#>
# The restored design executes identically
s1 <- execute(design, bfa_eas, seed = 42)
s2 <- execute(restored, bfa_eas, seed = 42)
identical(s1$ea_id, s2$ea_id)
#> [1] TRUE
# Saving an executed sample records a reproducibility receipt
write_design(s1, path, frame = bfa_eas)
attr(read_design(path), "execution")$seed
#> [1] 42
# Replay the receipt to reproduce the sample exactly
s3 <- replay_design(read_design(path), bfa_eas)
identical(s3$ea_id, s1$ea_id)
#> [1] TRUE
unlink(path)