Attaches nonparametric bootstrap standard errors and percentile confidence
intervals to every between-level correlation (edge) of a fitted
bass-ackwards hierarchy. Every edge ackwards() reports is a point
estimate. This function quantifies the sampling uncertainty of that
estimate. That matters most where a hard threshold consumes the estimate.
Two such places are prune()'s |r| >= redundancy_r redundancy rule and
the Forbes (2023) practice of interpreting the strongest all-pairs edge. A
factor is a summary variable standing in for a group of items that move
together, and a redundant factor is one that persists across levels without
changing.
Usage
boot_edges(x, ...)
# S3 method for class 'ackwards'
boot_edges(x, data, n_boot = 1000L, conf = 0.95, seed = NULL, ...)Arguments
- x
An
ackwardsobject fit withengine = "pca"or"efa"on a"pearson"or"spearman"basis. ESEM objects (exploratory structural equation modeling) are not supported, because refittingn_bootlavaan hierarchies needs its own performance treatment. Polychoric-basis objects are not supported either, because estimating a polychoric matrix in every resample is slow and unstable. Polychoric correlations estimate the correlation between the continuous traits assumed to underlie ordered responses. Objects fit from a correlation matrix are also unsupported, because resampling needs rows.- ...
Reserved for future arguments.
- data
The raw item data the model was fit on. Required, because the
ackwardsobject deliberately does not store raw data (light core), so it must be re-supplied here. Columns are matched by name against the fit, and a warning is issued if the data do not look like the fit data.- n_boot
Number of bootstrap replicates. Default
1000L. Larger values (2000+) are advisable for published interval endpoints (Efron & Tibshirani, 1993). Each replicate refits the full hierarchy, so cost scales linearly.- conf
Confidence level for the percentile intervals. Default
0.95.- seed
Integer seed for reproducible resampling.
NULL(default) uses the current RNG state.
Value
x, invisibly modified: the $boot element is populated with
- edges
Data frame with one row per edge, aligned with
tidy(x, what = "edges"). The identifier columns arefrom,to,level_from, andlevel_to. The estimate columns arer(the full-sample point estimate),se(bootstrap standard error), andloandhi(percentile interval endpoints). The columnn_boot_okcounts the usable replicates for that edge.- n_boot, conf, seed
The request.
After calling boot_edges(), the table tidy(x, what = "edges") gains
se, lo, and hi columns. Also, print(x) and summary(x) note the
interval coverage.
Details
For each of n_boot replicates, n rows are resampled with replacement.
The correlation matrix is recomputed with the same basis and missing-data
routine used at fit time, and the full hierarchy is refit. Each replicate
level is then anchored to the full-sample solution before its edges are
computed. That is, its factors are matched (greedy max-|r| with removal)
and sign-oriented against the full-sample factors, on the full-sample
correlation matrix. Without anchoring, factor label switching and sign
flipping across replicates would corrupt the pooled edge distributions.
This is the same matching machinery comparability() uses.
All resample indices are drawn upfront from seed, so results are
reproducible and identical whether replicates run serially or in parallel.
Replicate fits are dispatched through future.apply when it is
installed and the user has set a future::plan(). Otherwise they run
serially, as in the ESEM (exploratory structural equation modeling) engine
of ackwards().
What the intervals do and do not fix
Per-edge intervals make sampling uncertainty visible: an edge whose
interval straddles prune()'s redundancy_r threshold should not be
treated as decisively above or below it. They do not correct the
selection bias of scanning many edges for the strongest one. The maximum
of hundreds of correlations capitalizes on chance even when every
individual interval is honest. Treat the intervals as per-edge error bars,
not a familywise inference.
Failed replicates
A replicate whose hierarchy fails to converge (in full or at some levels)
contributes NA to the affected edges. It is dropped from their
distributions, because convergence is data, not an error. The usable
replicate count is reported per edge in n_boot_ok, and a message
summarises any
shortfall.
References
Efron, B., & Tibshirani, R. J. (1993). An introduction to the bootstrap. Chapman & Hall.
Forbes, M. K. (2023). Improving hierarchical models of individual differences: An extension of Goldberg's bass-ackward method. Psychological Methods. doi:10.1037/met0000546
See also
Use prune() for the thresholded rules the intervals
contextualise. See comparability() for split-half replicability of the
factors themselves, where the sample is split into two random halves and
each half is analysed separately. See tidy.ackwards() for the augmented
edge table.
Examples
# \donttest{
x <- ackwards(sim16, k_max = 3)
x <- boot_edges(x, sim16, n_boot = 100, seed = 1)
#> ℹ Fitting 100 bootstrap replicates (pca, k = 1-3)...
#> ✔ Fitting 100 bootstrap replicates (pca, k = 1-3)... [1.8s]
#>
x$boot$edges
#> from to level_from level_to r se lo hi
#> 1 m1f1 m2f1 1 2 0.70729611 0.03334587 0.62894118 0.755307440
#> 2 m1f1 m2f2 1 2 0.70691740 0.03221841 0.65534452 0.777438710
#> 3 m2f1 m3f1 2 3 -0.01134239 0.02483636 -0.08601120 0.007369852
#> 4 m2f1 m3f2 2 3 0.69709298 0.20160298 0.03830045 0.734809599
#> 5 m2f1 m3f3 2 3 0.71689101 0.09283102 0.67793763 0.998542647
#> 6 m2f2 m3f1 2 3 0.99559323 0.09091406 0.69647708 0.999880140
#> 7 m2f2 m3f2 2 3 0.07461577 0.20966388 -0.01269972 0.717035306
#> 8 m2f2 m3f3 2 3 -0.05680322 0.04384198 -0.12671309 0.029286309
#> n_boot_ok
#> 1 100
#> 2 100
#> 3 100
#> 4 100
#> 5 100
#> 6 100
#> 7 100
#> 8 100
head(tidy(x)) # now carries se / lo / hi
#> from to level_from level_to r beta is_primary above_cut
#> 1 m1f1 m2f1 1 2 0.70729611 0.70729611 TRUE TRUE
#> 2 m1f1 m2f2 1 2 0.70691740 0.70691740 TRUE TRUE
#> 3 m2f1 m3f1 2 3 -0.01134239 -0.01134239 FALSE FALSE
#> 4 m2f1 m3f2 2 3 0.69709298 0.69709298 TRUE TRUE
#> 5 m2f1 m3f3 2 3 0.71689101 0.71689101 TRUE TRUE
#> 6 m2f2 m3f1 2 3 0.99559323 0.99559323 TRUE TRUE
#> se lo hi n_boot_ok
#> 1 0.03334587 0.62894118 0.755307440 100
#> 2 0.03221841 0.65534452 0.777438710 100
#> 3 0.02483636 -0.08601120 0.007369852 100
#> 4 0.20160298 0.03830045 0.734809599 100
#> 5 0.09283102 0.67793763 0.998542647 100
#> 6 0.09091406 0.69647708 0.999880140 100
# }
