--- title: "Pairs bootstrap inference with hcinfer" vignette: > %\VignetteIndexEntry{Pairs bootstrap inference with hcinfer} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>", fig.width = 7, fig.height = 4.5 ) options(hcinfer.use_emoji = FALSE) ``` The pairs (case) bootstrap is a resampling method for the coefficients of an ordinary least squares model. It resamples whole observations, refits the model many times, and summarizes the resulting spread of the estimates. Because it makes no assumption about the form of the error variance, it provides an empirical cross-check on the analytic heteroskedasticity-consistent (HC) standard errors that `hcinfer` computes, and this vignette shows how to run it, read its output, and compare it with the HC estimators. ## The method For each replicate the bootstrap draws `n` rows with replacement from the original data and refits OLS on that resample. Writing the estimate on replicate `r` as the vector of refitted coefficients, the bootstrap standard error of a coefficient is the standard deviation of its replicate values. `boot_pairs()` offers three interval types: `"percentile"` uses the empirical quantiles of the replicates, `"basic"` (reverse percentile) reflects those quantiles about the original estimate, and `"normal"` uses the estimate plus or minus a normal quantile times the bootstrap standard error. ## Data and model The model below uses the `PublicSchools2` data, which has complete observations for all 51 states, and includes a `south` indicator that the original `PublicSchools` data lack. ```{r} library(hcinfer) schools <- PublicSchools2 schools$income_scaled <- schools$income / 10000 fit <- lm(expenditure ~ income_scaled + south, data = schools) fit ``` ## Running the bootstrap A single call fits the resamples and stores the estimates, standard errors, bias, and intervals. Supplying `seed` makes the run reproducible. ```{r} boot <- boot_pairs(fit, B = 2000, seed = 123) boot ``` ## Extractors The `coef()`, `vcov()`, and `confint()` methods pull out the pieces you need. `coef()` returns the original OLS estimates, `vcov()` the bootstrap covariance matrix, and `confint()` the interval table. Note the argument-name asymmetry: `boot_pairs()` sets the default interval type via `ci_type`, while `confint()` overrides it via `type`. ```{r} coef(boot) vcov(boot) confint(boot) ``` `confint()` can recompute intervals at a different level or type directly from the stored replicates, without rerunning the bootstrap. ```{r} confint(boot, level = 0.99, type = "basic") confint(boot, parm = "south", level = 0.90) ``` ## Visualizing the intervals `plot()` draws each coefficient as its estimate with its bootstrap interval, colored by whether the interval excludes zero. ```{r bootstrap-ci-plot, fig.alt = "Pairs bootstrap confidence intervals for the public-schools regression coefficients."} plot(boot) ``` ## An empirical reference for HC standard errors Because the pairs bootstrap assumes nothing about the error variance, its standard errors are a useful cross-check on the analytic HC estimators. The following table places the OLS, bootstrap, HCbeta, and HC3 standard errors side by side. ```{r} data.frame( term = boot$table$term, ols = sqrt(diag(vcov(fit))), bootstrap = boot$table$std_error, hcbeta = sqrt(diag(vcov(hcinfer(fit, type = "hcbeta")))), hc3 = sqrt(diag(vcov(hcinfer(fit, type = "hc3")))) ) ``` The bootstrap and HC standard errors should broadly agree; large disagreements are worth investigating, often at high-leverage points. ## Reproducibility With a fixed `seed`, two runs are identical, and the call restores the caller's random-number stream so it does not disturb a surrounding analysis. ```{r} a <- boot_pairs(fit, B = 1000, seed = 7) b <- boot_pairs(fit, B = 1000, seed = 7) identical(a$replicates, b$replicates) ``` ## Running in parallel For large `B` or large `n`, set `cores` to `2` or more to distribute the replicate fits across worker processes (requires the mirai and carrier packages). The numeric result is identical to a sequential run with the same seed; parallelism only changes the speed. The default `cores = 1` runs sequentially. ```{r, eval = FALSE} boot_pairs(fit, B = 10000, cores = 4, seed = 1) ``` ## Practical guidance Use a few thousand replicates for stable standard errors and more for stable tail quantiles of the percentile and basic intervals. Choose `ci_type` to match your needs: percentile and basic intervals adapt to skewness in the replicate distribution, while normal intervals are symmetric. If a resample is rank deficient it is dropped with a warning, and the summaries use the remaining replicates.