The basic workflow
samplyr separates a sampling design from the frame on
which it runs. You describe the design first, validate or inspect it,
and then execute it against one or more frames.
The smallest complete example is a simple random sample without replacement.
library(samplyr)
library(dplyr)
data(bfa_eas)
design <- sampling_design(title = "Burkina Faso EA sample") |>
draw(n = 100)
sample <- execute(design, bfa_eas, seed = 24)
sample |>
as.data.frame() |>
dplyr::select(ea_id, region, households, .weight) |>
head(4)
#> ea_id region households .weight
#> 1 5866 Centre-Nord 146 445.7
#> 2 24905 Nord 32 445.7
#> 3 5145 Centre-Nord 156 445.7
#> 4 32861 Est 22 445.7The frame has one row per enumeration area. The result keeps its frame columns and adds the design information needed for analysis.
.weight is the overall design weight. In a one-stage
sample it equals .weight_1. A multistage sample also
carries one weight column per stage and multiplies them into
.weight.
The design grammar
Six functions cover the ordinary workflow.
| Function | Role |
|---|---|
sampling_design() |
Start a reusable design |
stratify_by() |
Divide a stage into sampling strata |
cluster_by() |
Name the units selected as clusters |
draw() |
Choose the size and selection method |
add_stage() |
Start another sampling stage |
execute() |
Run the design against its frame or frames |
Column names are stored in the design and resolved when a frame is supplied. This lets the same design be validated and reused against compatible frame vintages.
stratified_design <- sampling_design(title = "Stratified EA sample") |>
stratify_by(region, alloc = "proportional") |>
draw(n = 260)
validate_frame(stratified_design, bfa_eas)validate_frame() returns invisibly when the required
columns and values are usable. It reports problems before selection
begins.
Stratified sampling
Stratification samples independently within groups. Here
n = 260 is a total allocated across regions in proportion
to their frame sizes.
stratified_sample <- execute(stratified_design, bfa_eas, seed = 25)
stratified_sample |>
count(region, name = "n_sampled")
#> # A tibble: 13 × 2
#> region n_sampled
#> <fct> <int>
#> 1 Boucle du Mouhoun 29
#> 2 Cascades 15
#> 3 Centre 23
#> 4 Centre-Est 17
#> 5 Centre-Nord 20
#> 6 Centre-Ouest 22
#> 7 Centre-Sud 9
#> 8 Est 32
#> 9 Hauts-Bassins 28
#> 10 Nord 17
#> 11 Plateau-Central 10
#> 12 Sahel 24
#> 13 Sud-Ouest 14If stratify_by() has no allocation rule, a scalar
n is interpreted per stratum. You can also pass a named
vector or a svyplan::n_alloc() result to
draw() when each stratum needs its own take.
Use equal allocation when comparable precision within each stratum is the goal. Use proportional allocation for a self-weighting element design when the other design features permit it. Neyman and cost-weighted allocations need prior variability or cost information and optimize the criterion supplied for that planning variable. They are not universal optima for every outcome and domain.
Sample-size bounds can protect small reporting domains.
bounded_design <- sampling_design() |>
stratify_by(region, alloc = "proportional") |>
draw(n = 260, min_n = 12, max_n = 30)
bounded_sample <- execute(bounded_design, bfa_eas, seed = 26)
bounded_sample |>
count(region, name = "n_sampled")
#> # A tibble: 13 × 2
#> region n_sampled
#> <fct> <int>
#> 1 Boucle du Mouhoun 29
#> 2 Cascades 14
#> 3 Centre 22
#> 4 Centre-Est 17
#> 5 Centre-Nord 20
#> 6 Centre-Ouest 21
#> 7 Centre-Sud 12
#> 8 Est 30
#> 9 Hauts-Bassins 28
#> 10 Nord 17
#> 11 Plateau-Central 12
#> 12 Sahel 24
#> 13 Sud-Ouest 14For without-replacement sampling, the population of a stratum remains
a hard upper bound. If a requested allocation cannot be reached,
execute() reports the affected pools and uses the
attainable take.
Cluster and PPS sampling
cluster_by() changes the sampling unit. The next example
selects enumeration areas with probability related to their household
counts.
pps_design <- sampling_design(title = "PPS EA sample") |>
cluster_by(ea_id) |>
draw(n = 80, method = "pps_brewer", mos = households)
pps_sample <- execute(pps_design, bfa_eas, seed = 27)
nrow(pps_sample)
#> [1] 80mos is the measure of size. A large measure gives a unit
a larger selection probability. If a resolved probability reaches one,
that unit is selected with certainty and contributes no variance at that
stage. Certainty at one stage does not make the final multistage weight
equal to one.
pps_brewer is one fixed-size PPS method. Method choice
also depends on the second-order information required for variance
estimation, whether a random sample size is acceptable, and whether
permanent random numbers are needed. The comparison is in
?selection-methods.
Continue inside selected units
add_stage() starts another selection within each
selected parent. For example, adding
add_stage() |> draw(n = 12) after the EA selection
declares a household draw within each selected EA. Execution needs
household rows, with EA identifiers linking them to their parents.
The next tutorial, vignette("three-stage-sampling"),
works through this process in full: commune and EA registers, household
listing, continuation, and survey export. It also explains the scope of
n at every stage.
Fractions, replacement, and ordering
draw() also accepts frac. Fixed-size
methods convert the fraction to an integer take, while Bernoulli
sampling keeps a random realized size.
fraction_sample <- sampling_design() |>
draw(frac = 0.01) |>
execute(bfa_eas, seed = 29)
nrow(fraction_sample)
#> [1] 446With-replacement methods may select the same population unit several
times. Their samples carry .draw_1, .draw_2,
and later-stage equivalents so every draw occurrence remains
distinct.
Systematic and sequential methods depend on frame order. Use
control when an explicit ordering is part of the design.
Their variance properties depend on that ordering, so an SRS variance
approximation for systematic selection need not be conservative.
Inspecting the result
A tbl_sample is a tibble with a design and an execution
receipt attached. Ordinary one-to-one joins and new analysis columns
preserve it. Removing or duplicating rows changes the realized sample
and prevents survey export.
summary(stratified_sample)
#> ── Sample Summary: Stratified EA sample ────────────────────────────────────────
#>
#> ℹ n = 260 of 44,570 | stages = 1/1 | seed = 25
#>
#> ── Stage 1 ─────────────────────────────────────────────────────────────────────
#> • srswor, by region (proportional)
#> • 13 strata: N_h 1,612-5,505, n_h 9-32, f_h 0.0056-0.0060
#>
#> ── Weights ─────────────────────────────────────────────────────────────────────
#> • Mean 171.42 [166.2, 179.11] | CV 0.01 | Kish DEFF 1 | n_eff 260frame_summary() reports what the execution resolved in
each selection pool.
frame_summary(stratified_sample, detail = "pool") |>
select(stage, region, N, n_target, n_realized) |>
slice_head(n = 6)
#> # A tibble: 6 × 5
#> stage region N n_target n_realized
#> <int> <fct> <dbl> <dbl> <dbl>
#> 1 1 Boucle du Mouhoun 5009 29 29
#> 2 1 Cascades 2508 15 15
#> 3 1 Centre 3888 23 23
#> 4 1 Centre-Est 2941 17 17
#> 5 1 Centre-Nord 3402 20 20
#> 6 1 Centre-Ouest 3723 22 22For domain estimates, convert the complete sample first and subset
the survey design afterwards. See
vignette("survey-analysis") for that workflow.
Choose your next step
The main learning path is:
- Get started: the design grammar and a first sample, covered here.
-
Select a three-stage sample:
vignette("three-stage-sampling")follows fieldwork from area registers to households and observations. -
Analyze the sample:
vignette("survey-analysis")covers outcome joins, domain estimates and variance choices, with optional two-phase and overlapping-frame examples.
Use the other articles when their task arises:
| Task | Article |
|---|---|
| Choose sizes and allocations before selection | vignette("survey-planning") |
| Coordinate new draws with permanent random numbers | vignette("sampling-coordination") |
| Schedule panels and refreshment cohorts | vignette("rotating-panels") |
| Save or replay a design | vignette("serialization") |
For a method or inference lookup, use
?selection-methods. Consult
vignette("design-semantics") for the underlying contracts
and vignette("validation") for simulation diagnostics.
A compact checklist
- Make sure one row represents the unit selected at the current stage.
- Declare strata, clusters, and selection methods in their sampling order.
- Validate the design against the intended frame vintage.
- Use a recorded seed when the selection must be reproducible.
- Keep the returned design columns unchanged.
- Archive the executed sample and its frame provenance.
Continue with vignette("three-stage-sampling"), or go
directly to vignette("survey-analysis") if you already have
a selected sample.