Learn R Programming

speccurvieR (version 1.0.0)

sca_variance: Decompose the variance of the specification curve by analytic choice

Description

`sca_variance()` quantifies how much of the variation in the focal coefficient across a specification curve is attributable to each analytic choice -- here, the inclusion or exclusion of each control variable. It is the descriptive complement to [sca_test()]: where the joint-inference test asks whether the curve as a whole is more extreme than chance, the variance decomposition asks which modelling choices *drive* the spread of estimates.

The focal coefficient (the `coef` column of [sca()] output) is regressed on the 0/1 control-inclusion indicators, and the variance explained is partitioned across controls. By default this uses the LMG (Shapley-value) decomposition of R-squared, whose shares are order-invariant and sum exactly to the model R-squared; the remaining `1 - R^2` is reported as a `"Residual"` row capturing interactions among choices and unexplained variation.

Usage

sca_variance(
  sca_data,
  estimate = "coef",
  method = c("lmg", "type2"),
  residual = TRUE
)

Value

A data frame with one row per control (and a final `"Residual"` row when `residual = TRUE`), sorted by descending share, with columns: `choice` (the control name, or `"Residual"`), `variance` (the portion of the focal coefficient's variance attributed to that choice), and `percent` (its share as a percentage; the column sums to 100).

Arguments

sca_data

A data frame returned by [sca()].

estimate

A string naming the numeric column to decompose. Defaults to `"coef"` (the focal coefficient).

method

One of `"lmg"` (default; LMG/Shapley decomposition of R-squared) or `"type2"` (normalised Type II partial sums of squares). `"shapley"` is an alias for `"lmg"`.

residual

A boolean indicating whether to append a `"Residual"` row for the unexplained (and choice-interaction) variance. Defaults to `TRUE`. When `FALSE`, the control percentages are rescaled to sum to 100.

Details

**Method.** With `method = "lmg"` (default) each control's share is the Shapley value of R-squared: its average marginal contribution to R-squared over all orderings of the controls. These shares are non-negative, order-invariant, and sum to the full-model R-squared, so the reported percentages (controls plus `"Residual"`) sum to 100. `method = "type2"` instead reports each control's "drop-one" partial sum of squares, normalised to sum to 100; because partial sums of squares do not add up under a non-orthogonal design, those percentages are unique contributions rather than an exact partition. (The regression is purely additive -- each control, including an interaction control, enters as a single 0/1 indicator with no product terms -- so Type II and Type III partial sums of squares coincide; the `"type2"` label is kept only for familiarity.) `"shapley"` is accepted as an alias for `"lmg"`. The LMG cost grows as 2 to the power of the number of varying controls (like `sca()`'s own combinatorial growth) and is capped at 20 controls; for larger sets use `"type2"`, which is linear.

**Choice unit.** The decomposition is over *controls* (one binary in/out choice each), read from the indicator columns of [sca()] output. An interaction control such as `"a*b"` is a single choice (its column `"a:b"`). Within one [sca()] call the model family, fixed effects, and focal variable are constant, so only control choices (plus `"Residual"`) appear.

**Relationship to specr.** This is analogous to `specr::icc_specs()` / `specr::plot_variance()` and returns a comparable choice-by-percent table and bar chart. It deliberately differs in method: `icc_specs()` fits a random-effects model and reads intraclass-correlation-based variance components, which treats each analytic choice as one grouping factor with many levels. speccurvieR's only enumerated choice is each control's binary status, for which two-level random-effect variance components are unreliable, so an LMG R-squared decomposition is used instead and no `lme4` dependency is added. The output is intentionally *not* labelled "ICC".

**Caveats.** The shares are descriptive, not inferential: they summarise an already-estimated set of point estimates and carry no sampling-uncertainty interpretation. A share measures how much a control's in/out status *moves* the focal coefficient, not the control's predictive importance and not the direction of any shift. For glm or fixed-effects curves the coefficient is on the model's native (e.g. log-odds) scale, so shares are not comparable across families. At least two specifications with a varying control are required; with exactly two controls the three specifications are saturated by the two main effects, so the residual is zero. If an interaction control is supplied *together with* its component main-effect controls, the controls are not cleanly separable and the shares should be interpreted with care.

See Also

[plot_variance()] to visualise the decomposition; [sca_test()] for the joint-inference test.

Examples

Run this code
s <- sca(y = "Salnty", x = "T_degC",
         controls = c("ChlorA", "O2Sat", "NO2uM"),
         data = bottles, progress_bar = FALSE, parallel = FALSE)
sca_variance(s)
sca_variance(s, method = "type2", residual = FALSE)

Run the code above in your browser using DataLab