
Per-trait proportion-of-variance decomposition across all model components
Source:R/extract-omega.R
extract_proportions.RdFor each trait, returns the proportion of total latent variance attributable to each component present in the model: shared (rr) and unique (diag) at each tier (unit, unit_obs, phy), diagonal cluster / cluster2 components when present, plus optionally the binomial link's implicit residual.
Arguments
- fit
A fit returned by
gllvmTMB().- link_residual
For non-Gaussian fits:
"auto"(default) adds the link's implicit residual as its own per-trait component (e.g. \(\pi^2/3\) for binomial logit, \(\log(1 + 1/\hat\mu_t)\) for Poisson log; see "Family-aware link residuals" inextract_Sigma()for the full per-family table). Mixed-family fits get the residual implied by each trait's family/link."none"omits the link-implicit component.- format
"long"(default) returns a tibble-like data frame with one row per (trait, component);"wide"returns one row per trait with one column per component.
Value
Long format: data frame with columns trait, component
(e.g. "shared_unit", "unique_unit", "shared_unit_obs",
"unique_unit_obs", "unique_phy", "shared_phy", "unique_cluster",
"unique_cluster2", "link_residual"),
variance (the absolute variance), proportion (the share of
the total). Wide format: data frame with one column per component
plus a total_variance column; the per-trait proportions sum to 1.
OLRE interpretation: for fits with a genuine observation-level
diagonal term, usually written as per-row indep() in new code (see
extract_residual_split()), the unique_unit_obs component is
\(\sigma^2_e\) (the estimated OLRE variance) and the link_residual
component is \(\sigma^2_d\) (the distribution-specific latent residual).
Details
This is the most general proportion-decomposition function in the
package. extract_phylo_signal() is the focused PGLLVM
\(H^2 / C^2_\text{non} / \psi^2\) convenience wrapper for the
species-level case; extract_communality() gives the rr-only
"shared" proportion at one tier; extract_ICC_site() gives the
between-vs-within proportion. extract_proportions() returns all of
these in one tidy frame.
Structured trait-intercept rho fits are excluded because this source-
allocation summary does not account for attenuation. Use extract_Sigma()
and its source_strength metadata.
See also
extract_phylo_signal() — the PGLLVM-specific shortcut;
extract_communality(); extract_ICC_site();
extract_residual_split() — explicit \(\sigma^2_d / \sigma^2_e\)
decomposition for OLRE fits.
Examples
set.seed(3)
## Simulate 4 traits recorded on a few species at each of 50 sites, with
## trait variation at two tiers: between sites (the "unit" tier) and
## between species records within a site (the "unit_obs" tier). A zero
## beta matrix turns off the simulator's environmental effects, which
## this model does not include.
sim <- simulate_site_trait(
n_sites = 50, n_species = 10, n_traits = 4,
mean_species_per_site = 3,
beta = matrix(0, 4, 2),
Lambda_B = matrix(c(0.8, 0.6, -0.5, 0.4), 4, 1),
psi_B = rep(0.3, 4),
Lambda_W = matrix(c(0.5, -0.4, 0.4, 0.3), 4, 1),
sigma2_eps = 0.3
)
## One latent factor plus trait-specific variances at each tier. Each
## species record has one value per trait, so the within-site
## trait-specific variances also absorb the measurement noise
## (gllvmTMB prints a note saying so).
fit <- gllvmTMB(
value ~ 0 + trait +
latent(0 + trait | site, d = 1, unique = TRUE) +
latent(0 + trait | site_species, d = 1, unique = TRUE),
data = sim$data,
trait = "trait",
unit = "site",
unit_obs = "site_species"
)
#> ℹ Auto-suppressing `sigma_eps`: `indep(0 + trait | site_species)` is at the
#> per-row level, so it already absorbs the observation residual.
#> • Fixed at 0.00122 (~1/1000 of sd(y)) to keep the Gaussian density
#> well-defined; the row-level residual variance is fully captured by the
#> per-row diagonal term.
## Each trait's variance split into components (shared and
## trait-specific, at each tier): one row per trait and component,
## with the variance and its share of the trait's total
extract_proportions(fit)
#> trait component variance proportion
#> 1 trait_1 shared_unit 0.69621687 0.47099863
#> 2 trait_2 shared_unit 0.32072421 0.28757834
#> 3 trait_3 shared_unit 0.30488801 0.30184502
#> 4 trait_4 shared_unit 0.07463678 0.08036782
#> 5 trait_1 unique_unit 0.37855037 0.25609363
#> 6 trait_2 unique_unit 0.41129712 0.36879081
#> 7 trait_3 unique_unit 0.32569315 0.32244251
#> 8 trait_4 unique_unit 0.46545928 0.50119991
#> 9 trait_1 shared_unit_obs 0.12609026 0.08530149
#> 10 trait_2 shared_unit_obs 0.11717010 0.10506093
#> 11 trait_3 shared_unit_obs 0.10806933 0.10699073
#> 12 trait_4 shared_unit_obs 0.14009496 0.15085225
#> 13 trait_1 unique_unit_obs 0.27731427 0.18760625
#> 14 trait_2 unique_unit_obs 0.26606716 0.23856992
#> 15 trait_3 unique_unit_obs 0.27143082 0.26872175
#> 16 trait_4 unique_unit_obs 0.24849886 0.26758002
## The same shares with one row per trait and one column per component;
## each row of proportions sums to 1
extract_proportions(fit, format = "wide")
#> trait shared_unit unique_unit shared_unit_obs unique_unit_obs
#> trait_1 trait_1 0.47099863 0.2560936 0.08530149 0.1876063
#> trait_2 trait_2 0.28757834 0.3687908 0.10506093 0.2385699
#> trait_3 trait_3 0.30184502 0.3224425 0.10699073 0.2687217
#> trait_4 trait_4 0.08036782 0.5011999 0.15085225 0.2675800
#> total_variance
#> trait_1 1.4781718
#> trait_2 1.1152586
#> trait_3 1.0100813
#> trait_4 0.9286899