
Pseudo-weights for a non-probability sample against a reference
Source:R/adjust-pseudoweight.R
step_pseudoweight.RdFor a non-probability sample (opt-in panel, volunteer or river sample) with no
design weights, step_pseudoweight() estimates each unit's participation
propensity \(\hat p\) against a probability reference_sample() and assigns
the pseudo-weight \((1 - \hat{p})/\hat{p}\) (the participation odds;
the adjusted logistic propensity of Wang, Valliant and Li 2021, after Elliott and
Valliant 2017), which inflates each unit to the population. Their sum estimates
the reference's estimated population size – it is unbiased for it, not equal to
it, and varies from sample to sample like any other estimator. It stacks the non-probability sample and the
reference internally (the participation indicator and the two samples' weights
are built for you), fits the propensity, and returns the pseudo-weight on the
non-probability units only; the reference is used to train the model and then
dropped.
Usage
step_pseudoweight(
spec,
reference,
formula,
engine = c("logit", "tree", "forest", "boost"),
num_classes = NULL,
by = NULL,
crossfit = NULL,
crossfit_seed = NULL,
id = NULL
)Arguments
- spec
a non-probability
weighting_spec.- reference
a
reference_sample()(the probability reference with its design weights). Pass the reference's replicate weights throughreference_sample(replicates = )to propagate its sampling variance through the recipe-aware bootstrap: each replicate refits the propensity from the paired reference replicate. Without them the reference is treated as fixed, so the bootstrap reflects only the variability of the non-probability sample (which it resamples as a with-replacement sample of units, a slightly conservative approximation when that sample is a large fraction of the population).- formula
one-sided formula of the covariates shared by both samples, e.g.
~ sex + age + region.- engine
propensity learner:
"logit"(default),"tree","forest"or"boost".- num_classes
NULL (default, direct
1/pi) or an integer: group the fitted propensities into that many quantile classes and use the class-average pseudo-weight, which is more robust to a misspecified model.- by
NULL (default), or a single column name: fit one participation model per domain, on that domain's units of both samples and on nothing else. The
referencemust carry the same domain column, and is split by it, so the pseudo-weights of a domain sum to that domain's reference total rather than to the national one – which is what lets a following domain-partitioned calibration start from a coherent input weight. Use it when the participation mechanism differs across domains (a covariate whose effect changes sign by region is the clear case), where a single additive national model misses the domain totals in both directions – measured on three domains with the slope changing sign:~ dom + xlanded at 4,258 / 3,530 / 4,803 against a truth of 4,022 / 4,033 / 3,945.For
engine = "logit"this is the fully interacted national model,~ dom * (...), and gives the same weights to numerical precision – not a different estimator, but the practicable way to fit it: the interactions are never written out, a domain without enough units on either side is named instead of quietly degrading the whole fit, and the tree, forest and boost engines have no interaction syntax at all, so there segmenting is the only route. Each domain needs enough units on each side to fit its own model; those that do not are reported by name.- crossfit, crossfit_seed
optional K-fold cross-fitting of the propensity (recommended for the flexible learners), and its seed.
- id
optional stable step id.
Details
The recipe must be a non-probability spec: weighting_spec(..., nonprob = TRUE). This step is the inverse-propensity (IPW) route; you can instead, or
additionally, calibrate to a reference_sample() with step_calibrate() /
step_model_calibration() (mass imputation / model-based), and combining both
gives the doubly robust estimator.
References
Wang, L., Valliant, R. and Li, Y. (2021). Adjusted logistic propensity weighting methods for population inference using nonprobability volunteer-based epidemiologic cohorts. Statistics in Medicine 40(24), 5237-5250. doi:10.1002/sim.9122
Elliott, M. R. and Valliant, R. (2017). Inference for non-probability samples. Statistical Science 32(2), 249-264.
See also
reference_sample(), step_calibrate(), step_model_calibration()
Other weighting steps:
step_assert(),
step_calibrate(),
step_cre(),
step_drop_ineligible(),
step_model_calibration(),
step_nonresponse(),
step_nr_sensitivity(),
step_rescale(),
step_round(),
step_select_within(),
step_subsample(),
step_trim(),
step_trim_calibrated(),
step_trim_weights(),
step_unknown_eligibility()
Examples
set.seed(1)
N <- nrow(population)
# a biased volunteer sample (men over-participate) and a probability reference
vol <- population[rbinom(N, 1, plogis(-2 + 0.9 * (population$sex == "M"))) == 1,
c("region", "sex", "income")]
ref <- population[sample(N, 600), c("region", "sex")]
ref$d <- N / 600 # its design weights
fit <- weighting_spec(vol, base_weights = NULL, nonprob = TRUE) |>
step_pseudoweight(reference = reference_sample(ref, "d"),
formula = ~ region + sex, engine = "logit") |>
prep()
# the pseudo-weighted mean corrects the volunteer bias
c(naive = mean(vol$income),
pseudo = weighted.mean(vol$income, fit$final_weight),
truth = mean(population$income))
#> naive pseudo truth
#> 19353.58 18936.79 19298.11