Skip to contents

This article covers variance components, two- and three-stage cluster designs, design effects, and design degrees of freedom. See Getting started for the core sizing and precision workflow, and allocation for stratified and joint allocation.

Multistage cluster designs

For two-stage or three-stage designs, the question is not just “how many?” but “how many clusters and how many units per cluster?” The answer depends on the cost structure and the degree of clustering.

Variance components from frame data

If frame data with cluster identifiers is available, varcomp() estimates between-cluster and within-cluster variance components:

set.seed(1)
n_clust <- 80
n_hh <- 15
cluster_id <- rep(seq_len(n_clust), each = n_hh)
cluster_mean <- rnorm(n_clust, mean = 50, sd = 10)
expenditure <- cluster_mean[cluster_id] + rnorm(n_clust * n_hh, sd = 20)
frame <- data.frame(cluster = cluster_id, expenditure = expenditure)

vc <- varcomp(expenditure ~ cluster, data = frame)
vc
#> Variance components (2-stage)
#> varb = 0.0398, varw = 0.1700
#> icc = 0.1896
#> var_ratio = 1.0589
#> Unit relvariance = 0.1981
as.data.frame(vc)
#>   stages       varb      varw       icc var_ratio unit_relvar
#> 1      2 0.03976226 0.1699763 0.1895801  1.058885   0.1980749

The icc value is the survey-planning measure of homogeneity. It feeds directly into n_cluster() and the cluster-planning mode of design_effect(). This icc is not a generic mixed-model ICC: varcomp() returns the bounded planning quantity from Valliant, Dever, and Kreuter (2018), and that is the scale expected by the cluster-planning functions. When icc is near 0, most variation is within clusters, so the analytical cluster optimum tends to favor many interviews in very few PSUs. When icc is near 1, most variation is between clusters, so the optimum tends to favor very few interviews in many PSUs. Both are degenerate boundary cases for the closed-form optimizer, so n_cluster() rejects values numerically too close to 0 or 1.

Optimal two-stage allocation

Given per-stage costs and the variance structure, n_cluster() finds the allocation that either minimizes cost for a target CV, or minimizes CV for a given budget:

# Minimize cost to achieve CV = 0.05
n_cluster(stage_cost = c(500, 50), icc = vc, cv = 0.05)
#> Optimal 2-stage allocation
#> field design: n_psu = 26 | n_per_psu = 7 -> total n = 182
#> cv = 0.0496, cost = 22100
#> continuous optimum: n_psu = 26.30386 | n_per_psu = 6.538208 (cv = 0.0500, cost = 21751)
#> design df = 25

# Maximize precision within a budget
n_cluster(stage_cost = c(500, 50), icc = vc, budget = 100000)
#> Optimal 2-stage allocation
#> field design: n_psu = 125 | n_per_psu = 6 -> total n = 750
#> cv = 0.0233, cost = 100000
#> continuous optimum: n_psu = 120.9321 | n_per_psu = 6.538208 (cv = 0.0233, cost = 100000)
#> design df = 124

Passing icc = vc (the varcomp object) automatically extracts icc, unit_relvar, and var_ratio.

Three-stage designs

Add a third cost element and a second icc for three-stage designs:

n_cluster(
  stage_cost  = c(1000, 200, 20),
  icc = c(0.01, 0.05),
  cv    = 0.05
)
#> Optimal 3-stage allocation
#> field design: n_psu = 13 | n_per_psu = 5 | n_per_ssu = 15 -> total n = 975
#> cv = 0.0500, cost = 45500
#> continuous optimum: n_psu = 13.46593 | n_per_psu = 4.974937 | n_per_ssu = 13.78405 (cv = 0.0500, cost = 45333)
#> design df = 12

Response rate in cluster designs

A cluster design can lose units at more than one stage, and the two losses are not interchangeable, so they are named for the stage they act on. resp_rate_psu is the share of selected clusters that can be worked at all: whole PSUs lost to insecurity, flooding, or an inaccessible road. Losing a PSU removes its entire contribution, so it deflates every variance term alike and the first-stage sample is inflated by 1 / resp_rate_psu to cover it.

In budget mode, applying a response rate does not change the allocation because the budget constrains the design. The achieved CV worsens instead. In CV mode:

n_cluster(stage_cost = c(500, 50), icc = vc, cv = 0.05, resp_rate_psu = 0.90)
#> Optimal 2-stage allocation
#> field design: n_psu = 29 | n_per_psu = 7 -> total n = 203 (net: 183)
#> (resp_rate_psu = 0.90)
#> cv = 0.0495, cost = 24650
#> continuous optimum: n_psu = 29.22651 | n_per_psu = 6.538208 (cv = 0.0500, cost = 24168)
#> design df = 28

Household or individual nonresponse is a different quantity acting at a different stage, and each has its own argument: resp_rate_ssu for second-stage units in a three-stage design, and resp_rate for the ultimate units. Naming a stage the design does not have is an error rather than a silently ignored argument, because a dropped response rate plans a design with none.

The three are not interchangeable. Losing whole PSUs deflates every variance term alike, whereas losing ultimate units shrinks the realized cluster and so changes the clustering penalty too. That is why the later-stage rates move the cost-optimal take while the PSU rate does not:

# a DHS-shaped design: EAs, households within EAs, one person per household
n_cluster(stage_cost = c(500, 100, 50), icc = c(0.02, 0.05), cv = 0.05,
          resp_rate_psu = 0.95, resp_rate_ssu = 0.90, resp_rate = 0.85)
#> Optimal 3-stage allocation
#> field design: n_psu = 36 | n_per_psu = 4 | n_per_ssu = 6 -> total n = 864 (net: 628)
#> (resp_rate_psu = 0.95, resp_rate_ssu = 0.90, resp_rate = 0.85)
#> cv = 0.0497, cost = 75600
#> continuous optimum: n_psu = 35.40747 | n_per_psu = 3.689324 | n_per_ssu = 6.686246 (cv = 0.0500, cost = 74438)
#> design df = 35

Sizes and costs stay gross: $n counts the units to issue and $cost pays for them, while the variance reads what they realize. Lumping the later rates into resp_rate_psu is conservative but wrong, and the gap grows with the between-PSU homogeneity.

Fixed overhead costs

The standard cost model is purely linear: C = c1*n_psu + c2*n_psu*n_per_psu. Real surveys also have a fixed overhead (training, infrastructure, setup). The fixed_cost parameter adds this term: C = C0 + c1*n_psu + c2*n_psu*n_per_psu. In budget mode, only budget - fixed_cost is available for the variable component, reducing n_psu while leaving the optimal n_per_psu/n_psu ratio unchanged. In CV mode, all sample sizes stay the same and fixed_cost is simply added to the total cost:

# Budget mode: fixed overhead reduces the allocatable budget
n_cluster(stage_cost = c(500, 50), icc = vc, budget = 100000, fixed_cost = 5000)
#> Optimal 2-stage allocation
#> field design: n_psu = 111 | n_per_psu = 7 -> total n = 777
#> cv = 0.0240, cost = 99350 (fixed: 5000)
#> continuous optimum: n_psu = 114.8855 | n_per_psu = 6.538208 (cv = 0.0239, cost = 100000)
#> design df = 110

# CV mode: same allocation, cost increases by fixed_cost
n_cluster(stage_cost = c(500, 50), icc = vc, cv = 0.05, fixed_cost = 5000)
#> Optimal 2-stage allocation
#> field design: n_psu = 26 | n_per_psu = 7 -> total n = 182
#> cv = 0.0496, cost = 27100 (fixed: 5000)
#> continuous optimum: n_psu = 26.30386 | n_per_psu = 6.538208 (cv = 0.0500, cost = 26751)
#> design df = 25

The same parameter is available when n_cluster() sizes a table of indicators.

Evaluating cluster allocations

prec_cluster() computes the achieved CV for any allocation:

alloc <- n_cluster(stage_cost = c(500, 50), icc = vc, budget = 100000)
prec_cluster(alloc)
#> Sampling precision for 2-stage cluster
#> n_psu = 121 | n_per_psu = 7 -> total n = 847
#> cv = 0.0233

# Arbitrary allocation
prec_cluster(n = c(50, 12), icc = 0.05)
#> Sampling precision for 2-stage cluster
#> n_psu = 50 | n_per_psu = 12 -> total n = 600
#> cv = 0.0508

Design effects

design_effect() builds the design effect you expect a plan to produce, from the design features you are choosing. The clustering component uses the same variance model as n_cluster() and prec_cluster(), so the two always agree:

design_effect(icc = 0.05, n_per_psu = 20)
#> Planning design effect: 1.9500

Components are selected by the arguments you supply and multiply together. Unequal weighting comes from planned weights or from a planned allocation’s stratum sizes and takes, and the stratification gain (the only component that can fall below 1) from the stratum standard deviations and means:

frame <- data.frame(
  N = c(50000, 120000), n = c(600, 400), sd = c(12, 20), mean = c(55, 48)
)
deff <- design_effect(icc = 0.05, n_per_psu = 20, strata = frame)
deff
#> Planning design effect: 2.6279

The result is a plain number wherever one is expected, and effective_n() is its mirror:

n_prop(p = 0.3, moe = 0.05, deff = deff)
#> Sample size for proportion (wald)
#> n = 848 (p = 0.30, moe = 0.050, deff = 2.63)
#> expected cases = 254.4
effective_n(deff, n = 1000)
#> [1] 380.5354

You can also read the features off a plan you already built, including an n_alloc() allocation:

design_effect(n_cluster(stage_cost = c(500, 50), icc = 0.05, cv = 0.05))
#> Planning design effect: 1.6392

These are planning quantities. After data collection, compute the design effect the sample actually achieved with survey::svymean(..., deff = TRUE), which uses the realized weights, strata, and clusters.

Multi-indicator multistage

For surveys with several indicators in a cluster design, hand n_cluster() a table of indicators carrying icc_psu columns, along with stage costs:

targets_ms <- data.frame(
  name   = c("stunting", "vaccination"),
  p      = c(0.25, 0.70),
  cv     = c(0.10, 0.08),
  icc_psu = c(0.05, 0.02)
)

n_cluster(indicators = targets_ms, stage_cost = c(500, 50), budget = 80000)
#> Multi-indicator optimal allocation (2-stage)
#> field design: n_psu = 64 | n_per_psu = 15 -> total n = 960
#> worst cv = 0.0729, cost = 80000 (binding: stunting)
#> continuous optimum: n_psu = 67.27204 | n_per_psu = 13.78403 (cv = 0.0728, cost = 80000)
#> 
#>  name        .n        .cv_target .cv_achieved .binding
#>  stunting    491.76043 0.10       0.0728       *       
#>  vaccination  84.08575 0.08       0.0241