knitr::opts_chunk$set(collapse = TRUE, comment = "#>") library(weightflow)
New here? This is the 15-minute tour: what problem
weightflowsolves and the shortest recipe that produces analysis weights. For the statistical reasoning behind each adjustment, read Staged survey weighting: the adjustment logic.
Every survey organization has weighting scripts. They grow over time, absorb new adjustments, and eventually become difficult to understand, maintain and reproduce. Two analysts can implement the same weighting strategy in different ways, which turns audits, updates and methodological reviews into archaeology.
The weights themselves are rarely the hard part. The hard part is that the strategy (the sequence of methodological decisions that produced the weights) is scattered across files, intermediate objects and the memory of whoever ran them last. When the responsible methodologist moves on, the knowledge often leaves with them.
A typical pipeline looks like this:
Anyone who has worked in a statistical office recognizes this immediately. Along the way you typically reach for many different packages, spread the logic across several scripts, and generate hundreds of lines of code. The methodology is real, but it is implicit: hidden in file order, column names, intermediate files and undocumented tweaks.
Before we look at any code, one picture. Weights exist because the realized sample differs from the population we want to describe, in specific, nameable ways. Each region below is corrected by a specific step.
The frame and the population overlap rather than nest: some of the target population is missing from the frame (undercoverage) and some frame units are out of scope (overcoverage). From the sample downward it is pure nesting (sample ⊃ eligible ⊃ respondents), and each split is a step. The weights are not conjured; they are the consequence of this sequence of decisions.
weightflow expresses the whole strategy as a single, explicit recipe. Nothing
is hidden in a script; nothing lives in an intermediate CSV. Every
methodological decision is a step_*() you can read top to bottom:
weightflowdoesn't just compute weights: it documents how they are constructed.It does compute the weights, of course. But a weighting strategy is a sequence of methodological decisions, and
weightflowturns those decisions into an explicit object that can be inspected, reproduced, modified and reused. The final weights are only one output of that object, and usually the least valuable one. The recipe is the institutional asset.
If you know the recipes/tidymodels world, the analogy is deliberate: a
recipe describes how a dish is produced, not the dish itself. A weightflow
recipe describes how the weights are produced, not the weights themselves.
Enough theory. weightflow ships a small bundled example (a stratified
household sample, sample_survey, drawn from a known population), so every
line below actually runs.
str(sample_survey[, c("pw", "region", "sex", "unknown_elig", "responded")])
A minimal but complete cascade: start from the design weights, resolve unknown
eligibility, correct for nonresponse, and calibrate to the population totals of
region and sex. We pass those totals in the tidy form: a small data
frame per margin with the categories and a counts column. table() already
produces exactly that shape (its counts column is named Freq):
m_region <- as.data.frame(table(region = population$region)) m_sex <- as.data.frame(table(sex = population$sex)) m_region
fit <- weighting_spec(sample_survey, base_weights = pw) |> step_unknown_eligibility(unknown = unknown_elig, by = "region") |> step_nonresponse(respondent = responded, method = "weighting_class", by = "region") |> step_calibrate(method = "raking", totals = list(m_region, m_sex), count = "Freq") |> prep()
prep() is where the recipe is actually estimated. Everything before it only
records the strategy. collect_weights() returns the data with the final
weight attached as .weight:
w <- collect_weights(fit) summary(w$.weight)
Because the strategy is an object, it explains itself. summary() walks the
cascade step by step, reporting how many units each stage touched, how weights
changed, and diagnostics such as the design effect:
summary(fit)
That printout is the methodological record. You did not write a separate memo describing what the scripts did; the recipe and its summary are the memo. Re-running it next year, or handing it to a colleague, reproduces the exact same weights and the exact same explanation.
You now have runnable weights and a mental map. To go deeper:
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.