Skip to content

Report the precision of a named null.terms variable across the model set #18

Description

@beckyfisher

What

Add an optional per-model summary of the precision of a term supplied through
null.terms — its standard error, or the width of its confidence band — so that
the effect of each candidate covariate on the estimate of a forced term can be
read from the model set.

Why it matters

Where null.terms carries a term the analysis exists to estimate, the question
asked of the model set is not only which candidates predict the response, but
which of them help resolve that term. The two are different, and the existing
output answers only the first.

A candidate can explain response variance well and still widen the interval on the
forced term, if the two are correlated. That case is not visible anywhere at
present: r2.vals.unique reports fit, variable.importance reports how often a
term is selected, and neither is a statement about the precision of a different
term. It is also the case the collinearity screen cannot catch, because
null.terms is outside it (beckyfisher/FSSgam_package#23).

The alternative is for the user to refit the set by hand, extracting the term's
standard error from each fit, which is a loop the package is already running.

Why not general effect-size reporting

A broader capability — effect sizes for every term in the selected set — is
tempting but has a defect that this narrower one avoids.

Estimates and intervals taken from a model chosen by AICc out of a large candidate
set have wrong coverage: the intervals are too narrow, because the selection step
is not accounted for. A term reported with an interval looks like an estimate and
will be used as one, and for a selected term that reading is not supported.

A null.terms term is not subject to selection for its own inclusion, so it does
not carry that bias in the same way. Restricting the report to forced terms keeps
the output defensible. (The standard error is still conditional on a data-driven
nuisance specification, which is a smaller effect but worth stating in the
documentation rather than leaving implied.)

Evidence that the loop already has what is needed

fit_model_set() already fits and holds every model, and extract_mod_dat()
already pulls per-model statistics from each fit:

mod.dat <- list(AICc=NA, BIC=NA, r2.vals=NA, r2.vals.unique=NA, edf=NA, edf.less.1=NA)

so the addition is another extractor over the same objects, not another pass.

Implementation detail

Interface

An argument naming the term of interest, e.g. precision.term = "s(flow)" or the
bare variable name, defaulting to NULL for no change in behaviour. Adding a
column to mod.data.out keeps it alongside AICc and r2.vals.unique, where the
comparison is wanted.

What to report, by term type

  • Parametric term — the standard error from summary(fit)$p.table, which is
    unambiguous.
  • Smooth — there is no single coefficient, so a choice is needed. Two
    workable options: the mean width of the pointwise confidence band over the
    observed range of the variable, or the standard error of a user-supplied
    contrast between two values of it. The second is more interpretable and more
    work; the first is a reasonable default. Either way the quantity should be
    named in the documentation, since "the precision of a smooth" is not
    self-defining.
  • Random effect in null.terms — not a target for this; the argument should
    either skip or error on a term with no fixed-effect interpretation, rather than
    return something meaningless.

Points to settle

  • Behaviour when the named term is absent from null.terms. Erroring is
    probably right: the whole argument for the feature rests on the term being
    forced into every model, so a term that is merely usually selected should not
    be accepted silently.
  • The gamm/gamm4/dsm classes each reach the fitted smooth differently, as
    extract_mod_dat() already has to handle for R².
  • Comparability across models requires the same rows in each fit, which holds
    when predictors are complete — generate_model_set() already rejects
    predictors containing NA.

Definition of done

For a named forced term, mod.data.out carries a precision column that can be
read against delta.AICc and r2.vals.unique, and the documentation states what
the number is, that it applies only to forced terms, and why it is not offered for
selected ones.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions