nullcat provides null model algorithms for categorical and
quantitative community ecology data. It extends classic binary null
models (e.g., curveball, swap) to work with categorical data, and
introduces a stratified randomization framework for continuous data that
addresses limitations in existing methods for randomizing quantitative
and count data.
Installation
# Install stable version from CRAN: install.packages("nullcat") # Or dev version from GitHub: # install.packages("remotes") remotes::install_github("matthewkling/nullcat")
Quick start
Categorical null models
Generalize binary null models to matrices where cells contain integers representing discrete categories:
library(nullcat) # Create a categorical matrix set.seed(123) cat_matrix <- matrix(sample(1:4, 20*10, replace = TRUE), nrow = 20) # Randomize using curvecat (preserves row & column category multisets) randomized <- curvecat(cat_matrix, n_iter = 1000) # Verify margins are preserved all.equal(sort(cat_matrix[1,]), sort(randomized[1,])) #> [1] TRUE all.equal(sort(cat_matrix[,1]), sort(randomized[,1])) #> [1] TRUE
Available algorithms: curvecat(), swapcat(), tswapcat(),
r0cat(), c0cat()
Quantitative null models
Apply stratified randomization to continuous community data:
# Create a quantitative community matrix set.seed(456) comm <- matrix(rexp(50 * 30, rate = 0.5), nrow = 50) # Stratified randomization with 5 strata rand1 <- quantize(comm, n_strata = 5, n_iter = 2000) # Preserve row value multisets (row sums maintained) rand2 <- quantize(comm, n_strata = 5, fixed = "row", n_iter = 2000) all.equal(rowSums(comm), rowSums(rand2)) #> [1] TRUE
Spatially constrained null models
Weight pair selection by spatial proximity, trait similarity, or any pairwise measure:
set.seed(789) x <- matrix(sample(1:4, 200, replace = TRUE), nrow = 20) # Site coordinates and distance-decay weights coords <- cbind(runif(20), runif(20)) W <- exp(-as.matrix(dist(coords)) / 0.3) # Nearby sites exchange tokens more frequently x_spatial <- curvecat(x, n_iter = 2000, wt_row = W) # Weight both margins simultaneously (Gibbs-like alternating) W_col <- exp(-as.matrix(dist(cbind(runif(10), runif(10)))) / 0.3) x_dual <- curvecat(x, n_iter = 2000, wt_row = W, wt_col = W_col)
Learn more
See vignette("nullcat") for comprehensive documentation including:
- Categorical null model algorithms and their constraints
- Quantitative null model workflow and stratification options
- Spatially and trait-constrained randomization via weighted pair sampling
- Convergence diagnostics and burn-in estimation
- Efficient batch generation of null distributions
- Integration with the vegan package
Package website: https://matthewkling.github.io/nullcat/
Report issues: https://github.com/matthewkling/nullcat/issues