Skip to contents

compute_invasion_fitness() evaluates the invasion-fitness surface \(\lambda_{is}\) over sites (\(s\)) and invaders (\(i\)) using the three standardized predictors:

  • Abiotic suitability \(r^{(z)}_{is}\) (alignment between invader traits and local environment),

  • Niche crowding \(C^{(z)}_{is}\) (overlap with resident trait space weighted by composition),

  • Resident competition \(S^{(z)}_{is}\) (site-only saturation).

It supports five published/useful variants: A: \(\gamma=1\), B: global \(\theta_0\), C: trait-varying \(\theta_i\), D: site-varying \(\Gamma_{is}\) and \(\alpha_{is}\), E: signed \(S\) effect. Optionally, it calibrates an offset \(\kappa\) so the mean resident \(\lambda\) is approximately zero on the same scale (when resident standardized matrices are supplied).

Usage

compute_invasion_fitness(
  r_is_z,
  C_is_z,
  S_is_z,
  option = c("A", "B", "C", "D", "E"),
  alpha_i = NULL,
  beta_i = NULL,
  theta0 = 1,
  theta_i = NULL,
  Gamma_is = NULL,
  alpha_is = NULL,
  beta_signed_i = NULL,
  calibrate_kappa = FALSE,
  r_js_z = NULL,
  C_js_z = NULL,
  S_js_z = NULL,
  Q_res = NULL,
  a0 = NULL,
  a1 = NULL,
  a2 = NULL,
  b0 = NULL,
  b1 = NULL,
  b2 = NULL,
  site_df = NULL,
  return_long = TRUE,
  label = NULL
)

Arguments

r_is_z

Matrix \(S \times I\) of standardized abiotic suitability for invaders. Row names are site IDs; column names are invader IDs.

C_is_z

Matrix \(S \times I\) of standardized niche crowding for invaders.

S_is_z

Matrix \(S \times I\) of standardized site saturation for invaders (site-only; same value down each site row).

option

Character, one of c("A","B","C","D","E"). See Details.

alpha_i

Optional named numeric vector (length \(I\)) of invader crowding sensitivities \(\alpha_i\). Required for A–C and E; ignored if alpha_is is provided in D.

beta_i

Optional named numeric vector (length \(I\)) of saturation sensitivities \(\beta_i\). Used in A–D. For E, use beta_signed_i for a signed effect.

theta0

Numeric scalar global slope for \(r^{(z)}\) (Option B; default 1).

theta_i

Optional named numeric vector (length \(I\)) of trait-varying slopes for \(r^{(z)}\) (Option C).

Gamma_is

Optional matrix \(S \times I\) of site-varying slopes for \(r^{(z)}\) (Option D). If NULL, falls back to theta_i or theta0 as available.

alpha_is

Optional matrix \(S \times I\) of site-varying penalties for crowding (Option D). If NULL, falls back to broadcasting alpha_i.

beta_signed_i

Optional named numeric vector (length \(I\)) providing a signed \(\beta\) for Option E (facilitation allowed when \(\beta<0\)).

calibrate_kappa

Logical; if TRUE, compute \(\kappa\) from residents so that the mean resident \(\lambda\) is ~0 on the same scale (see below).

r_js_z, C_js_z, S_js_z

Optional resident standardized matrices (site \(\times\) resident), required only when calibrate_kappa = TRUE.

Q_res

Optional data frame of resident trait-plane scores with columns tr1, tr2 and rownames = resident IDs (only needed for \(\kappa\) if you want to derive resident analogs \(\alpha_j\), \(\beta_j\) from trait slopes).

a0, a1, a2, b0, b1, b2

Optional numeric scalars: coefficients for resident analog slopes \(\text{slope}_C = a_0 + a_1\,tr1 + a_2\,tr2\) and \(\text{slope}_S = b_0 + b_1\,tr1 + b_2\,tr2\). Used only when calibrate_kappa=TRUE and Q_res provided.

site_df

Optional site table with columns site, x, y used to enrich the tidy output when return_long=TRUE.

return_long

Logical; if TRUE, returns a tidy table with predictors and coefficients.

label

Optional character to tag the option in the tidy output; defaults to a descriptive name per option (e.g., "Option A (γ=1)").

Value

A list with:

  • lambda_is — matrix \(S \times I\) of invasion fitness,

  • GI — the \(\gamma\) used (vector length \(I\) or matrix \(S \times I\)),

  • AI — the \(\alpha\) used (vector length \(I\) or matrix \(S \times I\)),

  • BI — the \(\beta\) used (vector length \(I\)),

  • kappa — numeric calibration offset,

  • option — option label,

  • lambda_long — tidy tibble (if return_long=TRUE).

Details

Compute invasion fitness (five options) with optional resident calibration

Options A: \(\lambda_{is} = 1\cdot r^{(z)}_{is} - \alpha_i C^{(z)}_{is} - \beta_i S^{(z)}_{is} + \kappa\) B: \(\lambda_{is} = \theta_0 r^{(z)}_{is} - \alpha_i C^{(z)}_{is} - \beta_i S^{(z)}_{is} + \kappa\) C: \(\lambda_{is} = \theta_i r^{(z)}_{is} - \alpha_i C^{(z)}_{is} - \beta_i S^{(z)}_{is} + \kappa\) D: \(\lambda_{is} = \Gamma_{is} r^{(z)}_{is} - \alpha_{is} C^{(z)}_{is} - \beta_i S^{(z)}_{is} + \kappa\) E: \(\lambda_{is} = \theta_0 r^{(z)}_{is} - \alpha_i C^{(z)}_{is} + \beta^{(\mathrm{signed})}_i S^{(z)}_{is} + \kappa\)

Resident calibration (\(\kappa\)). When calibrate_kappa=TRUE, the function computes resident analog penalties \(\alpha_j,\beta_j\) from Q_res and slopes {a0,a1,a2,b0,b1,b2}, builds resident matrices AJ, BJ, evaluates \(\lambda^{(\mathrm{res})}_{js} = \theta_0 r^{(z)}_{js} - \alpha_j C^{(z)}_{js} - \beta_j S^{(z)}_{js}\), then sets \(\kappa = -\mathrm{mean}(\lambda^{(\mathrm{res})}_{js})\) (na-rm), keeping residents and invaders on the same scale.

Examples

# Minimal reproducible example (toy shapes only)
S = 5; I = 3
set.seed(1)
r_is_z = matrix(rnorm(S*I),  S, I, dimnames=list(paste0("s",1:S), paste0("i",1:I)))
C_is_z = matrix(rnorm(S*I),  S, I, dimnames=dimnames(r_is_z))
S_is_z = matrix(rep(scale(rnorm(S)), each=I), S, I, dimnames=dimnames(r_is_z)) # site-only broadcast
alpha_i = setNames(runif(ncol(r_is_z), 0.2, 1.0), colnames(r_is_z))
beta_i  = setNames(runif(ncol(r_is_z), 0.1, 0.5), colnames(r_is_z))

# Option A (γ=1, κ=0)
outA = compute_invasion_fitness(r_is_z, C_is_z, S_is_z,
                                 option="A", alpha_i=alpha_i, beta_i=beta_i,
                                 theta0=1, return_long=FALSE)

# Option B (γ = θ0)
outB = compute_invasion_fitness(r_is_z, C_is_z, S_is_z,
                                 option="B", alpha_i=alpha_i, beta_i=beta_i,
                                 theta0=0.8, return_long=FALSE)

# Option C (γ_i = θ_i) — use I = ncol(r_is_z) to avoid length/name mismatch
I = ncol(r_is_z)
theta_i = setNames(runif(I, 0.5, 1.2), colnames(r_is_z))
outC = compute_invasion_fitness(r_is_z, C_is_z, S_is_z,
                                 option="C", alpha_i=alpha_i, beta_i=beta_i,
                                 theta_i=theta_i, return_long=FALSE)

# Option D (site-varying Γ_is and α_is)
Gamma_is = matrix(rep(theta_i, each=nrow(r_is_z)), nrow=nrow(r_is_z), dimnames=dimnames(r_is_z))
alpha_is = pmax(0, matrix(rep(alpha_i, each=nrow(r_is_z)), nrow=nrow(r_is_z),
                           dimnames=dimnames(r_is_z)) + matrix(rnorm(prod(dim(r_is_z)), 0, 0.1),
                                                               nrow=nrow(r_is_z)))
outD = compute_invasion_fitness(r_is_z, C_is_z, S_is_z,
                                 option="D", alpha_is=alpha_is, beta_i=beta_i,
                                 Gamma_is=Gamma_is, return_long=FALSE)
#> Error in compute_invasion_fitness(r_is_z, C_is_z, S_is_z, option = "D",     alpha_is = alpha_is, beta_i = beta_i, Gamma_is = Gamma_is,     return_long = FALSE): identical(dim(alpha_is), dim(r_is_z)) is not TRUE

# Option E (signed S effect)
beta_signed_i = setNames(rnorm(ncol(r_is_z), 0, 0.3), colnames(r_is_z))
outE = compute_invasion_fitness(r_is_z, C_is_z, S_is_z,
                                 option="E", alpha_i=alpha_i, beta_signed_i=beta_signed_i,
                                 theta0=1, return_long=FALSE)