Rao's quadratic entropy Q: expected trait dissimilarity between two randomly selected individuals. Decomposes into alpha and beta components.
rao_entropy <- function(comm, dist_traits) {
if (!requireNamespace("FD", quietly = TRUE)) install.packages("FD")
sp <- intersect(colnames(comm), labels(dist_traits))
comm <- comm[, sp]
D <- as.matrix(dist_traits)[sp, sp]
# Row-normalise
p <- sweep(comm, 1, rowSums(comm), "/")
# Rao Q = sum_ij p_i * p_j * d_ij
Q <- apply(p, 1, function(pi) as.numeric(pi %*% D %*% pi))
data.frame(site = rownames(comm), Rao_Q = Q)
}
# ── Example ──────────────────────────────────────────────────────
set.seed(42)
n_sp <- 20
traits <- matrix(rnorm(80), n_sp, 4)
rownames(traits) <- paste0("sp", 1:n_sp)
d_traits <- dist(traits)
comm <- matrix(rbinom(60, 1, 0.5), 3, n_sp,
dimnames = list(c("A","B","C"), paste0("sp", 1:n_sp)))
rao_entropy(comm, d_traits)