Skip to contents

Given a species-by-species trait distance matrix (e.g., Gower), this function extracts the invader × resident block of distances \(d_{ij}\) and transforms it to a competition coefficient matrix \(a_{ij}\) using a Gaussian kernel: $$a_{ij} = \exp\!\left\{ - \frac{d_{ij}^2}{2\,\sigma_t^2} \right\}.$$

The kernel bandwidth \(\sigma_t\) controls how quickly competition decays with trait difference. By default it is estimated from the resident-resident distances, so the decay reflects the realised dispersion of the resident pool.

Usage

compute_competition_kernel(
  g_all,
  residents,
  invaders = NULL,
  sigma_t = NULL,
  sigma_method = c("sd", "median", "iqr"),
  eps = 1e-08
)

Arguments

g_all

matrix. Symmetric species × species trait distance matrix with row/column names as species IDs (e.g., from Gower).

residents

character. Vector of resident species IDs (must be in rownames(g_all)).

invaders

NULL or character. Vector of invader species IDs. If NULL, defaults to all species in g_all that are not in residents.

sigma_t

NULL or numeric. Kernel bandwidth. If NULL, estimated from the upper triangle of the resident-resident distances using sigma_method.

sigma_method

character. How to estimate \(\sigma_t\) when missing; one of c("sd","median","iqr"). Default "sd".

eps

numeric. Tiny positive value used if the estimated \(\sigma_t\) is zero; default 1e-8.

Value

A list with:

  • d_ij (n_inv × n_res): invader-resident distance block (from g_all).

  • a_ij (n_inv × n_res): competition coefficients (Gaussian kernel of distances \(d_{ij}\)).

  • sigma_t: bandwidth used.

  • meta: list with estimation method and counts of invaders/residents.

Details

  • Use a distance matrix for g_all (not similarity). For Gower, distances are typically in 0, 1.

  • Estimating \(\sigma_t\) from residents makes the kernel scale data-driven and comparable across analyses.

  • If you prefer a fixed ecological scale, pass sigma_t explicitly (e.g., a trait threshold of interest).

Examples

# --- Simulate a toy distance matrix (no external packages) ---
set.seed(42)
spp <- paste0("sp_", 1:8)
traits <- data.frame(
  t1 = rnorm(length(spp)),
  t2 = runif(length(spp))
)

# Euclidean distances on simulated traits, scaled to [0, 1]
g_all <- as.matrix(stats::dist(traits, method = "euclidean"))
g_all <- g_all / max(g_all)                 # scale to [0,1]
rownames(g_all) <- colnames(g_all) <- spp

# Define residents and invaders
residents <- spp[1:5]
invaders  <- spp[6:8]

# Compute competition kernel (sigma_t estimated from resident–resident distances)
comp <- compute_competition_kernel(
  g_all     = g_all,
  residents = residents,
  invaders  = invaders,
  sigma_method = "sd"
)

# Inspect results
str(comp$a_ij)           # (invaders × residents) competition coefficients
#>  num [1:3, 1:5] 0.006808 0.966233 0.024361 0.694695 0.000156 ...
#>  - attr(*, "dimnames")=List of 2
#>   ..$ : chr [1:3] "sp_6" "sp_7" "sp_8"
#>   ..$ : chr [1:5] "sp_1" "sp_2" "sp_3" "sp_4" ...
comp$sigma_t             # bandwidth used
#> [1] 0.2388547

# Same call without providing invaders (uses complement of residents)
comp2 <- compute_competition_kernel(g_all, residents = residents)