Skip to contents

get_bootSummaryNlme() is the bootstrap-side companion to get_summaryNlme(): it fuses original-fit columns (estimate, %RSE, shrinkage) with per-replicate bootstrap columns (median / mean and a percentile CI) in one table, applying the same transform / shrinkage machinery to both sides.

When a non-identity transform is active, values are shown on the transformed scale only and the scale label is appended to the Parameter name (nV (CV%), CEps (SD)). The Unit column carries real units only, and the bootstrap CI is formatted as a dash range, lo - hi. The same display rules apply to get_summaryNlme().

This vignette walks through the three input modes against a small fixture shipped under inst/extdata/bootstrap/.

fixture_dir <- system.file("extdata", "bootstrap", package = "Certara.Xpose.NLME")
fixture_files <- list.files(fixture_dir)
fixture_files
#>  [1] "_build_fixture.R"         "BootOmegaCI.csv"         
#>  [3] "BootOmegaStacked.csv"     "BootOverall.csv"         
#>  [5] "BootSecondary.csv"        "BootSecondaryStacked.csv"
#>  [7] "BootSigmaCI.csv"          "BootSigmaStacked.csv"    
#>  [9] "BootTheta.csv"            "BootThetaStacked.csv"    
#> [11] "fitSummary.csv"

The fixture is a checked-in snapshot of the per-parameter and per-replicate CSVs that Certara.RsNLME::loadBootstrapResult() would materialize from a finished bootstrap run. We load it into the same shape an rsnlme_boot object would have.

load_fixture <- function(dir) {
  read_csv <- function(name) {
    path <- file.path(dir, name)
    if (!file.exists(path)) return(NULL)
    df <- utils::read.csv(path, stringsAsFactors = FALSE,
                          check.names = FALSE)
    if (!nrow(df)) NULL else tibble::as_tibble(df)
  }
  list(
    BootOverall          = read_csv("BootOverall.csv"),
    BootTheta            = read_csv("BootTheta.csv"),
    BootThetaStacked     = read_csv("BootThetaStacked.csv"),
    BootOmegaCI          = read_csv("BootOmegaCI.csv"),
    BootOmegaStacked     = read_csv("BootOmegaStacked.csv"),
    BootSigmaCI          = read_csv("BootSigmaCI.csv"),
    BootSigmaStacked     = read_csv("BootSigmaStacked.csv"),
    BootSecondary        = read_csv("BootSecondary.csv"),
    BootSecondaryStacked = read_csv("BootSecondaryStacked.csv"),
    fitSummary           = read_csv("fitSummary.csv")
  )
}
boot_result <- load_fixture(fixture_dir)

Mode 1 – bootstrap only

When neither an xpdb argument nor an embedded fitSummary is available, get_bootSummaryNlme() returns a bootstrap-only table and emits a message noting that original-fit columns are unavailable (and how to include them). The residual-transform advisory still fires here, since there’s no PML to prove the multiplicative_cv default fits:

boot_only <- boot_result
boot_only$fitSummary <- NULL
get_bootSummaryNlme(boot_only)
#> No original-fit (fitmodel) summary is available for this bootstrap result. Original-fit Estimate / %RSE / Shrinkage (%) are unavailable. Re-run bootstrap() with initialEstimates = TRUE, or pass `xpdb`, to include them.
#> Default residual transform is `multiplicative_cv`, appropriate for a genuinely proportional error model. If your model is additive, combined, or otherwise non-proportional, override the affected sigma(s) with `transform = list(<sigma> = ...)` (see ?get_summaryNlme).
#> # A tibble: 6 × 4
#>   Section        Parameter  `Bootstrap estimate (Median)` `Bootstrap 95% CI`
#>   <chr>          <chr>      <chr>                         <chr>             
#> 1 Fixed effects  tvCl       1.95                          1.55 - 2.27       
#> 2 Fixed effects  tvV        51.2                          43.7 - 55.9       
#> 3 Random effects nCl (CV%)  20.4                          18.5 - 22.2       
#> 4 Random effects nV (CV%)   30.2                          27.1 - 34         
#> 5 Residual error CEps (CV%) 19.4                          17.6 - 22.2       
#> 6 Secondary      AUC        101                           91.8 - 108

Mode 2 – bootstrap with embedded fitSummary

When Certara.RsNLME::bootstrap(model, initialEstimates = TRUE) is used, the resulting rsnlme_boot carries a compact fitSummary tibble. get_bootSummaryNlme() will pick it up automatically and fuse the original-fit columns into the same table.

get_bootSummaryNlme(boot_result)
#> # A tibble: 6 × 7
#>   Section       Parameter Estimate `%RSE` `Shrinkage (%)` Bootstrap estimate (…¹
#>   <chr>         <chr>        <dbl>  <dbl>           <dbl> <chr>                 
#> 1 Fixed effects tvCl           2     9               NA   1.95                  
#> 2 Fixed effects tvV           50     8               NA   51.2                  
#> 3 Random effec… nCl (CV%)     20.2   6.38             5.5 20.4                  
#> 4 Random effec… nV (CV%)      30.7   6.39             7.2 30.2                  
#> 5 Residual err… CEps (CV…     20     9                8.1 19.4                  
#> 6 Secondary     AUC          100     5               NA   101                   
#> # ℹ abbreviated name: ¹​`Bootstrap estimate (Median)`
#> # ℹ 1 more variable: `Bootstrap 95% CI` <chr>

The original-fit columns come from the same pipeline get_summaryNlme() uses, so the Estimate, %RSE, and Shrinkage (%) numbers match a single-fit summary built directly from the original fitmodel() run. By default the percentile CI inherits the confidence level the bootstrap was run at (ci_level = NULL reads the confidenceLevel stored on the result, falling back to 0.95); pass an explicit ci_level to override it. digits rounds both the bootstrap and the original-fit numeric columns, and the returned table’s print method uses the same digits for on-screen precision.

Mode 3 – explicit xpdb

The xpdb argument is the most general entry point: it accepts an xpose_data object built via xposeNlme() / xposeNlmeModel(). This carries richer metadata than fitSummary (covariates, residuals, posthoc) and is preferred when the same xpdb is also driving GOF plots elsewhere.

xp <- xposeNlme(dir = fitmodel_run_dir)
get_bootSummaryNlme(boot_result, xpdb = xp)

When both xpdb and an embedded fitSummary are present, xpdb wins and a one-shot warning fires.

Residual-shape advisories (a per-sigma warning when a sigma looks additive or combined in PML but is reported with the multiplicative_cv default) require the PML source, which is only available from xpdb. They therefore fire only in mode 3; modes 1 and 2 cannot classify the error model and emit no shape warning.

Custom transforms

get_bootSummaryNlme() accepts the same transform argument as get_summaryNlme(). It can be:

  • a preset string from the section’s catalog, or
  • a list(fn = ..., dfn = ..., name = ...) spec for a custom function, its derivative, and the scale label (name) appended to the parameter name. A custom transform supplied without name triggers a warning and leaves the parameter name unflagged.

The preset catalog is section-specific (a transform valid for one section is not necessarily valid for another):

Section Allowed presets
Fixed effects "raw"
Random effects "raw", "lognormal_cv", "normal_sd"
Residual error "raw", "log_additive_cv", "multiplicative_cv"
Secondary "raw"

Section defaults: raw (fixed / secondary), lognormal_cv (random), multiplicative_cv (residual). See ?get_summaryNlme for the delta-method derivative each preset uses and the scale flag (CV% / SD) it appends to the parameter name.

The same transform is applied to both the original-fit rows (delta-method %RSE) and to each replicate’s bootstrap value before the empirical metric and CI are computed. Identity (raw) rows render as plain numbers with a bare name; transformed rows show the transformed-scale value only, with the scale flag on the parameter name and the CI as a lo - hi dash range.

get_bootSummaryNlme(
  boot_result,
  transform = list(
    CEps = list(
      fn   = function(s) 200 * s,
      dfn  = function(s) 200,
      name = "2xSD"
    )
  )
)

Replicate filter and attributes

Replicates whose BootOverall$ReturnCode falls outside return_code_ok (default 1:3) are dropped silently before the metric and CI are computed. The result tibble carries a set of attributes that document what was used:

res <- get_bootSummaryNlme(boot_result)
str(attributes(res)[c(
  "n_used", "n_total", "ci_level",
  "return_code_ok", "metric", "fitSource"
)])
#> List of 6
#>  $ n_used        : int 30
#>  $ n_total       : int 30
#>  $ ci_level      : num 0.95
#>  $ return_code_ok: int [1:3] 1 2 3
#>  $ metric        : chr "Median"
#>  $ fitSource     : chr "embedded"

Soft-degrade for missing stacks

BootSigmaStacked and BootSecondaryStacked are net-new in the corresponding Certara.NLME8 release. When either is NULL (older NLME8 build), the matching bootstrap rows are emitted with NA cells and a single warning fires once naming the missing stacks plus the installed Certara.NLME8 version. BootThetaStacked and BootOmegaStacked predate the new release and are always populated.

See also