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] TRUEAvailable 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] TRUESpatially constrained null models
Randomize within groups of sites, e.g. regions, or a different random tiling of space in each replicate:
set.seed(789)
x <- matrix(sample(1:4, 600, replace = TRUE), nrow = 60)
# Fixed regions: each region keeps its own species pool
region <- rep(1:3, each = 20)
x_reg <- curvecat(x, n_iter = 1000, row_groups = region)
# Random hexagonal tilings (one per replicate) pool each site with its neighbors
coords <- cbind(runif(60, 0, 10), runif(60, 0, 10))
tiles <- tile_groups(coords, spacing = 4, n = 99, lonlat = FALSE)
sims <- nullcat_batch(x, n_reps = 99, row_groups = tiles, n_iter = 500)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 taxonomically constrained randomization within groups and random tilings
- 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
