This walk-through shows how to:
plsc()),The workflow is intentionally small and fast so the vignette runs quickly; for real analyses, increase the number of permutations/bootstraps.
n <- 80 # subjects
pX <- 8 # brain/features
pY <- 5 # behavior
d <- 2 # true latent dimensions
# orthonormal loadings
Vx_true <- qr.Q(qr(matrix(rnorm(pX * d), pX, d)))
Vy_true <- qr.Q(qr(matrix(rnorm(pY * d), pY, d)))
F_scores <- matrix(rnorm(n * d), n, d) # latent scores
noise <- 0.10
X <- F_scores %*% t(Vx_true) + noise * matrix(rnorm(n * pX), n, pX)
Y <- F_scores %*% t(Vy_true) + noise * matrix(rnorm(n * pY), n, pY)scores_df <- data.frame(
LV1_x = scores(fit_plsc, "X")[, 1],
LV1_y = scores(fit_plsc, "Y")[, 1],
LV2_x = scores(fit_plsc, "X")[, 2],
LV2_y = scores(fit_plsc, "Y")[, 2]
)
ggplot(scores_df, aes(x = LV1_y, y = LV1_x)) +
geom_point(alpha = 0.7) +
geom_smooth(method = "lm", se = FALSE, color = "firebrick") +
labs(x = "Behavior scores (LV1)", y = "Brain scores (LV1)",
title = "Score association for LV1") +
theme_minimal()
#> `geom_smooth()` using formula = 'y ~ x'Shuffle rows of Y to break the X–Y link and build an
empirical null for the singular values.
set.seed(123)
pt <- perm_test(fit_plsc, X, Y, nperm = 199, comps = 3, parallel = FALSE)
pt$component_results
#> # A tibble: 3 × 5
#> comp observed pval lower_ci upper_ci
#> <int> <dbl> <dbl> <dbl> <dbl>
#> 1 1 4.16 0.005 0.269 1.07
#> 2 2 1.76 0.005 0.0819 0.509
#> 3 3 0.0283 0.205 0.0140 0.0396
cat("Sequential n_significant (alpha = 0.05):", pt$n_significant, "\n")
#> Sequential n_significant (alpha = 0.05): 2Bootstrap resamples subjects, re-fits PLSC, sign-aligns loadings, and
reports mean/SD (ratio ≈ Z).
Here we keep it light for the vignette; use ≥500–1000 in practice.
set.seed(321)
boot_plsc <- bootstrap(fit_plsc, nboot = 120, X = X, Y = Y, comps = 2, parallel = FALSE)
# X-loadings bootstrap ratios for LV1
df_bsr <- data.frame(
variable = paste0("x", seq_len(pX)),
bsr = boot_plsc$z_vx[, 1]
)
ggplot(df_bsr, aes(x = reorder(variable, bsr), y = bsr)) +
geom_hline(yintercept = c(-2, 2), linetype = "dashed", color = "grey50") +
geom_col(fill = "#1f78b4") +
coord_flip() +
labs(x = NULL, y = "Bootstrap ratio (X loadings, LV1)",
title = "Stable variables exceed |BSR| ≈ 2") +
theme_minimal()Do the same for Y loadings if needed:
standardize() to run PLSC on correlation scale
(default here); switch to center() for covariance
scale.nperm (e.g., 999) and nboot
(≥500) for publication-grade inference.boot_plsc$z_vx.