Skip to contents

Refit a GLM on repeated bootstrap samples of the estimation portfolio and retain the coefficient estimates from every successful refit. The resulting distribution describes how sensitive individual model coefficients are to sampling variation in the observed portfolio.

Usage

bootstrap_coefficients(
  object,
  n_resamples = 500,
  seed = NULL,
  show_progress = interactive()
)

Arguments

object

A fitted glm object. Refined GLMs are accepted when their estimation data can be recovered from the model object.

n_resamples

Positive whole number. Number of bootstrap samples. Default is 500.

seed

Optional single numeric seed for reproducible resampling.

show_progress

Logical. If TRUE, display a text progress bar.

Value

An object of class "bootstrap_coefficients". It contains the original coefficients, a coefficient matrix with one row per requested resample, indicators for successful model fits, recorded failure messages, and the resampling settings. Use summary.bootstrap_coefficients() for a coefficient-level data frame and as_gt() for a formatted table.

Details

Each resample contains the same number of portfolio rows as the original estimation data and is drawn with replacement. The function recovers these data from object; a separate data argument is deliberately not required. Rows omitted during the original model fit are excluded so the resampling population remains aligned with the fitted GLM.

Original factor levels, the model formula, offsets and model weights are retained during refitting. A factor level may nevertheless be absent from a particular bootstrap sample. Its coefficient can then be non-estimable and is stored as NA for that replicate.

A failed or non-converged GLM refit does not stop the procedure. The failed replicate is recorded and the function continues. After resampling, an informative message reports how many requested refits produced usable model objects. summary.bootstrap_coefficients() reports the number of finite estimates separately for each coefficient.

Actuarial interpretation

The bootstrap distribution can identify tariff effects that are sensitive to the particular portfolio sample. Wide intervals, material bootstrap bias or a low number of estimable replicates often indicate sparse levels, correlated model terms or limited claim information. These diagnostics should be considered alongside exposure, claim counts, coefficient interpretation and stability across calendar periods.

The row bootstrap represents sampling variation in the observed estimation portfolio. It does not include future trend, parameter uncertainty caused by model selection, structural changes in portfolio composition or dependence between repeated records for the same policy. Where such dependence is material, a cluster-level bootstrap would require a different resampling design.

Author

Martin Haringa

Examples

model <- glm(
  nclaims ~ age_policyholder + zip + offset(log(exposure)),
  family = poisson(),
  data = MTPL
)

boot <- bootstrap_coefficients(
  model,
  n_resamples = 25,
  seed = 123,
  show_progress = FALSE
)

summary(boot, scale = "link")
#>               term      estimate bootstrap_mean          bias bootstrap_se
#> 1      (Intercept) -1.1636200937   -1.220009055 -0.0563889610  0.249137624
#> 2 age_policyholder -0.0170418702   -0.016712389  0.0003294813  0.001285304
#> 3             zip1 -0.0006505428    0.039395119  0.0400456614  0.232329635
#> 4             zip2 -0.1037738083   -0.067240901  0.0365329070  0.243555770
#> 5             zip3 -0.0456536315   -0.007005003  0.0386486282  0.225874270
#>         lower       upper n_successful n_requested success_rate
#> 1 -1.68483701 -0.82875913           25          25            1
#> 2 -0.01939017 -0.01443457           25          25            1
#> 3 -0.32506741  0.50862020           25          25            1
#> 4 -0.41445244  0.40491816           25          25            1
#> 5 -0.35596929  0.40830170           25          25            1
summary(boot, scale = "exponentiated")
#>               term  estimate bootstrap_mean         bias bootstrap_se     lower
#> 1      (Intercept) 0.3123534      0.3039502 -0.008403155  0.073652441 0.1856046
#> 2 age_policyholder 0.9831025      0.9834273  0.000324747  0.001263773 0.9807967
#> 3             zip1 0.9993497      1.0684033  0.069053585  0.263559137 0.7225523
#> 4             zip2 0.9014292      0.9629808  0.061551629  0.249736638 0.6609599
#> 5             zip3 0.9553728      1.0182805  0.062907708  0.241018199 0.7004985
#>       upper n_successful n_requested success_rate
#> 1 0.4365920           25          25            1
#> 2 0.9856691           25          25            1
#> 3 1.6686660           25          25            1
#> 4 1.5047469           25          25            1
#> 5 1.5113859           25          25            1
summary(boot, scale = "relativity")
#>               term  estimate bootstrap_mean         bias bootstrap_se     lower
#> 1      (Intercept) 0.3123534      0.3039502 -0.008403155  0.073652441 0.1856046
#> 2 age_policyholder 0.9831025      0.9834273  0.000324747  0.001263773 0.9807967
#> 3             zip1 0.9993497      1.0684033  0.069053585  0.263559137 0.7225523
#> 4             zip2 0.9014292      0.9629808  0.061551629  0.249736638 0.6609599
#> 5             zip3 0.9553728      1.0182805  0.062907708  0.241018199 0.7004985
#>       upper n_successful n_requested success_rate
#> 1 0.4365920           25          25            1
#> 2 0.9856691           25          25            1
#> 3 1.6686660           25          25            1
#> 4 1.5047469           25          25            1
#> 5 1.5113859           25          25            1

if (requireNamespace("gt", quietly = TRUE)) {
  as_gt(boot, scale = "relativity")
}
Term
Exponentiated coefficients
Bootstrap resamples
Original Mean Bias SE Lower Upper Successful Requested Success (%)
(Intercept) 0,312 0,304 −0,008 0,074 0,186 0,437 25 25 100,0%
age_policyholder 0,983 0,983 0,000 0,001 0,981 0,986 25 25 100,0%
zip1 0,999 1,068 0,069 0,264 0,723 1,669 25 25 100,0%
zip2 0,901 0,963 0,062 0,250 0,661 1,505 25 25 100,0%
zip3 0,955 1,018 0,063 0,241 0,700 1,511 25 25 100,0%