Skip to contents

Count the degrees of freedom the variance estimator of a planned design will have, before any data are collected. The planning analogue of survey::degf(), which reports the same quantity for a design that has already been fielded.

Usage

design_df(x = NULL, ...)

# Default S3 method
design_df(x = NULL, ..., n_psu = NULL, n_strata = 1, n = NULL)

# S3 method for class 'svyplan_cluster'
design_df(x, ...)

# S3 method for class 'svyplan_n'
design_df(x, ...)

# S3 method for class 'svyplan_strata'
design_df(x, ...)

# S3 method for class 'svyplan_twophase'
design_df(x, ...)

Arguments

x

A svyplan result to count from: a n_cluster() or prec_cluster() allocation, a n_alloc() allocation, a strata_bound() stratification, a n_twophase() allocation, or a single-indicator n_prop() or n_mean() size. NULL (default) counts from the components below.

...

Additional arguments passed to methods. Unused arguments are rejected.

n_psu

Number of PSUs the design will select, across all strata.

n_strata

Number of strata, default 1 (unstratified).

n

Number of ultimate units, for an element design. Supply this or n_psu, not both.

Value

A svyplan_df object: a numeric scalar carrying the counts it was formed from. Use it directly wherever a df argument is expected, as.double() to strip it to a plain number, and $strata and $domains for the per-stratum and per-domain tables.

Details

The degrees of freedom of a design-based variance estimator are the number of independent units contributing to it, less the number of constraints the design imposes: for a stratified design, sampled units minus strata. In a clustered design the units are the PSUs, not the ultimate units, which is why a survey of 12,000 households in 300 clusters across 20 strata has 280 degrees of freedom rather than 11,999.

That number is what a t quantile needs, what a Korn-Graubard interval widens on, and what decides whether a domain estimate can be published at all. Nothing reports it for a design that has only been planned, and the plan is the only place it can be known before fielding.

What is counted, per design shape

DesignCounteddf
Unstratified elementunits\(n - 1\)
Unstratified clusterPSUs\(m - 1\)
Stratified elementunits per stratum\(\sum_h n_h - H\)
Stratified clusterPSUs per stratum\(\sum_h m_h - H\)
Two-phasephase-2 units per stratum\(\sum_h n_{2h} - H\)

The counts are read from the whole-unit columns a plan reports (n_int, n_psu_int, operational$n), never from the continuous optimum, since a degree of freedom is a unit that will be fielded. They are the planned counts and are not netted down for element nonresponse: a response rate is already priced into the size the plan reports, and element nonresponse does not reduce the number of PSUs, which is what the df of a clustered design counts.

A stratum that carries no sampling variance drops out of both terms. In element mode a take_all stratum is a census and contributes nothing. In cluster mode take_all marks an element-level census inside the stratum, which leaves the PSU stage sampling as before, so such a stratum still contributes \(m_h - 1\). A phase-2 take_all stratum likewise still contributes, since following up every phase-1 unit in a stratum does not remove the phase-1 sampling variance.

Per-domain degrees of freedom

$domains is exact rather than an approximation. The allocation API expresses a domain as a set of whole strata, so a domain's df is that union's own contribution, \(\sum_{h \in d} m_h - H_d\), and the per-domain values sum to the overall df whenever the domains partition the frame.

The case that is not derivable is an analytic domain cutting across strata, such as an age group or sex. Its df is bounded above by the design df, and the Korn-Graubard counting rule for it (PSUs containing domain members, minus strata containing them) needs frame information that a plan does not carry. It is a limit of what is knowable before fielding, not an omission.

What the count cannot see

Certainty, or self-representing, PSUs contribute no between-PSU variance and should not count toward df. The API expresses certainty through take_all and strata_bound()(take_all_above = ) at the stratum level rather than as a PSU-level flag, so sampled PSUs are counted as they stand. A design with a material number of certainty PSUs has fewer degrees of freedom than reported here.

A stratum holding a single PSU supports no within-stratum variance estimate at all, and warns, naming the stratum. Its own contribution is zero and $strata marks it "singleton". Whether a small but positive df is a problem is a judgment call, so it is reported and never warned about.

Methods (by class)

  • design_df(default): Count from the design's own numbers. Supply n_psu for a clustered design or n for an element design, with n_strata where the design is stratified.

  • design_df(svyplan_cluster): Count the PSUs a n_cluster() or prec_cluster() allocation selects. Unstratified, so the count is one design.

  • design_df(svyplan_n): Count a n_alloc() allocation, at the PSU stage when the frame carried cluster columns and at the element stage otherwise, or the units of a single n_prop() or n_mean() size.

  • design_df(svyplan_strata): Count a strata_bound() stratification, whose strata are element-stage and whose take-all strata are censuses.

  • design_df(svyplan_twophase): Count the phase-2 units a n_twophase() allocation measures. A take-all phase-2 stratum still carries the phase-1 sampling variance, so it contributes as any other does.

References

Valliant, R., Dever, J. A., and Kreuter, F. (2018). Practical Tools for Designing and Weighting Survey Samples (2nd ed.). Springer. Ch. 3.

Korn, E. L. and Graubard, B. I. (1998). Confidence intervals for proportions with small expected number of positive counts estimated from survey data. Survey Methodology, 24(2), 193–201.

See also

design_effect() for the other property of a design read off a plan, n_prop() and n_mean(), whose df argument this is the input to, and varcomp() for the components a clustered plan is built from.

Examples

# A stratified cluster allocation: PSUs minus strata
frame <- data.frame(
  stratum = c("a", "b", "c"),
  N       = c(12000, 30000, 8000),
  sd      = c(5, 8, 3),
  mean    = c(10, 20, 5),
  icc_psu = 0.05,
  n_per_psu = 12
)
alloc <- n_alloc(frame, n = 3000)
design_df(alloc)
#> Design degrees of freedom (planning)
#> 
#>   df = 246   (249 PSUs - 3 strata)
design_df(alloc)$strata
#>   stratum n_units  df .status
#> 1       a      46  45      ok
#> 2       b     185 184      ok
#> 3       c      18  17      ok

# Drop-in wherever a df is expected
n_prop(p = 0.02, moe = 0.01, method = "beta", df = design_df(alloc))
#> Sample size for proportion (beta)
#> n = 867 (p = 0.02, moe = 0.010, deff = 1)
#> expected cases = 17.3

# From counts, with no plan in hand
design_df(n_psu = 300, n_strata = 20)
#> Design degrees of freedom (planning)
#> 
#>   df = 280   (300 PSUs - 20 strata)