Skip to contents

Use confint_inspect() when a profile confidence interval is missing, one-sided, very wide, or hard to trust. Most users should start with confint.gllvmTMB_multi() or the matching extract_*() interval helper; this function is the advanced visual check for a direct profile target.

Usage

confint_inspect(
  fit,
  parm,
  level = 0.95,
  ystep = 0.5,
  ytol = NULL,
  parm.range = c(-Inf, Inf)
)

Arguments

fit

A fit returned by gllvmTMB().

parm

Character. A single profile-target label from profile_targets(). Examples: "sigma_eps", "sd_B[1]", "phi_nbinom2[2]", "b_fix[1]". Derived targets are not accepted by this direct-parameter diagnostic.

level

Confidence level. Default 0.95.

ystep

Profile grid spacing on the deviance scale, passed to TMB::tmbprofile(). Default 0.5.

ytol

Profile maximum-deviance budget, passed to TMB::tmbprofile(). Default NULL, which sizes the budget for the requested level (the crossing threshold plus a margin). A budget below the threshold cannot produce a crossing, so the bound would come back infinite; supply a number only if you want to override that.

parm.range

Two-element numeric range (in the TMB-link scale) for the profile walk, passed to TMB::tmbprofile(). Default c(-Inf, Inf).

Value

An object of class gllvmTMB_confint_inspect with components:

$curve

Data frame with one row per profile-grid point. Columns: parm (user-facing label), parm_value_natural (parameter value on the natural scale after the registered transformation), parm_value_link (parameter value on the TMB optimisation scale), nll (negative log-likelihood), deviance_drop (2 * (nll - mle_nll), the chi-squared statistic), excess_over_threshold (deviance_drop - chi2_threshold; negative is inside CI, positive is outside), in_ci (logical).

$bounds

Data frame, 1 row: parm, estimate_natural, lower_natural, upper_natural, wald_lower_natural, wald_upper_natural, wald_profile_disagree_lower, wald_profile_disagree_upper. Wald bounds come from fit$sd_report$cov.fixed via the delta method; disagreement flags are TRUE when the absolute difference exceeds 25% of the Wald half-width (a heuristic for "look at the plot").

$plot

A ggplot object visualising the curve, MLE, chi-squared threshold, profile bounds (vertical lines), and Wald bounds (dashed vertical lines for comparison). NULL if ggplot2 is not installed.

$diagnostics

Named character vector flagging any of: "no_heuristic_warning" (none of this helper's shape warnings fired; this does not prove a quadratic profile), "asymmetric" (skewed, Wald-vs-profile disagrees), "flat_at_mle", "hits_lower_bound", "hits_upper_bound", "no_lower_crossing", "no_upper_crossing", "profile_failed".

$call

The match.call() of the invocation.

Details

It returns the full profile-likelihood curve, the deviance bounds, and (when ggplot2 is available) a ggplot visualisation showing the curve, the MLE, the chi-squared threshold, and the resulting confidence-interval bounds. It surfaces a small set of numerical shape warnings before the user interprets the bound; the returned label is not a goodness or calibration certificate.

This helper inspects direct profile-ready targets from profile_targets(). Nonlinear derived targets such as communality, repeatability, and trait correlation do not currently have a public profile-inspection route. A working direct curve does not establish empirical interval coverage for every model class.

Common patterns to look for in the returned plot (see the profile-likelihood article):

  • Quadratic and approximately symmetric near the MLE: Wald and profile may agree closely for this target.

  • Asymmetric or skewed: inspect the endpoint status and constrained-fit stability before preferring either interval.

  • Flat near the MLE: the target may be weakly informed, or the numerical profile may need closer inspection.

  • Hits a parameter-range bound: interpret the endpoint on the target's transformed scale and distinguish a natural boundary from a truncated search.

  • No usable crossing: treat the endpoint as unavailable; do not replace it automatically with bootstrap output unless simulation, refits, failed replicate counts, and Monte Carlo resolution are credible for that target.

See also

confint.gllvmTMB_multi() (the corresponding CI extractor; same parm vocabulary), profile_targets() (the target inventory), tmbprofile_wrapper() (the lower-level profile API), and the profile-likelihood article.

Examples

set.seed(1)
# Four traits measured twice on each of 80 units (e.g. individuals),
# sharing one latent axis.
sim <- simulate_unit_trait(n_units = 80, n_obs_per_unit = 2,
                           n_traits = 4,
                           Lambda_B = matrix(c(0.9, 0.8, -0.7, 0.5)),
                           psi_B = 0.3, sigma2_eps = 0.3)
fit <- gllvmTMB(value ~ 0 + trait +
                  latent(0 + trait | unit, d = 1, unique = TRUE),
                data = sim$data, trait = "trait", unit = "unit")

# Profile the residual standard deviation (true value sqrt(0.3) = 0.55).
# The profile tracks how much worse the fit gets as sigma_eps moves
# away from its estimate; the interval is the range where that loss
# stays below the chi-squared threshold.
insp <- confint_inspect(fit, parm = "sigma_eps")

# Printing shows the profile and Wald bounds side by side, followed by
# any shape warnings.
insp
#> 
#> ── gllvmTMB confint_inspect for "sigma_eps" ────────────────────────────────────
#> 
#> ── Estimate + CI ──
#> 
#>                    parm estimate_natural lower_natural upper_natural
#> log_sigma_eps sigma_eps         0.582798     0.5404067     0.6310422
#>               wald_lower_natural wald_upper_natural wald_profile_disagree_lower
#> log_sigma_eps          0.5393509           0.629745                       FALSE
#>               wald_profile_disagree_upper
#> log_sigma_eps                       FALSE
#> ── Diagnostics ──
#> 
#> ℹ No heuristic shape warning fired. Inspect the curve directly; this does not prove quadratic shape or calibrated coverage.
#> The $plot component is a <ggplot>; call `plot(result$plot)` to render.

# A few points of the profile curve.
head(insp$curve[, c("parm_value_natural", "deviance_drop", "in_ci")])
#>   parm_value_natural deviance_drop in_ci
#> 1          0.5295040      6.281139 FALSE
#> 2          0.5329037      5.446743 FALSE
#> 3          0.5363252      4.675053 FALSE
#> 4          0.5397687      3.965273 FALSE
#> 5          0.5467221      2.728302  TRUE
#> 6          0.5537651      1.729648  TRUE

# Plot the curve with the threshold, the estimate and both intervals
# (needs the ggplot2 package).
if (requireNamespace("ggplot2", quietly = TRUE)) {
  plot(insp$plot)
}