Skip to contents

Register a user-defined sampling method so it can be used through unequal_prob_wor(), unequal_prob_wr(), or balanced_wor() and their associated generics.

Usage

register_method(
  name,
  type = c("wor", "wr", "balanced"),
  sample_fn,
  joint_fn = NULL,
  fixed_size = TRUE,
  variance_family = NULL,
  supports_prn = NULL,
  supports_aux = NULL,
  supports_strata = NULL,
  supports_spread = NULL,
  probabilities = c("unknown", "exact", "approximate")
)

Arguments

name

A unique method name (character string). Must not collide with a built-in method name.

type

"wor" (without replacement), "wr" (with replacement), or "balanced" (balanced without replacement, dispatched through balanced_wor()).

sample_fn

A function that draws a sample. See Contracts below.

joint_fn

An optional function that computes joint inclusion probabilities (WOR) or joint expected hits (WR). If NULL, joint_inclusion_prob() / joint_expected_hits() will error for this method.

fixed_size

Does this method always produce exactly n units? Must be TRUE for type = "wr".

variance_family

Optional declaration of how design-based variance should be estimated for this method, for downstream packages that export designs for variance estimation. One of "srs", "pps_brewer", "poisson", "wr", or "unsupported"; see Variance families below. NULL (the default) means undeclared: consumers fall back on inferring a treatment from type and fixed_size.

supports_prn

Does this method support permanent random numbers for sample coordination? Set to TRUE or FALSE for "wor" and "wr" methods. NULL (the default) resolves to FALSE. Leave NULL for "balanced" methods; balanced_wor() has no prn argument.

supports_aux

Does this method use auxiliary balancing variables? Set to TRUE or FALSE for type = "balanced". NULL (the default) resolves to TRUE for balanced methods and FALSE otherwise. Set it to FALSE for spread-only (spatially balanced) methods such as the local pivotal method, so that passing aux to balanced_wor() is an error instead of being silently ignored. Leave NULL for "wor" and "wr" methods.

supports_strata

Does this method support stratified balanced sampling? Set to TRUE or FALSE for type = "balanced". NULL (the default) resolves to FALSE. When FALSE, passing strata to balanced_wor() with this method is an error, and sample_fn does not need a strata argument. Leave NULL for "wor" and "wr" methods.

supports_spread

Does this method support spatial spreading (well-spread / spatially balanced sampling)? Set to TRUE or FALSE for type = "balanced". NULL (the default) resolves to FALSE. When FALSE, passing spread to balanced_wor() with this method is an error, and sample_fn does not need a spread argument. Leave NULL for "wor" and "wr" methods.

probabilities

Where the method sits in the first-order probability taxonomy, for downstream packages that weight or record per-unit selection probabilities:

  • "exact": the true first-order inclusion probabilities (types "wor" and "balanced") or expected hits (type "wr") equal the pik or hits vector passed to sample_fn, as for Sampford or the cube method.

  • "approximate": pik or hits is the method's first-order target, achieved up to a documented approximation, as for Pareto or sequential Poisson order sampling. Design weights 1/pik remain standard practice.

  • "unknown" (the default): pik or hits is an input weight or preference only, so the corresponding first-order quantities are not known. The toy WOR sampler in the examples is such a method: successive sampling with prob = pik does not yield inclusion probabilities equal to pik, so its design weights 1/pik would be systematically biased, not merely noisy. (The same draw with replacement does honor expected hits, so a multinomial-style type = "wr" method declares "exact".)

The default is deliberately strict: if you have not established which tier your method is in, its selection probabilities are unknown, and downstream packages that weight estimation by 1/pik may refuse to draw with it rather than produce biased weights. Sampling through sondage itself is unaffected: the declaration describes the method, it never disables it. Like variance_family, the declaration is an assertion by the method author that sondage cannot verify; the package vignette shows how to check a first-order contract by simulation.

Value

Invisible NULL, called for its side effect.

Details

Registrations last for the current R session. Registering an existing custom method name is an error; call unregister_method() first when deliberately replacing a method.

Contracts

sample_fn(pik, n = NULL, prn = NULL, ...) (type "wor")

pik

Inclusion probabilities, numeric vector of length N.

n

Target sample size, equal to round(sum(pik)).

prn

Permanent random numbers (numeric vector length N, values in (0,1)), or NULL. Supplying prn is an error when the method is registered with supports_prn = FALSE, and sample_fn is not called.

Returns

Integer vector of selected unit indices (1-based). Indices are distinct and have length n for fixed-size methods, or varying length for random-size methods. The dispatcher validates the type, range, size, and replacement rules before constructing the sample object.

sample_fn(hits, n = NULL, prn = NULL, ...) (type "wr")

hits

Expected hits, numeric vector of length N.

n

Target sample size, equal to round(sum(hits)).

prn

Permanent random numbers (numeric vector length N, values in (0,1)), or NULL. Supplying prn is an error when the method is registered with supports_prn = FALSE, and sample_fn is not called.

Returns

Integer vector of n selected unit indices (1-based), with possible repeats. The dispatcher validates the type, range, size, and replacement rules before constructing the sample object.

sample_fn(pik, n = NULL, aux = NULL, ...) (type "balanced")

pik

Inclusion probabilities, numeric vector of length N.

n

Target sample size (integer when fixed_size, otherwise sum(pik)).

aux

Auxiliary balancing matrix (N x p, double), or NULL. Passed through as supplied to balanced_wor() after validation; the sample-size constraint is not prepended, so add it yourself if your algorithm needs it (e.g. cbind(pik, aux)). Methods registered with supports_aux = FALSE always receive aux = NULL.

strata

Only when registered with supports_strata = TRUE and the caller supplies strata: an integer vector (length N) of dense stratum labels 1:H. Declare it as strata = NULL in your function signature.

spread

Only when registered with supports_spread = TRUE and the caller supplies spread: a numeric matrix (N x d, double) of spatial coordinates (or other spreading variables). Declare it as spread = NULL in your function signature.

Returns

Integer vector of distinct selected unit indices (1-based). The dispatcher validates the returned indices.

joint_fn(pik, sample_idx = NULL, ...) (optional; types "wor" and "balanced")

pik

Inclusion probabilities, numeric vector of length N.

eps

If the function explicitly declares an eps formal, it receives the value supplied to joint_inclusion_prob().

sample_idx

When non-NULL, an integer vector of sampled unit indices. Return only the submatrix for these units.

Returns

Symmetric matrix of joint inclusion probabilities (N x N when sample_idx is NULL, length(sample_idx) x length(sample_idx) otherwise). The dispatcher validates that the matrix has the required dimensions and contains finite, symmetric numeric values.

joint_fn(hits, sample_idx = NULL, ...) (optional; type "wr")

hits

Expected hits, numeric vector of length N, renormalized to sum exactly to the integer sample size n.

nsim

If the function explicitly declares an nsim formal, it receives the value supplied to joint_expected_hits().

sample_idx

When non-NULL, an integer vector of distinct sampled unit indices. Return only the submatrix for these units.

Returns

Symmetric matrix of joint expected hits (N x N when sample_idx is NULL, length(sample_idx) x length(sample_idx) otherwise). The dispatcher validates that the matrix has the required dimensions and contains finite, symmetric numeric values.

Variance families

variance_family names the estimator treatment a variance consumer (such as a survey-export package) should apply to samples drawn with this method. Selection metadata alone cannot determine it: a fixed-size WOR method may need Brewer's unequal-probability approximation or an SRS-style variance, and for a random-size WOR method no safe inference exists at all, because a Poisson-type method (independent selections) and a correlated random-size scheme need different estimators.

"srs"

Equal-probability fixed-size WOR. SRS-style variance with a finite population correction. Requires fixed_size = TRUE.

"pps_brewer"

Fixed-size unequal-probability WOR. Brewer's approximation from the marginal inclusion probabilities. Requires fixed_size = TRUE.

"poisson"

Random-size WOR with independent selections (Poisson-type). Exact Poisson linearization. Requires type = "wor" and fixed_size = FALSE.

"wr"

With-replacement (or minimum-replacement) selection. Hansen-Hurwitz variance, no finite population correction. Requires type = "wr".

"unsupported"

No linearization treatment is valid; consumers should refuse to linearize and point to replicate methods instead. The correct declaration for correlated random-size schemes. Always allowed.

Balanced methods allow only "pps_brewer" or "unsupported": balancing constraints couple selections across units, so "poisson" can never hold for them.

The declaration is an assertion by the method author, not something sondage can verify; "poisson" in particular asserts that units are selected independently, and a wrong declaration produces silently wrong variance estimates for every user of the method. The package vignette (vignette("custom-methods", package = "sondage")) shows how to check a declared family by simulation.

Examples

# Register a toy random sampler. Successive sampling with
# prob = pik does not give first-order inclusion probabilities
# equal to pik, so its probabilities stay "unknown" (the default).
my_sampler <- function(pik, n = NULL, prn = NULL, ...) {
  sample.int(length(pik), size = n, prob = pik)
}
register_method(
  "toy",
  type = "wor",
  sample_fn = my_sampler
)
s <- unequal_prob_wor(c(0.3, 0.3, 0.4), method = "toy")
s$method
#> [1] "toy"

# Register a toy balanced sampler (ignores aux, keeps size fixed)
my_balanced <- function(pik, n = NULL, aux = NULL, ...) {
  sample.int(length(pik), size = n, prob = pik)
}
register_method("toy_bal", type = "balanced", sample_fn = my_balanced)
s <- balanced_wor(c(0.3, 0.3, 0.4), method = "toy_bal")
s$method
#> [1] "toy_bal"

# Clean up
unregister_method("toy")
unregister_method("toy_bal")