Precision targets for proportions, means, and ratios
Source:vignettes/articles/precision.Rmd
precision.RmdThis article helps you choose the quantity to estimate and the way to state its precision. Begin with Getting started for the basic sample-size and precision workflow.
Four ways to state precision
svyplan reports four related quantities:
| Absolute | Relative | |
|---|---|---|
| Sampling uncertainty | standard error (se) |
coefficient of variation (cv) |
| Interval half-width | margin of error (moe) |
relative margin of error (rmoe) |
For a proportion, moe = 0.05 means 5 percentage points.
It does not mean 5% of the proportion. The latter is a relative margin
of error. At p = 0.70, rmoe = 0.05 is an
absolute margin of error of 0.035.
n_prop(p = 0.70, moe = 0.035)
#> Sample size for proportion (wald)
#> n = 659 (p = 0.70, moe = 0.035, deff = 1)
#> expected cases = 461.0
n_prop(p = 0.70, rmoe = 0.05)
#> Sample size for proportion (wald)
#> n = 659 (p = 0.70, rmoe = 0.050, deff = 1)
#> expected cases = 461.0
n_prop(p = 0.70, cv = 0.05)
#> Sample size for proportion (wald)
#> n = 172 (p = 0.70, cv = 0.050, deff = 1)
#> expected cases = 120.0The coefficient of variation describes the sampling variance. The two
margin of error targets also depend on the confidence level and interval
method. For a two-sided Wald interval, rmoe is the interval
quantile times cv.
Proportions and interval methods
The default Wald calculation is the familiar normal approximation:
n_prop(p = 0.30, moe = 0.05)
#> Sample size for proportion (wald)
#> n = 323 (p = 0.30, moe = 0.050, deff = 1)
#> expected cases = 96.8Four interval methods are available:
| Method | Planning interpretation |
|---|---|
"wald" |
Symmetric normal approximation (the default). |
"wilson" |
Wilson score interval, bounded to the parameter space. |
"logodds" |
Interval formed on the log-odds scale and transformed back. |
"beta" |
Korn–Graubard interval with optional design degrees of freedom. |
Their differences are most visible near 0 or 1 or with few sampled clusters:
sapply(c("wald", "wilson", "logodds", "beta"), function(method) {
result <- prec_prop(
p = 0.02,
n = 900,
deff = 2,
df = 25,
method = method
)
c(se = result$se, cv = result$cv, moe = result$moe, rmoe = result$rmoe)
})
#> wald wilson logodds beta
#> se 0.006599663 0.006599663 0.006599663 0.006599663
#> cv 0.329983165 0.329983165 0.329983165 0.329983165
#> moe 0.013592261 0.014251833 0.014565337 0.014997984
#> rmoe 0.679613049 0.712591665 0.728266856 0.749899196The sampling standard error and CV do not change across columns. The
interval half-widths do because each method constructs a different
interval. Choose the method that matches the intended reporting
procedure. Use df = design_df(...) when the planned
variance estimator has few degrees of freedom.
The log-odds limits bound the proportion, or equivalently its odds. They do not bound an odds ratio, and the method does not size a logistic-regression coefficient.
Means and totals
For a mean, supply a population variance or standard deviation estimated from a previous survey, pilot, or comparable population:
n_mean(var = 40000, moe = 30)
#> Sample size for mean
#> n = 171 (var = 40000.00, moe = 30.000, deff = 1)
n_mean(sd = 200, mu = 800, cv = 0.05)
#> Sample size for mean
#> n = 25 (var = 40000.00, cv = 0.050, deff = 1)A target CV or relative margin of error also needs the anticipated mean because both are relative to its magnitude.
A total is a mean multiplied by a known population size. It therefore
does not need a separate sizing function. A CV target is unchanged and
an absolute margin of error for a total must be divided by
N before sizing the mean:
population <- 10000
total_moe <- 500000
n_mean(
var = 2500,
moe = total_moe / population,
N = population
)
#> Sample size for mean
#> n = 4 (var = 2500.00, moe = 50.000, deff = 1)This conversion assumes that the population size used to define the total is known for planning.
Ratios of two totals
n_ratio() plans for
R = T_y / T_x,
where the numerator and denominator are observed on the same sampled units. Examples include consumption per person and yield per hectare. Supply the anticipated ratio, the coefficient of variation of each component, and their unit-level correlation:
n_ratio(
r = 420,
cv_num = 1.20,
cv_den = 0.45,
component_cor = 0.65,
cv = 0.05
)
#> Sample size for ratio (linearization)
#> n = 377 (r = 420, unit_relvar = 0.941, cv = 0.050, deff = 1)This estimand is different from the mean of unit ratios y_i/x_i, which is planned with
n_mean(). A coverage rate among an eligible group is
usually a domain proportion. First calculate the sample required
within the eligible domain, then use its expected share to
calculate the overall sample. The multiple-indicator and domain guide
demonstrates that step.
The ratio calculation uses the relative variance of the linearized variable e = y - Rx. A stronger positive association between the components can make the ratio more stable:
ratio_plan <- n_ratio(
r = 420,
cv_num = 1.20,
cv_den = 0.45,
component_cor = 0.65,
cv = 0.05
)
predict(
ratio_plan,
data.frame(component_cor = c(0.30, 0.65, 0.90))
)
#> component_cor n se moe cv rmoe
#> 1 0.30 527.4 21 41.15924 0.05 0.0979982
#> 2 0.65 376.2 21 41.15924 0.05 0.0979982
#> 3 0.90 268.2 21 41.15924 0.05 0.0979982Margin-of-error targets are stated on the ratio’s own scale. Here
moe = 20 asks for an interval of plus or minus 20 currency
units per person, and rmoe would state the same target
relative to r. Design effect and response rate enter as for
a mean:
n_ratio(
r = 420,
cv_num = 1.20,
cv_den = 0.45,
component_cor = 0.65,
moe = 20,
deff = 1.3,
resp_rate = 0.85
)
#> Sample size for ratio (linearization)
#> n = 2437 gross (net: 2072) (r = 420, unit_relvar = 0.941, moe = 20.000, deff = 1.30, resp_rate = 0.85)prec_ratio() evaluates a ratio design at a fixed sample
size. Passing it the sizing result carries the same assumptions and
returns the target CV:
prec_ratio(ratio_plan)
#> Sampling precision for ratio (linearization)
#> n = 377
#> se = 21.0000, moe = 41.1592, cv = 0.0500, rmoe = 0.0980When the two component CVs are nearly equal and their correlation is
near 1, the assumed ratio is nearly constant and the required size falls
toward zero. That size depends on a correlation known to several
decimals, and n_ratio() warns about it:
n_ratio(
r = 420,
cv_num = 1.20,
cv_den = 1.19,
component_cor = 0.9999,
cv = 0.05
)
#> Warning: the ratio's unit relative variance (0.000386) is far below its
#> components': the plan rests on 'component_cor' = 0.9999 being known to that
#> precision. Vary it with predict() before committing to this size
#> Sample size for ratio (linearization)
#> n = 1 (r = 420, unit_relvar = 0.000386, cv = 0.050, deff = 1)Using a known auxiliary total
A ratio can also be used to estimate a different quantity. If the auxiliary total T_x is known from the frame, the estimator \widehat{T}_y = T_x\widehat{R} targets the outcome total. For example, known total cultivated area can turn estimated yield per hectare into an estimated harvest total. Multiplication by a known constant preserves relative precision, while an absolute margin of error must be multiplied by T_x.
The first-order variance uses residuals e_i
= y_i - R x_i and the planned sample design (Cochran 1977). A
generic regression variance reduction such as 1-\rho^2 is not automatically the variance
reduction of this ratio estimator, because that reduction depends on the
assumed relation between the two variables. The calculation also omits
higher-order ratio bias. Document those approximations when using
n_ratio() for a known-total auxiliary estimator.
The same residuals give the planning input when the ratio estimator
sharpens the estimate of the mean of y.
Fit the ratio to pilot data, take the residual variance, and pass it to
n_mean(var = ) with the mean of the analysis variable:
set.seed(2)
area <- rlnorm(200, 3, 0.5)
harvest <- 2.5 * area + rnorm(200, 0, 15)
pilot_ratio <- mean(harvest) / mean(area)
residual <- harvest - pilot_ratio * area
n_mean(var = var(harvest), mu = mean(harvest), cv = 0.02)
#> Sample size for mean
#> n = 839 (var = 1260.27, cv = 0.020, deff = 1)
n_mean(var = var(residual), mu = mean(harvest), cv = 0.02)
#> Sample size for mean
#> n = 147 (var = 220.22, cv = 0.020, deff = 1)
n_ratio(
r = pilot_ratio,
cv_num = sd(harvest) / mean(harvest),
cv_den = sd(area) / mean(area),
component_cor = cor(area, harvest),
cv = 0.02
)
#> Sample size for ratio (linearization)
#> n = 147 (r = 2.648, unit_relvar = 0.0586, cv = 0.020, deff = 1)The first call ignores the auxiliary variable. The second sizes the
ratio estimator of the mean. With a CV target it gives the same size as
n_ratio() on the pilot’s component CVs and correlation,
because the two estimators have the same relative variance.
If the auxiliary total is estimated in an earlier sampling phase, it is no longer a fixed multiplier. Its uncertainty and covariance must be included. See the two-phase method boundary.
Ratios in a cluster design
For a multistage survey, estimate the variance components of the linearized variable. The relevant homogeneity is not generally the homogeneity of the numerator or denominator:
set.seed(1)
psu <- rep(1:30, each = 20)
x <- rlnorm(600, 1, 0.4)
y <- 3 * x + rnorm(600, 0, 0.8)
ratio <- mean(y) / mean(x)
linearized <- y - ratio * x
components <- suppressWarnings(varcomp(linearized, stage_id = list(psu)))
n_cluster(
stage_cost = c(500, 50),
icc = components$icc,
unit_relvar = var(linearized) / mean(y)^2,
var_ratio = components$var_ratio,
cv = 0.01
)
#> Optimal 2-stage allocation
#> field design: n_psu = 10 | n_per_psu = 15 -> total n = 150
#> cv = 0.0099, cost = 12500
#> continuous optimum: n_psu = 9.49938 | n_per_psu = 15.88247 (cv = 0.0100, cost = 12293)
#> design df = 9The linearized variable has mean zero by construction, so
varcomp() warns that its relative variances are infinite.
Its icc and var_ratio remain usable because
they do not depend on the mean and unit_relvar is supplied
separately on the ratio estimator’s scale.
Precision across sample sizes
prec_prop() and the other prec_*()
functions evaluate a fixed sample size. predict() over
n shows how precision changes as the sample grows:
fixed_n <- prec_prop(p = 0.30, n = 400)
predict(fixed_n, data.frame(n = c(100, 200, 400, 800, 1600)))
#> n se moe cv rmoe
#> 1 100 0.04582576 0.08981683 0.15275252 0.29938944
#> 2 200 0.03240370 0.06351009 0.10801234 0.21170031
#> 3 400 0.02291288 0.04490842 0.07637626 0.14969472
#> 4 800 0.01620185 0.03175505 0.05400617 0.10585015
#> 5 1600 0.01145644 0.02245421 0.03818813 0.07484736Each fourfold increase in n halves the standard error
and the margin of error.
Solve for a reportable level
prec_prop() can solve for the smallest proportion that a
fixed sample can estimate at a target relative precision:
floor <- prec_prop(n = 1500, cv = 0.10, N = 2e6)
floor
#> Sampling precision for proportion (wald, solved for p)
#> n = 1500
#> p = 0.06246
#> se = 0.0062, moe = 0.0122, cv = 0.1000, rmoe = 0.1960
#> expected cases = 93.7
floor$params$p
#> [1] 0.06245608Every larger proportion has a smaller CV under the same design, and
every smaller one is too rare to report at that precision. This makes
the result a prospective reporting threshold. The printed
expected_cases is the expected number of positive cases at
that proportion, so the precision threshold can be read beside the
min_cases floor of n_prop().
predict() traces the threshold across sample sizes, with
the target CV held fixed:
predict(floor, expand.grid(n = c(500, 1500, 5000)))
#> n p se moe cv rmoe
#> 1 500 0.16663201 0.016663201 0.032659274 0.1 0.1959964
#> 2 1500 0.06245608 0.006245608 0.012241167 0.1 0.1959964
#> 3 5000 0.01955979 0.001955979 0.003833649 0.1 0.1959964A cv target fixes the sampling variance and gives the
same threshold under every interval method. An rmoe target
fixes the relative half-width of the interval the survey will report, so
its threshold moves with method:
prec_prop(n = 1500, rmoe = 0.20, method = "wald", N = 2e6)$params$p
#> [1] 0.06012947
prec_prop(n = 1500, rmoe = 0.20, method = "beta", N = 2e6)$params$p
#> [1] 0.06327848Two properties bound the rmoe search. The Wilson and
Korn–Graubard half-widths do not shrink to zero as p
approaches 1, so their relative margin of error has a positive floor. A
target below that floor is refused, and the error names the floor:
prec_prop(n = 1500, rmoe = 0.001, method = "wilson", N = 2e6)
#> Error:
#> ! 'rmoe' = 0.001 is unattainable: at n = 1500 the 'wilson' interval's relative margin of error never falls below 0.001276The back-transformed log-odds half-width turns upward once the logit
spread exceeds logit(p). The turn lies near
p = 0.999 at n = 1500 and near
p = 0.97 at n = 30. Under
"logodds" the search stops at that turn and returns the
lower root.
prec_mean() takes cv the same way and
returns the magnitude of the mean. The standard error of a mean does not
involve the mean, so this inversion is a division rather than a
search:
prec_mean(var = 25, n = 1500, cv = 0.10)$params$mu
#> [1] 1.290994Expected confidence intervals
confint() extracts the expected interval from supported
size and precision results:
confint(n_prop(p = 0.30, moe = 0.05))
#> 2.5 % 97.5 %
#> 0.25 0.35
confint(n_mean(var = 100, mu = 50, moe = 2))
#> 2.5 % 97.5 %
#> 48 52
confint(ratio_plan)
#> 2.5 % 97.5 %
#> 378.8408 461.1592The level argument sets the confidence level, and a
precision result gives its interval the same way:
confint(fixed_n)
#> 2.5 % 97.5 %
#> 0.2550916 0.3449084
confint(fixed_n, level = 0.99)
#> 0.5 % 99.5 %
#> 0.2409803 0.3590197A repeated-survey result has an interval too. For the average level pooled across two occasions:
confint(prec_pooled(var = 100, n = 300, occasions = 2, mu = 50))
#> 2.5 % 97.5 %
#> 49.19985 50.80015The center for a mean must be supplied because variance and margin of
error do not determine it. For a proportion, Wald endpoints are
truncated to [0, 1] when needed. The other methods stay within the
parameter space by construction. Cluster, allocation, power, and
multi-indicator results have no single interval and are not supported by
confint().
These calculations follow standard survey-sampling variance
approximations (Cochran 1977; Valliant, Dever, and Kreuter 2018).
Document the source and uncertainty of every planning value, then
compare plausible alternatives with predict().